diff --git a/core/mac/src/pe/include/lim_ft.h b/core/mac/src/pe/include/lim_ft.h index f26d5c8c8173..a9803ebb28bb 100644 --- a/core/mac/src/pe/include/lim_ft.h +++ b/core/mac/src/pe/include/lim_ft.h @@ -140,13 +140,15 @@ void lim_fill_ft_session(struct mac_context *mac, struct bss_description *pbssDescription, struct pe_session *ft_session, struct pe_session *pe_session, - enum wlan_phymode bss_phymode); + enum wlan_phymode bss_phymode, + tpSirAssocRsp assoc_rsp); /** * lim_ft_prepare_add_bss_req() - Create Add Bss Req to the new AP * @mac: Global MAC context * @add_bss_params: Bss params including rsp data * @pe_session: PE Session + * @assoc_rsp: assoc response from ap * * This will be used when we are ready to FT to the new AP. * The newly created ft Session entry is passed to this function @@ -155,7 +157,8 @@ void lim_fill_ft_session(struct mac_context *mac, */ void lim_ft_prepare_add_bss_req(struct mac_context *mac, struct pe_session *ft_session, - struct bss_description *bssDescription); + struct bss_description *bssDescription, + tpSirAssocRsp assoc_rsp); QDF_STATUS lim_send_preauth_scan_offload(struct mac_context *mac_ctx, struct pe_session *session_entry, tSirFTPreAuthReq *ft_preauth_req); @@ -164,11 +167,13 @@ static inline void lim_fill_ft_session(struct mac_context *mac, struct bss_description *pbssDescription, struct pe_session *ft_session, struct pe_session *pe_session, - enum wlan_phymode bss_phymode) + enum wlan_phymode bss_phymode, + tpSirAssocRsp assoc_rsp) {} static inline void lim_ft_prepare_add_bss_req(struct mac_context *mac, struct pe_session *ft_session, - struct bss_description *bssDescription) + struct bss_description *bssDescription, + tpSirAssocRsp assoc_rsp) {} #endif diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 35ededa25452..61c81991ce3f 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -2518,6 +2518,64 @@ lim_check_ft_initial_im_association(struct roam_offload_synch_ind *roam_synch, } } +/** + * lim_get_assoc_resp_from_roam_sync() - get assoc response from + * roam sync event + * @mac_ctx: mac context + * @session: pe session + * @roam_sync_ind_ptr: roam sync indication + * + * This function is to get parsed assoc response data + * + * Return: assoc response data struct + */ +static tpSirAssocRsp +lim_get_assoc_resp_from_roam_sync( + struct mac_context *mac_ctx, + struct pe_session *session, + struct roam_offload_synch_ind *roam_sync_ind_ptr) +{ + uint8_t *reassoc_resp; + tpSirAssocRsp assoc_rsp; + uint32_t frame_len; + uint8_t *frm_body; + + if (roam_sync_ind_ptr->reassocRespLength <= SIR_MAC_HDR_LEN_3A) { + pe_warn("invalid roam sync assoc rsp"); + return NULL; + } + reassoc_resp = (uint8_t *)roam_sync_ind_ptr + + roam_sync_ind_ptr->reassocRespOffset + + SIR_MAC_HDR_LEN_3A; + frame_len = roam_sync_ind_ptr->reassocRespLength - SIR_MAC_HDR_LEN_3A; + + assoc_rsp = qdf_mem_malloc(sizeof(*assoc_rsp)); + if (!assoc_rsp) { + pe_warn("err to malloc assoc rsp"); + return NULL; + } + + frm_body = qdf_mem_malloc(frame_len); + if (!frm_body) { + pe_warn("err to malloc assoc rsp body"); + qdf_mem_free(assoc_rsp); + return NULL; + } + qdf_mem_copy(frm_body, reassoc_resp, frame_len); + /* parse Re/Association Response frame. */ + if (sir_convert_assoc_resp_frame2_struct( + mac_ctx, session, frm_body, + frame_len, assoc_rsp) == QDF_STATUS_E_FAILURE) { + pe_err("Parse error Assoc resp length: %d", frame_len); + qdf_mem_free(frm_body); + qdf_mem_free(assoc_rsp); + return NULL; + } + qdf_mem_free(frm_body); + + return assoc_rsp; +} + QDF_STATUS pe_roam_synch_callback(struct mac_context *mac_ctx, struct roam_offload_synch_ind *roam_sync_ind_ptr, @@ -2533,6 +2591,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, struct bss_params *add_bss_params; QDF_STATUS status = QDF_STATUS_E_FAILURE; uint16_t join_rsp_len; + tpSirAssocRsp assoc_rsp; if (!roam_sync_ind_ptr) { pe_err("LFR3:roam_sync_ind_ptr is NULL"); @@ -2622,11 +2681,15 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, ft_session_ptr->csaOffloadEnable = session_ptr->csaOffloadEnable; /* Next routine will update nss and vdev_nss with AP's capabilities */ + assoc_rsp = lim_get_assoc_resp_from_roam_sync( + mac_ctx, ft_session_ptr, roam_sync_ind_ptr); lim_fill_ft_session(mac_ctx, bss_desc, ft_session_ptr, - session_ptr, roam_sync_ind_ptr->phy_mode); + session_ptr, roam_sync_ind_ptr->phy_mode, + assoc_rsp); pe_set_rmf_caps(mac_ctx, ft_session_ptr, roam_sync_ind_ptr); /* Next routine may update nss based on dot11Mode */ - lim_ft_prepare_add_bss_req(mac_ctx, ft_session_ptr, bss_desc); + lim_ft_prepare_add_bss_req(mac_ctx, ft_session_ptr, bss_desc, + assoc_rsp); if (session_ptr->is11Rconnection) lim_fill_fils_ft(session_ptr, ft_session_ptr); @@ -2639,6 +2702,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, if (!curr_sta_ds) { pe_err("LFR3:failed to lookup hash entry"); ft_session_ptr->bRoamSynchInProgress = false; + qdf_mem_free(assoc_rsp); return status; } session_ptr->limSmeState = eLIM_SME_IDLE_STATE; @@ -2655,6 +2719,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, pe_err("LFR3:failed to add hash entry for "QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(add_bss_params->staContext.staMac)); ft_session_ptr->bRoamSynchInProgress = false; + qdf_mem_free(assoc_rsp); return status; } @@ -2694,6 +2759,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, roam_sync_ind_ptr->join_rsp = qdf_mem_malloc(join_rsp_len); if (!roam_sync_ind_ptr->join_rsp) { ft_session_ptr->bRoamSynchInProgress = false; + qdf_mem_free(assoc_rsp); return QDF_STATUS_E_NOMEM; } @@ -2735,6 +2801,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, ft_session_ptr->limSmeState = eLIM_SME_LINK_EST_STATE; ft_session_ptr->limPrevSmeState = ft_session_ptr->limSmeState; ft_session_ptr->bRoamSynchInProgress = false; + qdf_mem_free(assoc_rsp); return QDF_STATUS_SUCCESS; } diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c index e94f2cefe545..0138255706b6 100644 --- a/core/mac/src/pe/lim/lim_ft.c +++ b/core/mac/src/pe/lim/lim_ft.c @@ -114,7 +114,8 @@ void lim_ft_cleanup(struct mac_context *mac, struct pe_session *pe_session) *------------------------------------------------------------------*/ void lim_ft_prepare_add_bss_req(struct mac_context *mac, struct pe_session *ft_session, - struct bss_description *bssDescription) + struct bss_description *bssDescription, + tpSirAssocRsp assoc_rsp) { struct bss_params *pAddBssParams = NULL; tAddStaParams *sta_ctx; @@ -164,6 +165,26 @@ void lim_ft_prepare_add_bss_req(struct mac_context *mac, #ifdef WLAN_FEATURE_11W pAddBssParams->rmfEnabled = ft_session->limRmfEnabled; #endif + if (assoc_rsp && + ft_session->htCapability && pBeaconStruct->HTCaps.present && + assoc_rsp->HTCaps.present) { + /* Some AP have different HT ch width setting in + * beacon/assoc resp. FW uses assoc response to decide + * the bw of HT AP in Roaming sync. + * Here overwrite beacon HT bw setting from assoc + * resp frame to keep sync with FW. + */ + pBeaconStruct->HTCaps.supportedChannelWidthSet = + assoc_rsp->HTCaps.supportedChannelWidthSet; + if (pBeaconStruct->HTInfo.present && + assoc_rsp->HTInfo.present) { + pBeaconStruct->HTInfo.secondaryChannelOffset = + assoc_rsp->HTInfo.secondaryChannelOffset; + pBeaconStruct->HTInfo.recommendedTxWidthSet = + assoc_rsp->HTInfo.recommendedTxWidthSet; + } + } + /* Use the advertised capabilities from the received beacon/PR */ if (IS_DOT11_MODE_HT(ft_session->dot11mode) && (pBeaconStruct->HTCaps.present)) { @@ -506,7 +527,8 @@ void lim_fill_ft_session(struct mac_context *mac, struct bss_description *pbssDescription, struct pe_session *ft_session, struct pe_session *pe_session, - enum wlan_phymode bss_phymode) + enum wlan_phymode bss_phymode, + tpSirAssocRsp assoc_rsp) { uint8_t currentBssUapsd; uint8_t bss_chan_id; @@ -571,6 +593,25 @@ void lim_fill_ft_session(struct mac_context *mac, ft_session->htCapability = (IS_DOT11_MODE_HT(ft_session->dot11mode) && pBeaconStruct->HTCaps.present); + if (assoc_rsp && + ft_session->htCapability && pBeaconStruct->HTCaps.present && + assoc_rsp->HTCaps.present) { + /* Some AP have different HT ch width setting in + * beacon/assoc resp. FW uses assoc response to decide + * the bw of HT AP in Roaming sync. + * Here overwrite beacon HT bw setting from assoc + * resp frame to keep sync with FW. + */ + pBeaconStruct->HTCaps.supportedChannelWidthSet = + assoc_rsp->HTCaps.supportedChannelWidthSet; + if (pBeaconStruct->HTInfo.present && + assoc_rsp->HTInfo.present) { + pBeaconStruct->HTInfo.secondaryChannelOffset = + assoc_rsp->HTInfo.secondaryChannelOffset; + pBeaconStruct->HTInfo.recommendedTxWidthSet = + assoc_rsp->HTInfo.recommendedTxWidthSet; + } + } if (IS_DOT11_MODE_HE(ft_session->dot11mode) && pBeaconStruct->he_cap.present) diff --git a/core/mac/src/pe/lim/lim_ft_preauth.c b/core/mac/src/pe/lim/lim_ft_preauth.c index 48b4fd9cb57d..9c294b6be099 100644 --- a/core/mac/src/pe/lim/lim_ft_preauth.c +++ b/core/mac/src/pe/lim/lim_ft_preauth.c @@ -339,9 +339,9 @@ QDF_STATUS lim_ft_setup_auth_session(struct mac_context *mac, if (req && req->pbssDescription) { lim_fill_ft_session(mac, req->pbssDescription, ft_session, - pe_session, WLAN_PHYMODE_AUTO); + pe_session, WLAN_PHYMODE_AUTO, NULL); lim_ft_prepare_add_bss_req(mac, ft_session, - req->pbssDescription); + req->pbssDescription, NULL); } return QDF_STATUS_SUCCESS;