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 817c1836e0..d5f29894fc 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-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -88,6 +88,7 @@ * @ACTION_OUI_SWITCH_TO_11N_MODE: connect in 11n * @ACTION_OUI_CONNECT_1X1_WITH_1_CHAIN: connect in 1x1 & disable diversity gain * @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_MAXIMUM_ID: maximun number of action oui types */ enum action_oui_id { @@ -98,6 +99,7 @@ enum action_oui_id { ACTION_OUI_SWITCH_TO_11N_MODE = 4, ACTION_OUI_CONNECT_1X1_WITH_1_CHAIN = 5, ACTION_OUI_DISABLE_AGGRESSIVE_TX = 6, + ACTION_OUI_FORCE_MAX_NSS = 7, ACTION_OUI_MAXIMUM_ID }; diff --git a/core/hdd/inc/hdd_config.h b/core/hdd/inc/hdd_config.h index ccfbe7649b..326ae24d51 100644 --- a/core/hdd/inc/hdd_config.h +++ b/core/hdd/inc/hdd_config.h @@ -1336,6 +1336,43 @@ enum host_log_level { "", \ "Set modulized host debug log level") +/* + * + * gActionOUIForceMaxNss - Used to specify action OUIs for Max NSS connection + * @Default: + * Note: User should strictly add new action OUIs at the end of this + * default value. + * + * Default OUIs: (All values in Hex) + * OUI 1 :001018 + * OUI data Len : 06 + * OUI Data : 0201009c0000 + * OUI data Mask: FC + * Info Mask : 01 - only OUI present in Info mask + * OUI 2 :001018 + * OUI data Len : 06 + * OUI Data : 0201001c0000 + * OUI data Mask: FC + * Info Mask : 01 - only OUI present in Info mask + * + * This ini is used to specify the AP OUIs with which max capability is + * sent in association request even though AP advertises 1x1 capability. + * + * Related: None + * + * Supported Feature: Action OUIs + * + * Usage: External + * + * + */ +#define CFG_ACTION_OUI_FORCE_MAX_NSS CFG_INI_STRING( \ + "gActionOUIForceMaxNss", \ + 0, \ + ACTION_OUI_MAX_STR_LEN, \ + "001018 06 0201009c0000 FC 01 001018 06 0201001c0000 FC 01", \ + "Used to specify action OUIs for forcing max NSS connection") + #define CFG_HDD_ALL \ CFG_ENABLE_PACKET_LOG_ALL \ CFG_ENABLE_RUNTIME_PM_ALL \ @@ -1348,6 +1385,7 @@ enum host_log_level { CFG(CFG_ACTION_OUI_ITO_ALTERNATE) \ CFG(CFG_ACTION_OUI_ITO_EXTENSION) \ CFG(CFG_ACTION_OUI_DISABLE_AGGRESSIVE_TX) \ + CFG(CFG_ACTION_OUI_FORCE_MAX_NSS) \ CFG(CFG_ACTION_OUI_SWITCH_TO_11N_MODE) \ CFG(CFG_ADVERTISE_CONCURRENT_OPERATION) \ CFG(CFG_BUG_ON_REINIT_FAILURE) \ diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 75b7701f78..b938b71526 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -9513,6 +9513,9 @@ static void hdd_cfg_params_init(struct hdd_context *hdd_ctx) cfg_get(psoc, CFG_ACTION_OUI_DISABLE_AGGRESSIVE_TX), ACTION_OUI_MAX_STR_LEN); + qdf_str_lcopy(config->action_oui_str[ACTION_OUI_FORCE_MAX_NSS], + cfg_get(psoc, CFG_ACTION_OUI_FORCE_MAX_NSS), + ACTION_OUI_MAX_STR_LEN); config->enable_rtt_support = cfg_get(psoc, CFG_ENABLE_RTT_SUPPORT); config->is_unit_test_framework_enabled = cfg_get(psoc, CFG_ENABLE_UNIT_TEST_FRAMEWORK); diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h index 0d7f4df7cb..77b709f2ed 100644 --- a/core/mac/src/include/parser_api.h +++ b/core/mac/src/include/parser_api.h @@ -56,6 +56,8 @@ #define NSS_1x1_MODE 1 #define NSS_2x2_MODE 2 +#define NSS_3x3_MODE 3 +#define NSS_4x4_MODE 4 #define MBO_IE_ASSOC_DISALLOWED_SUBATTR_ID 0x04 /* QCN IE definitions */ diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index 931a399900..4f98d3fff3 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -510,6 +510,39 @@ lim_handle_assoc_reject_status(struct mac_context *mac_ctx, } #endif +/** + * lim_get_nss_supported_by_ap() - finds out nss from AP's beacons + * @vht_caps: VHT capabilities + * @ht_caps: HT capabilities + * + * Return: nss advertised by AP in beacon + */ +static uint8_t lim_get_nss_supported_by_ap(tDot11fIEVHTCaps *vht_caps, + tDot11fIEHTCaps *ht_caps) +{ + if (vht_caps->present) { + if ((vht_caps->rxMCSMap & 0xC0) != 0xC0) + return NSS_4x4_MODE; + + if ((vht_caps->rxMCSMap & 0x30) != 0x30) + return NSS_3x3_MODE; + + if ((vht_caps->rxMCSMap & 0x0C) != 0x0C) + return NSS_2x2_MODE; + } else if (ht_caps->present) { + if (ht_caps->supportedMCSSet[3]) + return NSS_4x4_MODE; + + if (ht_caps->supportedMCSSet[2]) + return NSS_3x3_MODE; + + if (ht_caps->supportedMCSSet[1]) + return NSS_2x2_MODE; + } + + return NSS_1x1_MODE; +} + /** * lim_process_assoc_rsp_frame() - Processes assoc response * @mac_ctx: Pointer to Global MAC structure @@ -541,6 +574,8 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t sme_sessionid = 0; struct csr_roam_session *roam_session; #endif + uint8_t ap_nss; + /* Initialize status code to success. */ if (lim_is_roam_synch_in_progress(session_entry)) hdr = (tpSirMacMgmtHdr) mac_ctx->roam.pReassocResp; @@ -842,6 +877,9 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, session_entry, assoc_rsp->statusCode ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS, assoc_rsp->statusCode); + ap_nss = lim_get_nss_supported_by_ap(&assoc_rsp->VHTCaps, + &assoc_rsp->HTCaps); + if (subtype == LIM_REASSOC) { pe_debug("Successfully Reassociated with BSS"); #ifdef FEATURE_WLAN_ESE @@ -877,6 +915,14 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, session_entry, false); goto assocReject; } + + if (ap_nss < session_entry->nss) { + session_entry->nss = ap_nss; + lim_objmgr_update_vdev_nss(mac_ctx->psoc, + session_entry->smeSessionId, + ap_nss); + } + if ((session_entry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE) || lim_is_roam_synch_in_progress(session_entry)) { @@ -963,6 +1009,13 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, if (lim_search_pre_auth_list(mac_ctx, hdr->sa)) lim_delete_pre_auth_node(mac_ctx, hdr->sa); + if (ap_nss < session_entry->nss) { + session_entry->nss = ap_nss; + lim_objmgr_update_vdev_nss(mac_ctx->psoc, + session_entry->smeSessionId, + ap_nss); + } + lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp, session_entry); /* * Extract the AP capabilities from the beacon that diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c index 4ea020ec6b..c47d919fe0 100644 --- a/core/mac/src/pe/lim/lim_prop_exts_utils.c +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c @@ -159,8 +159,8 @@ static void lim_check_he_ldpc_cap(struct pe_session *session, {} #endif -static void lim_objmgr_update_vdev_nss(struct wlan_objmgr_psoc *psoc, - uint8_t vdev_id, uint8_t nss) +void lim_objmgr_update_vdev_nss(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint8_t nss) { struct wlan_objmgr_vdev *vdev; diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.h b/core/mac/src/pe/lim/lim_prop_exts_utils.h index aeacc91785..d07af6f454 100644 --- a/core/mac/src/pe/lim/lim_prop_exts_utils.h +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.h @@ -56,4 +56,15 @@ lim_extract_ap_capability(struct mac_context *mac_ctx, uint8_t *p_ie, ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode); +/** + * lim_objmgr_update_vdev_nss() - update nss in vdev object + * @psoc: Pointer to Global MAC structure + * @vdev_id: vdev id + * @nss: nss + * + * Return: None + */ +void lim_objmgr_update_vdev_nss(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint8_t nss); + #endif /* __LIM_PROP_EXTS_UTILS_H */ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index f15cbbe35b..2272069efe 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -8785,6 +8785,11 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, #endif } + if (pSmeJoinRsp->nss < session_ptr->nss) { + session_ptr->nss = pSmeJoinRsp->nss; + session_ptr->vdev_nss = pSmeJoinRsp->nss; + } + session_ptr->supported_nss_1x1 = pSmeJoinRsp->supported_nss_1x1; sme_debug("SME session supported nss: %d", @@ -9199,6 +9204,10 @@ static void csr_roam_roaming_state_reassoc_rsp_processor(struct mac_context *mac result = eCsrReassocSuccess; csr_session = CSR_GET_SESSION(mac, pSmeJoinRsp->sessionId); if (csr_session) { + if (pSmeJoinRsp->nss < csr_session->nss) { + csr_session->nss = pSmeJoinRsp->nss; + csr_session->vdev_nss = pSmeJoinRsp->nss; + } csr_session->supported_nss_1x1 = pSmeJoinRsp->supported_nss_1x1; sme_debug("SME session supported nss: %d", @@ -15310,6 +15319,8 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId, tDot11fIEVHTCaps *vht_caps = NULL; bool bvalue = 0; eCsrAuthType akm; + bool force_max_nss; + uint8_t ap_nss; if (!pSession) { sme_err("session %d not found", sessionId); @@ -15414,32 +15425,6 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId, dot11mode = MLME_DOT11_MODE_11N; } - if (IS_5G_CH(pBssDescription->channelId)) - vdev_type_nss = &mac->vdev_type_nss_5g; - else - vdev_type_nss = &mac->vdev_type_nss_2g; - if (pSession->pCurRoamProfile->csrPersona == - QDF_P2P_CLIENT_MODE) - pSession->vdev_nss = vdev_type_nss->p2p_cli; - else - pSession->vdev_nss = vdev_type_nss->sta; - pSession->nss = pSession->vdev_nss; - - if (pSession->nss > csr_get_nss_supported_by_sta_and_ap( - &pIes->VHTCaps, - &pIes->HTCaps, dot11mode)) { - pSession->nss = csr_get_nss_supported_by_sta_and_ap( - &pIes->VHTCaps, &pIes->HTCaps, - dot11mode); - pSession->vdev_nss = pSession->nss; - } - - if (!mac->mlme_cfg->vht_caps.vht_cap_info.enable2x2) - pSession->nss = 1; - - if (pSession->nss == 1) - pSession->supported_nss_1x1 = true; - ieLen = csr_get_ielen_from_bss_description(pBssDescription); /* Dump the Vendor Specific IEs*/ @@ -15461,6 +15446,38 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId, vendor_ap_search_attr.enable_5g = IS_5G_CH(pBssDescription->channelId); + if (IS_5G_CH(pBssDescription->channelId)) + vdev_type_nss = &mac->vdev_type_nss_5g; + else + vdev_type_nss = &mac->vdev_type_nss_2g; + if (pSession->pCurRoamProfile->csrPersona == + QDF_P2P_CLIENT_MODE) + pSession->vdev_nss = vdev_type_nss->p2p_cli; + else + pSession->vdev_nss = vdev_type_nss->sta; + pSession->nss = pSession->vdev_nss; + + force_max_nss = ucfg_action_oui_search(mac->psoc, + &vendor_ap_search_attr, + ACTION_OUI_FORCE_MAX_NSS); + + if (!mac->mlme_cfg->vht_caps.vht_cap_info.enable2x2) { + force_max_nss = false; + pSession->nss = 1; + } + + if (!force_max_nss) + ap_nss = csr_get_nss_supported_by_sta_and_ap( + &pIes->VHTCaps, + &pIes->HTCaps, dot11mode); + if (!force_max_nss && pSession->nss > ap_nss) { + pSession->nss = ap_nss; + pSession->vdev_nss = pSession->nss; + } + + if (pSession->nss == 1) + pSession->supported_nss_1x1 = true; + is_vendor_ap_present = ucfg_action_oui_search(mac->psoc, &vendor_ap_search_attr,