diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index e0c3bce625d0..c62e50be9a4b 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -687,7 +687,9 @@ typedef struct sSirSmeStartBssReq { tSirMacRateSet extendedRateSet; /* Has 11g rates */ tSirHTConfig htConfig; struct sir_vht_config vht_config; - +#ifdef WLAN_FEATURE_11AX + tDot11fIEvendor_he_cap he_config; +#endif #ifdef WLAN_FEATURE_11W bool pmfCapable; bool pmfRequired; @@ -1179,6 +1181,9 @@ typedef struct sSirSmeJoinReq { uint8_t txLdpcIniFeatureEnabled; tSirHTConfig htConfig; struct sir_vht_config vht_config; +#ifdef WLAN_FEATURE_11AX + tDot11fIEvendor_he_cap he_config; +#endif uint8_t enableVhtpAid; uint8_t enableVhtGid; uint8_t enableAmpduPs; @@ -6876,6 +6881,9 @@ struct wow_enable_params { }; #ifdef WLAN_FEATURE_11AX +#define HE_OP_OUI_TYPE "\x00\x13\x74\x02" +#define HE_OP_OUI_SIZE 4 + /* HE Op Mask is based on the HE Operation definition in the D1.0 spec */ #define HE_OP_BSS_COLOR_MASK (0x3F << 0) #define HE_OP_DEF_PE_DUR_MASK (0x07 << 6) @@ -6887,6 +6895,18 @@ struct wow_enable_params { #define HE_OP_BSS_COLOR_DIS_MASK (0x01 << 30) #define HE_OP_DUAL_BEACON_MASK (0x01 << 31) +#define HE_OP_BSS_COLOR_GET(he_op) ((he_op & HE_OP_BSS_COLOR_MASK) >> 0) +#define HE_OP_DEF_PE_DUR_GET(he_op) ((he_op & HE_OP_DEF_PE_DUR_MASK) >> 6) +#define HE_OP_TWT_REQ_GET(he_op) ((he_op & HE_OP_TWT_REQ_MASK) >> 9) +#define HE_OP_RTS_THRES_GET(he_op) ((he_op & HE_OP_RTS_THRES_MASK) >> 10) +#define HE_OP_PART_BSS_COLOR_GET(he_op) ((he_op & HE_OP_PART_BSS_COLOR_MASK) \ + >> 20) +#define HE_OP_MAXBSSID_IND_GET(he_op) ((he_op & HE_OP_MAXBSSID_IND_MASK) >> 21) +#define HE_OP_TX_BSSIX_IND_GET(he_op) ((he_op & HE_OP_TX_BSSIX_IND_MASK) >> 29) +#define HE_OP_BSS_COLOR_DIS_GET(he_op) ((he_op & HE_OP_BSS_COLOR_DIS_MASK) \ + >> 30) +#define HE_OP_DUAL_BEACON_GET(he_op) ((he_op & HE_OP_DUAL_BEACON_MASK) >> 31) + #define HE_RU_ALLOC_INDX0_MASK (0x01 << 0) #define HE_RU_ALLOC_INDX1_MASK (0x01 << 1) #define HE_RU_ALLOC_INDX2_MASK (0x01 << 2) diff --git a/core/mac/src/include/dph_global.h b/core/mac/src/include/dph_global.h index 63236b9be124..35f2a34497fc 100644 --- a/core/mac/src/include/dph_global.h +++ b/core/mac/src/include/dph_global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -266,6 +266,10 @@ typedef struct sDphHashNode { bool sta_deletion_in_progress; struct parsed_ies parsed_ies; +#ifdef WLAN_FEATURE_11AX + tDot11fIEvendor_he_cap he_config; +#endif + /* * When a station with already an existing dph entry tries to * associate again, the old dph entry will be zeroed out except diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h index 01abc33c3091..174713d4f16e 100644 --- a/core/mac/src/include/parser_api.h +++ b/core/mac/src/include/parser_api.h @@ -195,6 +195,8 @@ typedef struct sSirProbeRespBeacon { bool assoc_disallowed; uint8_t assoc_disallowed_reason; tSirQCNIE QCN_IE; + tDot11fIEvendor_he_cap vendor_he_cap; + tDot11fIEvendor_he_op vendor_he_op; } tSirProbeRespBeacon, *tpSirProbeRespBeacon; /* probe Request structure */ @@ -210,6 +212,7 @@ typedef struct sSirProbeReq { uint8_t wscIePresent; uint8_t p2pIePresent; tDot11fIEVHTCaps VHTCaps; + tDot11fIEvendor_he_cap vendor_he_cap; } tSirProbeReq, *tpSirProbeReq; /* / Association Request structure (one day to be replaced by */ @@ -263,6 +266,7 @@ typedef struct sSirAssocReq { tDot11fIEExtCap ExtCap; tDot11fIEvendor_vht_ie vendor_vht_ie; tDot11fIEhs20vendor_ie hs20vendor_ie; + tDot11fIEvendor_he_cap he_cap; } tSirAssocReq, *tpSirAssocReq; /* / Association Response structure (one day to be replaced by */ @@ -314,6 +318,8 @@ typedef struct sSirAssocRsp { tDot11fIEvendor_vht_ie vendor_vht_ie; tDot11fIEOBSSScanParameters obss_scanparams; tSirQCNIE QCN_IE; + tDot11fIEvendor_he_cap vendor_he_cap; + tDot11fIEvendor_he_op vendor_he_op; } tSirAssocRsp, *tpSirAssocRsp; #ifdef FEATURE_WLAN_ESE @@ -999,4 +1005,23 @@ sir_validate_and_rectify_ies(tpAniSirGlobal mac_ctx, uint32_t frame_bytes, uint32_t *missing_rsn_bytes); +#ifdef WLAN_FEATURE_11AX +QDF_STATUS populate_dot11f_he_caps(tpAniSirGlobal , tpPESession , + tDot11fIEvendor_he_cap *); +QDF_STATUS populate_dot11f_he_operation(tpAniSirGlobal , tpPESession , + tDot11fIEvendor_he_op *); +#else +static inline QDF_STATUS populate_dot11f_he_caps(tpAniSirGlobal mac_ctx, + tpPESession session, tDot11fIEvendor_he_cap *he_cap) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS populate_dot11f_he_operation(tpAniSirGlobal mac_ctx, + tpPESession session, tDot11fIEvendor_he_op *he_op) +{ + return QDF_STATUS_SUCCESS; +} + +#endif #endif /* __PARSE_H__ */ diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index 3fbcf898ef20..a9b99760f8f6 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/core/mac/src/pe/include/lim_api.h @@ -358,5 +358,26 @@ static inline void lim_fill_join_rsp_ht_caps(tpPESession session, #endif QDF_STATUS lim_update_ext_cap_ie(tpAniSirGlobal mac_ctx, uint8_t *ie_data, uint8_t *local_ie_buf, uint16_t *local_ie_len); + +#ifdef WLAN_FEATURE_11AX +#define LIM_HE_SU_BEAMFORMER_BYTE_IDX 8 +#define LIM_HE_SU_BEAMFORMEE_BYTE_IDX 9 +#define LIM_HE_MU_BEAMFORMER_BYTE_IDX 9 +#define LIM_HE_SU_BEAMFORMER_BIT_POS 8 +#define LIM_HE_SU_BEAMFORMEE_BIT_POS 1 +#define LIM_HE_MU_BEAMFORMER_BIT_POS 2 + +#define LIM_GET_BIT_VALUE(arr, byte, bit) ((arr[byte-1] >> (bit - 1)) & 0x01) +#define LIM_GET_SU_BEAMFORMER(he_cap) \ + LIM_GET_BIT_VALUE(he_cap, LIM_HE_SU_BEAMFORMER_BYTE_IDX, \ + LIM_HE_SU_BEAMFORMER_BIT_POS) +#define LIM_GET_SU_BEAMFORMEE(he_cap) \ + LIM_GET_BIT_VALUE(he_cap, LIM_HE_SU_BEAMFORMEE_BYTE_IDX, \ + LIM_HE_SU_BEAMFORMEE_BIT_POS) +#define LIM_GET_MU_BEAMFORMER(he_cap) \ + LIM_GET_BIT_VALUE(he_cap, LIM_HE_MU_BEAMFORMER_BYTE_IDX, \ + LIM_HE_MU_BEAMFORMER_BIT_POS) +#endif + /************************************************************/ #endif /* __LIM_API_H */ diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h index 14a05676d657..6672d6eb6a65 100644 --- a/core/mac/src/pe/include/lim_global.h +++ b/core/mac/src/pe/include/lim_global.h @@ -340,6 +340,9 @@ typedef struct sLimMlmStaContext { /* 802.11n HT Capability in Station: Enabled 1 or DIsabled 0 */ uint8_t htCapability:1; uint8_t vhtCapability:1; +#ifdef WLAN_FEATURE_11AX + bool he_capable; +#endif } tLimMlmStaContext, *tpLimMlmStaContext; /* Structure definition to hold deferred messages queue parameters */ diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index ef8bd18dc4cf..f54f5a272a8f 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -493,7 +493,11 @@ typedef struct sPESession /* Added to Support BT-AMP */ bool ignore_assoc_disallowed; bool send_p2p_conf_frame; bool process_ho_fail; +#ifdef WLAN_FEATURE_11AX bool he_capable; + tDot11fIEvendor_he_cap he_config; + tDot11fIEvendor_he_op he_op; +#endif } tPESession, *tpPESession; /*------------------------------------------------------------------------- diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index 1bc58d95dbce..a3074227c62d 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -2112,6 +2112,7 @@ static uint32_t lim_populate_vht_caps(tDot11fIEVHTCaps input_caps) return vht_caps; } + /** * lim_add_sta()- called to add an STA context at hardware * @mac_ctx: pointer to global mac structure @@ -2240,13 +2241,14 @@ lim_add_sta(tpAniSirGlobal mac_ctx, else { add_sta_params->htCapable = session_entry->htCapability; add_sta_params->vhtCapable = session_entry->vhtCapability; - } - lim_log(mac_ctx, LOG2, FL("vhtCapable: %d "), - add_sta_params->vhtCapable); - lim_log(mac_ctx, LOG2, FL(" StaIdx: %d updateSta = %d htcapable = %d "), + + lim_update_sta_he_capable(mac_ctx, add_sta_params, sta_ds, + session_entry); + + lim_log(mac_ctx, LOG1, FL("StaIdx: %d updateSta = %d htcapable = %d vhtCapable: %d"), add_sta_params->staIdx, add_sta_params->updateSta, - add_sta_params->htCapable); + add_sta_params->htCapable, add_sta_params->vhtCapable); add_sta_params->greenFieldCapable = sta_ds->htGreenfield; add_sta_params->maxAmpduDensity = sta_ds->htAMpduDensity; @@ -2371,6 +2373,9 @@ lim_add_sta(tpAniSirGlobal mac_ctx, if (assoc_req && add_sta_params->vhtCapable) add_sta_params->vht_caps = lim_populate_vht_caps(assoc_req->VHTCaps); + + lim_add_he_cap(add_sta_params, assoc_req); + } else if (LIM_IS_IBSS_ROLE(session_entry)) { /* @@ -2869,6 +2874,9 @@ lim_add_sta_self(tpAniSirGlobal pMac, uint16_t staIdx, uint8_t updateSta, pAddStaParams->listenInterval, pAddStaParams->shortPreambleSupported); + if (IS_DOT11_MODE_HE(selfStaDot11Mode)) + lim_add_self_he_cap(pAddStaParams, psessionEntry); + msgQ.type = WMA_ADD_STA_REQ; msgQ.reserved = 0; msgQ.bodyptr = pAddStaParams; @@ -3506,7 +3514,6 @@ static void lim_update_vht_oper_assoc_resp(tpAniSirGlobal mac_ctx, FL("Updating VHT Operation in assoc Response")); } - /** * limSendAddBss() * @@ -3722,6 +3729,10 @@ tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, pAddBssParams->ch_center_freq_seg0, pAddBssParams->ch_center_freq_seg1); + if (lim_is_session_he_capable(psessionEntry) && + (pAssocRsp->vendor_he_cap.present)) + lim_add_bss_he_cap(pAddBssParams, pAssocRsp); + /* * Populate the STA-related parameters here * Note that the STA here refers to the AP @@ -3803,6 +3814,10 @@ tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, psessionEntry->vht_config.su_beam_former) sta_context->enable_su_tx_bformer = 1; } + if (lim_is_session_he_capable(psessionEntry) && + pAssocRsp->vendor_he_cap.present) + lim_intersect_ap_he_caps(psessionEntry, pAddBssParams, + NULL, pAssocRsp); if ((pAssocRsp->HTCaps.supportedChannelWidthSet) && (chanWidthSupp)) { @@ -4271,11 +4286,15 @@ tSirRetStatus lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t update } else { pAddBssParams->vhtCapable = 0; } + + if (lim_is_session_he_capable(psessionEntry) && + pBeaconStruct->vendor_he_cap.present) + lim_update_bss_he_capable(pMac, pAddBssParams); + lim_log(pMac, LOGE, FL("vhtCapable %d vhtTxChannelWidthSet %d center_freq_seg0 - %d, center_freq_seg1 - %d"), pAddBssParams->vhtCapable, pAddBssParams->ch_width, pAddBssParams->ch_center_freq_seg0, pAddBssParams->ch_center_freq_seg1); - /* * Populate the STA-related parameters here * Note that the STA here refers to the AP @@ -4346,6 +4365,11 @@ tSirRetStatus lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t update lim_log(pMac, LOG2, FL("StaContext: su_tx_bfer %d"), pAddBssParams->staContext.enable_su_tx_bformer); } + if (lim_is_session_he_capable(psessionEntry) && + pBeaconStruct->vendor_he_cap.present) + lim_intersect_ap_he_caps(psessionEntry, pAddBssParams, + pBeaconStruct, NULL); + if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) && (chanWidthSupp)) { pAddBssParams->staContext.ch_width = diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c index 6c4999a07d62..be473aa01e05 100644 --- a/core/mac/src/pe/lim/lim_ft.c +++ b/core/mac/src/pe/lim/lim_ft.c @@ -376,6 +376,11 @@ void lim_ft_prepare_add_bss_req(tpAniSirGlobal pMac, pftSessionEntry->vht_config.su_beam_former) sta_ctx->enable_su_tx_bformer = 1; } + if (lim_is_session_he_capable(pftSessionEntry) && + pBeaconStruct->vendor_he_cap.present) + lim_intersect_ap_he_caps(pftSessionEntry, + pAddBssParams, pBeaconStruct, NULL); + if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) && (chanWidthSupp)) { sta_ctx->ch_width = (uint8_t) diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index 6c18beddd3a9..8eec7a2f4385 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -1275,6 +1275,7 @@ static bool lim_update_sta_ds(tpAniSirGlobal mac_ctx, tpSirMacMgmtHdr hdr, sta_ds->mlmStaContext.vhtCapability = vht_caps->present; else sta_ds->mlmStaContext.vhtCapability = false; + lim_update_stads_he_capable(sta_ds, assoc_req); sta_ds->qos.addtsPresent = (assoc_req->addtsPresent == 0) ? false : true; sta_ds->qos.addts = assoc_req->addtsReq; @@ -1417,6 +1418,9 @@ static bool lim_update_sta_ds(tpAniSirGlobal mac_ctx, tpSirMacMgmtHdr hdr, else sta_ds->vht_su_bfee_capable = 0; } + + lim_intersect_sta_he_caps(assoc_req, session, sta_ds); + if (lim_populate_matching_rate_set(mac_ctx, sta_ds, &(assoc_req->supportedRates), &(assoc_req->extendedRates), 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 0ed58ce974c3..adb17e51dab1 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 @@ -207,6 +207,10 @@ void lim_update_assoc_sta_datas(tpAniSirGlobal mac_ctx, sta_ds->vhtSupportedRxNss = ((sta_ds->supportedRates.vhtRxMCSMap & MCSMAPMASK2x2) == MCSMAPMASK2x2) ? 1 : 2; + + if (IS_DOT11_MODE_HE(session_entry->dot11mode)) + lim_update_stads_he_caps(sta_ds, assoc_rsp, session_entry); + /* If one of the rates is 11g rates, set the ERP mode. */ if ((phy_mode == WNI_CFG_PHY_MODE_11G) && sirIsArate(sta_ds->supportedRates.llaRates[0] & 0x7f)) 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 09bbf4a85832..fd2204cace7e 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 @@ -432,6 +432,10 @@ static void mlm_add_sta(tpAniSirGlobal mac_ctx, tpAddStaParams sta_param, sta_param->enable_su_tx_bformer = session_entry->vht_config.su_beam_former; } + + if (lim_is_session_he_capable(session_entry)) + lim_add_self_he_cap(sta_param, session_entry); + /* * Since this is Self-STA, need to populate Self MAX_AMPDU_SIZE * capabilities @@ -527,7 +531,12 @@ lim_mlm_add_bss(tpAniSirGlobal mac_ctx, addbss_param->nwType = mlm_start_req->nwType; addbss_param->htCapable = mlm_start_req->htCapable; addbss_param->vhtCapable = session->vhtCapability; - addbss_param->he_capable = session->he_capable; + if (lim_is_session_he_capable(session)) { + lim_update_bss_he_capable(mac_ctx, addbss_param); + lim_decide_he_op(mac_ctx, addbss_param, session); + lim_update_usr_he_cap(mac_ctx, session); + } + addbss_param->ch_width = session->ch_width; addbss_param->ch_center_freq_seg0 = session->ch_center_freq_seg0; @@ -557,6 +566,7 @@ lim_mlm_add_bss(tpAniSirGlobal mac_ctx, addbss_param->obssProtEnabled = mlm_start_req->obssProtEnabled; addbss_param->maxTxPower = session->maxTxPower; + mlm_add_sta(mac_ctx, &addbss_param->staContext, addbss_param->bssId, addbss_param->htCapable, session); diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index f4f9827794e9..ead9ef6b7ccc 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -794,12 +794,15 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) IS_DOT11_MODE_HT(session->dot11mode); session->vhtCapability = IS_DOT11_MODE_VHT(session->dot11mode); - session->he_capable = - IS_DOT11_MODE_HE(session->dot11mode); - lim_log(mac_ctx, LOG1, FL("HT[%d], VHT[%d], HE[%d]"), - session->htCapability, session->vhtCapability, - session->he_capable); + lim_log(mac_ctx, LOG1, FL("HT[%d], VHT[%d]"), + session->htCapability, session->vhtCapability); + + if (IS_DOT11_MODE_HE(session->dot11mode)) { + lim_update_session_he_capable(mac_ctx, session); + lim_copy_bss_he_cap(session, sme_start_bss_req); + } + session->txLdpcIniFeatureEnabled = sme_start_bss_req->txLdpcIniFeatureEnabled; #ifdef WLAN_FEATURE_11W @@ -902,8 +905,8 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) (session->htSecondaryChannelOffset) ? 1 : 0; QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_INFO, FL("cbMode %u"), sme_start_bss_req->cbMode); - if (session->he_capable || session->vhtCapability || - session->htCapability) { + if (lim_is_session_he_capable(session) || + session->vhtCapability || session->htCapability) { chanwidth = sme_start_bss_req->vht_channel_width; lim_log(mac_ctx, LOG1, FL("vht_channel_width %u htSupportedChannelWidthSet %d"), @@ -1736,16 +1739,17 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) session->vht_config.su_beam_former); } - session->he_capable = - IS_DOT11_MODE_HE(session->dot11mode); + if (IS_DOT11_MODE_HE(session->dot11mode)) { + lim_update_session_he_capable(mac_ctx, session); + lim_copy_join_req_he_cap(session, sme_join_req); + } lim_log(mac_ctx, LOG1, - FL("vhtCapability: %d su_beam_formee: %d txbf_csn_value: %d su_tx_bformer %d he_capable: %d"), + FL("vhtCapability: %d su_beam_formee: %d txbf_csn_value: %d su_tx_bformer %d"), session->vhtCapability, session->vht_config.su_beam_formee, session->vht_config.csnof_beamformer_antSup, - session->vht_config.su_beam_former, - session->he_capable); + session->vht_config.su_beam_former); /*Phy mode */ session->gLimPhyMode = bss_desc->nwType; handle_ht_capabilityand_ht_info(mac_ctx, session); diff --git a/core/mac/src/pe/lim/lim_send_frames_host_roam.c b/core/mac/src/pe/lim/lim_send_frames_host_roam.c index 2bf89e122f2b..5fb62a9e878b 100644 --- a/core/mac/src/pe/lim/lim_send_frames_host_roam.c +++ b/core/mac/src/pe/lim/lim_send_frames_host_roam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -315,6 +315,13 @@ void lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal mac_ctx, &frm.vendor_vht_ie.VHTCaps); vht_enabled = true; } + + if (lim_is_session_he_capable(pe_session)) { + lim_log(mac_ctx, LOG1, FL("Populate HE IEs")); + populate_dot11f_he_caps(mac_ctx, pe_session, + &frm.vendor_he_cap); + } + status = dot11f_get_packed_re_assoc_request_size(mac_ctx, &frm, &payload); if (DOT11F_FAILED(status)) { @@ -689,6 +696,13 @@ void lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal pMac, isVHTEnabled = true; } populate_dot11f_ext_cap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry); + + if (lim_is_session_he_capable(psessionEntry)) { + lim_log(pMac, LOG1, FL("Populate HE IEs")); + populate_dot11f_he_caps(pMac, psessionEntry, + &frm.vendor_he_cap); + } + nStatus = dot11f_get_packed_re_assoc_request_size(pMac, &frm, &nPayload); if (DOT11F_FAILED(nStatus)) { diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 6a01564f13fb..d115236a2d55 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -348,6 +348,12 @@ lim_send_probe_req_mgmt_frame(tpAniSirGlobal mac_ctx, populate_dot11f_qcn_ie(&pr.QCN_IE); + if (IS_DOT11_MODE_HE(dot11mode) && NULL != pesession) + lim_update_session_he_capable(mac_ctx, pesession); + + lim_log(mac_ctx, LOG1, FL("Populate HE IEs")); + populate_dot11f_he_caps(mac_ctx, pesession, &pr.vendor_he_cap); + if (addn_ielen) { qdf_mem_zero((uint8_t *)&extracted_ext_cap, sizeof(tDot11fIEExtCap)); @@ -689,6 +695,14 @@ lim_send_probe_rsp_mgmt_frame(tpAniSirGlobal mac_ctx, is_vht_enabled = true; } + if (lim_is_session_he_capable(pe_session)) { + lim_log(mac_ctx, LOG1, FL("Populate HE IEs")); + populate_dot11f_he_caps(mac_ctx, pe_session, + &frm->vendor_he_cap); + populate_dot11f_he_operation(mac_ctx, pe_session, + &frm->vendor_he_op); + } + populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &frm->ExtCap, pe_session); @@ -1282,6 +1296,14 @@ lim_send_assoc_rsp_mgmt_frame(tpAniSirGlobal mac_ctx, populate_dot11f_ext_cap(mac_ctx, is_vht, &frm.ExtCap, pe_session); + if (lim_is_sta_he_capable(sta) && + lim_is_session_he_capable(pe_session)) { + lim_log(mac_ctx, LOG1, FL("Populate HE IEs")); + populate_dot11f_he_caps(mac_ctx, pe_session, + &frm.vendor_he_cap); + populate_dot11f_he_operation(mac_ctx, pe_session, + &frm.vendor_he_op); + } #ifdef WLAN_FEATURE_11W if (eSIR_MAC_TRY_AGAIN_LATER == status_code) { if (wlan_cfg_get_int @@ -1877,6 +1899,11 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, &frm->ExtCap, pe_session); populate_dot11f_qcn_ie(&frm->QCN_IE); + if (lim_is_session_he_capable(pe_session)) { + lim_log(mac_ctx, LOG1, FL("Populate HE IEs")); + populate_dot11f_he_caps(mac_ctx, pe_session, + &frm->vendor_he_cap); + } if (pe_session->pLimJoinReq->is11Rconnection) { tSirBssDescription *bssdescr; diff --git a/core/mac/src/pe/lim/lim_send_messages.c b/core/mac/src/pe/lim/lim_send_messages.c index b0401b41221f..d926bd18bb6d 100644 --- a/core/mac/src/pe/lim/lim_send_messages.c +++ b/core/mac/src/pe/lim/lim_send_messages.c @@ -42,6 +42,7 @@ #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ #include "host_diag_core_log.h" #endif /* FEATURE_WLAN_DIAG_SUPPORT */ +#include "lim_utils.h" /* When beacon filtering is enabled, firmware will * analyze the selected beacons received during BMPS, @@ -237,12 +238,13 @@ tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac, sizeof(tSirMacAddr)); pChnlParams->peSessionId = peSessionId; pChnlParams->vhtCapable = pSessionEntry->vhtCapability; - pChnlParams->he_capable = pSessionEntry->he_capable; + if (lim_is_session_he_capable(pSessionEntry)) + lim_update_chan_he_capable(pMac, pChnlParams); pChnlParams->dot11_mode = pSessionEntry->dot11mode; pChnlParams->nss = pSessionEntry->nss; - lim_log(pMac, LOG1, FL("dot11mode: %d, he_capable: %d, vht_capable: %d nss value: %d"), - pChnlParams->dot11_mode, pChnlParams->he_capable, - pChnlParams->vhtCapable, pChnlParams->nss); + lim_log(pMac, LOG1, FL("dot11mode: %d, vht_capable: %d nss value: %d"), + pChnlParams->dot11_mode, pChnlParams->vhtCapable, + pChnlParams->nss); /*Set DFS flag for DFS channel */ if (ch_width == CH_WIDTH_160MHZ) { diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 142990a439a0..52f2f5fefe04 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -7353,3 +7353,550 @@ void lim_update_last_processed_frame(last_processed_msg *last_processed_frm, qdf_mem_copy(last_processed_frm->sa, pHdr->sa, ETH_ALEN); last_processed_frm->seq_num = seq_num; } + +#ifdef WLAN_FEATURE_11AX +/** + * lim_add_he_cap() - Copy HE capability into Add sta params + * @add_sta_params: pointer to add sta params + * @assoc_req: pointer to Assoc request + * + * Return: None + */ +void lim_add_he_cap(tpAddStaParams add_sta_params, tpSirAssocReq assoc_req) +{ + if (!add_sta_params->he_capable || !assoc_req) + return; + + qdf_mem_copy(&add_sta_params->he_config, &assoc_req->he_cap, + sizeof(add_sta_params->he_config)); +} + +/** + * lim_add_self_he_cap() - Copy HE capability into add sta from PE session + * @add_sta_params: pointer to add sta params + * @session: pointer to PE Session + * + * Return: None + */ +void lim_add_self_he_cap(tpAddStaParams add_sta_params, tpPESession session) +{ + if (!session) + return; + + add_sta_params->he_capable = true; + + qdf_mem_copy(&add_sta_params->he_config, &session->he_config, + sizeof(add_sta_params->he_config)); + qdf_mem_copy(&add_sta_params->he_op, &session->he_op, + sizeof(add_sta_params->he_op)); +} + +/** + * lim_intersect_he_caps() - Intersect peer capability and self capability + * @rcvd_he: pointer to received peer capability + * @session_he: pointer to self capability + * @peer_he: pointer to Intersected capability + * + * Return: None + */ +static void lim_intersect_he_caps(tDot11fIEvendor_he_cap *rcvd_he, + tDot11fIEvendor_he_cap *session_he, + tDot11fIEvendor_he_cap *peer_he) +{ + uint8_t val; + + qdf_mem_copy(peer_he, rcvd_he, sizeof(*peer_he)); + + peer_he->fragmentation &= session_he->fragmentation; + + /* Tx STBC is first bit and Rx STBC is second bit */ + if (session_he->stbc) { + val = 0; + if ((session_he->stbc & 0x1) && (peer_he->stbc & 0x10)) + val |= (1 << 1); + if ((session_he->stbc & 0x10) && (peer_he->stbc & 0x1)) + val |= (1 << 0); + peer_he->stbc = val; + } + + /* Tx Doppler is first bit and Rx Doppler is second bit */ + if (session_he->doppler) { + val = 0; + if ((session_he->stbc & 0x1) && (peer_he->stbc & 0x10)) + val |= (1 << 1); + if ((session_he->stbc & 0x10) && (peer_he->stbc & 0x1)) + val |= (1 << 0); + peer_he->doppler = val; + } + + peer_he->su_beamformer = session_he->su_beamformee ? + peer_he->su_beamformer : 0; + peer_he->su_beamformee = (session_he->su_beamformer || + session_he->mu_beamformer) ? + peer_he->su_beamformee : 0; + peer_he->mu_beamformer = session_he->su_beamformee ? + peer_he->mu_beamformer : 0; + + peer_he->twt_request = session_he->twt_responder ? + peer_he->twt_request : 0; + peer_he->twt_responder = session_he->twt_request ? + peer_he->twt_responder : 0; +} + +/** + * lim_intersect_sta_he_caps() - Intersect STA capability with SAP capability + * @assoc_req: pointer to assoc request + * @session: pointer to PE session + * @sta_ds: pointer to STA dph hash table entry + * + * Return: None + */ +void lim_intersect_sta_he_caps(tpSirAssocReq assoc_req, tpPESession session, + tpDphHashNode sta_ds) +{ + tDot11fIEvendor_he_cap *rcvd_he = &assoc_req->he_cap; + tDot11fIEvendor_he_cap *session_he = &session->he_config; + tDot11fIEvendor_he_cap *peer_he = &sta_ds->he_config; + + if (sta_ds->mlmStaContext.he_capable) + lim_intersect_he_caps(rcvd_he, session_he, peer_he); +} + +/** + * lim_intersect_ap_he_caps() - Intersect AP capability with self STA capability + * @session: pointer to PE session + * @add_bss: pointer to ADD BSS params + * @beacon: pointer to beacon + * @assoc_rsp: pointer to assoc response + * + * Return: None + */ +void lim_intersect_ap_he_caps(tpPESession session, tpAddBssParams add_bss, + tSchBeaconStruct *beacon, tpSirAssocRsp assoc_rsp) +{ + tDot11fIEvendor_he_cap *rcvd_he; + tDot11fIEvendor_he_cap *session_he = &session->he_config; + tDot11fIEvendor_he_cap *peer_he = &add_bss->staContext.he_config; + + if (beacon) + rcvd_he = &beacon->vendor_he_cap; + else + rcvd_he = &assoc_rsp->vendor_he_cap; + + lim_intersect_he_caps(rcvd_he, session_he, peer_he); + add_bss->staContext.he_capable = true; +} + +/** + * lim_add_bss_he_cap() - Copy HE capability into ADD BSS params + * @add_bss: pointer to add bss params + * @assoc_rsp: pointer to assoc response + * + * Return: None + */ +void lim_add_bss_he_cap(tpAddBssParams add_bss, tpSirAssocRsp assoc_rsp) +{ + tDot11fIEvendor_he_cap *he_cap; + tDot11fIEvendor_he_op *he_op; + + he_cap = &assoc_rsp->vendor_he_cap; + he_op = &assoc_rsp->vendor_he_op; + add_bss->he_capable = he_cap->present; + if (he_cap) + qdf_mem_copy(&add_bss->staContext.he_config, + he_cap, sizeof(*he_cap)); + if (he_op) + qdf_mem_copy(&add_bss->staContext.he_op, + he_op, sizeof(*he_op)); +} + + +/** + * lim_update_stads_he_caps() - Copy HE capability into STA DPH hash table entry + * @sta_ds: pointer to sta dph hash table entry + * @assoc_rsp: pointer to assoc response + * @session_entry: pointer to PE session + * + * Return: None + */ +void lim_update_stads_he_caps(tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp, + tpPESession session_entry) +{ + tDot11fIEvendor_he_cap *he_cap; + + he_cap = &assoc_rsp->vendor_he_cap; + sta_ds->mlmStaContext.he_capable = he_cap->present; + + if (!he_cap->present) + return; + + qdf_mem_copy(&sta_ds->he_config, he_cap, sizeof(*he_cap)); + +} + +/** + * lim_update_usr_he_cap() - Update HE capability based on userspace + * @mac_ctx: global mac context + * @session: PE session entry + * + * Parse the HE Capability IE and populate the fields to be + * sent to FW as part of add bss and update PE session. + */ +void lim_update_usr_he_cap(tpAniSirGlobal mac_ctx, tpPESession session) +{ + uint8_t *vendor_ie; + uint8_t *he_cap_data; + tSirAddIeParams *add_ie = &session->addIeParams; + tDot11fIEvendor_he_cap *he_cap = &session->he_config; + + vendor_ie = cfg_get_vendor_ie_ptr_from_oui(mac_ctx, + HE_CAP_OUI_TYPE, HE_CAP_OUI_SIZE, + add_ie->probeRespBCNData_buff, + add_ie->probeRespBCNDataLen); + + if (!vendor_ie) { + lim_log(mac_ctx, LOGE, FL("11AX: Unable to parse HE Caps")); + return; + } + + he_cap_data = vendor_ie + HE_OP_OUI_SIZE + 2; + + lim_log(mac_ctx, LOG1, FL("Before update: su_beamformer: %d, su_beamformee: %d, mu_beamformer: %d"), + he_cap->su_beamformer, he_cap->su_beamformee, he_cap->mu_beamformer); + if (he_cap->su_beamformer) + he_cap->su_beamformer = LIM_GET_SU_BEAMFORMER(he_cap_data); + if (he_cap->su_beamformee) + he_cap->su_beamformee = LIM_GET_SU_BEAMFORMEE(he_cap_data); + if (he_cap->mu_beamformer) + he_cap->mu_beamformer = LIM_GET_MU_BEAMFORMER(he_cap_data); + + lim_log(mac_ctx, LOG1, FL("After update: su_beamformer: %d, su_beamformee: %d, mu_beamformer: %d"), + he_cap->su_beamformer, he_cap->su_beamformee, he_cap->mu_beamformer); +} + +/** + * lim_decide_he_op() - Determine HE operation elements + * @mac_ctx: global mac context + * @he_ops: pointer to HE operation IE + * @session: PE session entry + * + * Parse the HE Operation IE and populate the fields to be + * sent to FW as part of add bss. + */ +void lim_decide_he_op(tpAniSirGlobal mac_ctx, tpAddBssParams add_bss, + tpPESession session) +{ + uint8_t *vendor_ie; + uint32_t he_op; + tDot11fIEvendor_he_op *he_ops = &add_bss->he_op; + tSirAddIeParams *add_ie = &session->addIeParams; + + vendor_ie = cfg_get_vendor_ie_ptr_from_oui(mac_ctx, + HE_OP_OUI_TYPE, HE_OP_OUI_SIZE, + add_ie->probeRespBCNData_buff, + add_ie->probeRespBCNDataLen); + + if (!vendor_ie) { + lim_log(mac_ctx, LOGE, FL("11AX: Unable to parse HE Operation")); + return; + } + + qdf_mem_copy(&he_op, &vendor_ie[HE_OP_OUI_SIZE + 2], sizeof(uint32_t)); + + he_ops->bss_color = HE_OP_BSS_COLOR_GET(he_op); + he_ops->default_pe = HE_OP_DEF_PE_DUR_GET(he_op); + he_ops->twt_required = HE_OP_TWT_REQ_GET(he_op); + he_ops->rts_threshold = HE_OP_RTS_THRES_GET(he_op); + he_ops->partial_bss_col = HE_OP_PART_BSS_COLOR_GET(he_op); + he_ops->maxbssid_ind = HE_OP_MAXBSSID_IND_GET(he_op); + he_ops->tx_bssid_ind = HE_OP_TX_BSSIX_IND_GET(he_op); + he_ops->bss_col_disabled = HE_OP_BSS_COLOR_DIS_GET(he_op); + he_ops->dual_beacon = HE_OP_DUAL_BEACON_GET(he_op); + + session->he_op.bss_color = he_ops->bss_color; + session->he_op.default_pe = he_ops->default_pe; + session->he_op.twt_required = he_ops->twt_required; + session->he_op.rts_threshold = he_ops->rts_threshold; + session->he_op.partial_bss_col = he_ops->partial_bss_col; + session->he_op.maxbssid_ind = he_ops->maxbssid_ind; + session->he_op.tx_bssid_ind = he_ops->tx_bssid_ind; + session->he_op.bss_col_disabled = he_ops->bss_col_disabled; + session->he_op.dual_beacon = he_ops->dual_beacon; + + lim_log(mac_ctx, LOG1, FL("HE Operation: bss_color: %0x, default_pe_duration: %0x, twt_required: %0x, rts_threshold: %0x"), + he_ops->bss_color, he_ops->default_pe, + he_ops->twt_required, he_ops->rts_threshold); + lim_log(mac_ctx, LOG1, ("\tpartial_bss_color: %0x, MaxBSSID Indicator: %0x, Tx BSSID Indicator: %0x, BSS color disabled: %0x, Dual beacon: %0x"), + he_ops->partial_bss_col, he_ops->maxbssid_ind, + he_ops->tx_bssid_ind, he_ops->bss_col_disabled, + he_ops->dual_beacon); +} + +/** + * lim_copy_bss_he_cap() - Copy HE capability into PE session from start bss + * @session: pointer to PE session + * @sme_start_bss_req: pointer to start BSS request + * + * Return: None + */ +void lim_copy_bss_he_cap(tpPESession session, + tpSirSmeStartBssReq sme_start_bss_req) +{ + qdf_mem_copy(&(session->he_config), &(sme_start_bss_req->he_config), + sizeof(session->he_config)); +} + +/** + * lim_copy_join_req_he_cap() - Copy HE capability to PE session from Join req + * @session: pointer to PE session + * @sme_join_req: pointer to SME join request + * + * Return: None + */ +void lim_copy_join_req_he_cap(tpPESession session, + tpSirSmeJoinReq sme_join_req) +{ + qdf_mem_copy(&(session->he_config), &(sme_join_req->he_config), + sizeof(session->he_config)); +} + +/** + * lim_log_he_cap() - Print HE capabilities + * @mac: pointer to MAC context + * @he_cap: pointer to HE Capability + * + * Received HE capabilities are converted into dot11f structure. + * This function will print all the HE capabilities as stored + * in the dot11f structure. + * + * Return: None + */ +void lim_log_he_cap(tpAniSirGlobal mac, tDot11fIEvendor_he_cap *he_cap) +{ + if (!he_cap->present) + return; + + lim_log(mac, LOG1, FL("HE Capabilities:")); + + /* HE MAC capabilities */ + lim_log(mac, LOG1, "\tHTC-HE conrol: 0x%01x", he_cap->htc_he); + lim_log(mac, LOG1, "\tTWT Requestor support: 0x%01x", + he_cap->twt_request); + lim_log(mac, LOG1, "\tTWT Responder support: 0x%01x", + he_cap->twt_responder); + lim_log(mac, LOG1, "\tFragmentation support: 0x%02x", + he_cap->fragmentation); + lim_log(mac, LOG1, "\tMax no.of frag MSDUs: 0x%03x", + he_cap->max_num_frag_msdu); + lim_log(mac, LOG1, "\tMin. frag size: 0x%02x", he_cap->min_frag_size); + lim_log(mac, LOG1, "\tTrigger MAC pad duration: 0x%02x", + he_cap->trigger_frm_mac_pad); + lim_log(mac, LOG1, "\tMulti-TID aggr support: 0x%03x", + he_cap->multi_tid_aggr); + lim_log(mac, LOG1, "\tLink adaptation: 0x%02x", + he_cap->he_link_adaptation); + lim_log(mac, LOG1, "\tAll ACK support: 0x%01x", he_cap->all_ack); + lim_log(mac, LOG1, "\tUL MU resp. scheduling: 0x%01x", + he_cap->ul_mu_rsp_sched); + lim_log(mac, LOG1, "\tA-Buff status report: 0x%01x", he_cap->a_bsr); + lim_log(mac, LOG1, "\tBroadcast TWT support: 0x%01x", + he_cap->broadcast_twt); + lim_log(mac, LOG1, "\t32bit BA bitmap support: 0x%01x", + he_cap->ba_32bit_bitmap); + lim_log(mac, LOG1, "\tMU Cascading support: 0x%01x", + he_cap->mu_cascade); + lim_log(mac, LOG1, "\tACK enabled Multi-TID: 0x%01x", + he_cap->ack_enabled_multitid); + lim_log(mac, LOG1, "\tMulti-STA BA in DL MU: 0x%01x", he_cap->dl_mu_ba); + lim_log(mac, LOG1, "\tOMI A-Control support: 0x%01x", + he_cap->omi_a_ctrl); + lim_log(mac, LOG1, "\tOFDMA RA support: 0x%01x", he_cap->ofdma_ra); + lim_log(mac, LOG1, "\tMax A-MPDU Length: 0x%02x", + he_cap->max_ampdu_len); + lim_log(mac, LOG1, "\tA-MSDU Fragmentation: 0x%01x", + he_cap->amsdu_frag); + lim_log(mac, LOG1, "\tFlex. TWT sched support: 0x%01x", + he_cap->flex_twt_sched); + lim_log(mac, LOG1, "\tRx Ctrl frame to MBSS: 0x%01x", + he_cap->rx_ctrl_frame); + lim_log(mac, LOG1, "\tBSRP A-MPDU Aggregation: 0x%01x", + he_cap->bsrp_ampdu_aggr); + lim_log(mac, LOG1, "\tQuite Time Period support: 0x%01x", he_cap->qtp); + lim_log(mac, LOG1, "\tA-BQR support: 0x%01x", he_cap->a_bqr); + + /* HE PHY capabilities */ + lim_log(mac, LOG1, "\tDual band support: 0x%01x", he_cap->dual_band); + lim_log(mac, LOG1, "\tChannel width support: 0x%07x", + he_cap->chan_width); + lim_log(mac, LOG1, "\tPreamble puncturing Rx: 0x%04x", + he_cap->rx_pream_puncturing); + lim_log(mac, LOG1, "\tClass of device: 0x%01x", he_cap->device_class); + lim_log(mac, LOG1, "\tLDPC coding support: 0x%01x", + he_cap->ldpc_coding); + lim_log(mac, LOG1, "\tLTF and GI for HE PPDUs: 0x%02x", + he_cap->he_ltf_gi_ppdu); + lim_log(mac, LOG1, "\tLTF and GI for NDP: 0x%02x", + he_cap->he_ltf_gi_ndp); + lim_log(mac, LOG1, "\tSTBC Tx & Rx support: 0x%02x", he_cap->stbc); + lim_log(mac, LOG1, "\tDoppler support: 0x%02x", he_cap->doppler); + lim_log(mac, LOG1, "\tUL MU: 0x%02x", he_cap->ul_mu); + lim_log(mac, LOG1, "\tDCM encoding Tx: 0x%03x", he_cap->dcm_enc_tx); + lim_log(mac, LOG1, "\tDCM encoding Tx: 0x%03x", he_cap->dcm_enc_rx); + lim_log(mac, LOG1, "\tHE MU PPDU payload support: 0x%01x", + he_cap->ul_he_mu); + lim_log(mac, LOG1, "\tSU Beamformer: 0x%01x", he_cap->su_beamformer); + lim_log(mac, LOG1, "\tSU Beamformee: 0x%01x", he_cap->su_beamformee); + lim_log(mac, LOG1, "\tMU Beamformer: 0x%01x", he_cap->mu_beamformer); + lim_log(mac, LOG1, "\tBeamformee STS for <= 80Mhz: 0x%03x", + he_cap->bfee_sts_lt_80); + lim_log(mac, LOG1, "\tNSTS total for <= 80Mhz: 0x%03x", + he_cap->nsts_tol_lt_80); + lim_log(mac, LOG1, "\tBeamformee STS for > 80Mhz: 0x%03x", + he_cap->bfee_sta_gt_80); + lim_log(mac, LOG1, "\tNSTS total for > 80Mhz: 0x%03x", + he_cap->nsts_tot_gt_80); + lim_log(mac, LOG1, "\tNo. of sounding dim <= 80Mhz: 0x%03x", + he_cap->num_sounding_lt_80); + lim_log(mac, LOG1, "\tNo. of sounding dim > 80Mhz: 0x%03x", + he_cap->num_sounding_gt_80); + lim_log(mac, LOG1, "\tNg=16 for SU feedback support: 0x%01x", + he_cap->su_feedback_tone16); + lim_log(mac, LOG1, "\tNg=16 for MU feedback support: 0x%01x", + he_cap->mu_feedback_tone16); + lim_log(mac, LOG1, "\tCodebook size for SU: 0x%01x", + he_cap->codebook_su); + lim_log(mac, LOG1, "\tCodebook size for MU: 0x%01x ", + he_cap->codebook_mu); + lim_log(mac, LOG1, "\tBeamforming trigger w/ Trigger: 0x%01x", + he_cap->beamforming_feedback); + lim_log(mac, LOG1, "\tHE ER SU PPDU payload: 0x%01x", + he_cap->he_er_su_ppdu); + lim_log(mac, LOG1, "\tDL MUMIMO on partial BW: 0x%01x", + he_cap->dl_mu_mimo_part_bw); + lim_log(mac, LOG1, "\tPPET present: 0x%01x", he_cap->ppet_present); + lim_log(mac, LOG1, "\tSRP based SR-support: 0x%01x", he_cap->srp); + lim_log(mac, LOG1, "\tPower boost factor: 0x%01x", he_cap->power_boost); + lim_log(mac, LOG1, "\t4x HE LTF support: 0x%01x", he_cap->he_ltf_gi_4x); + + lim_log(mac, LOG1, "\tHighest NSS supported: 0x%03x", + he_cap->nss_supported); + lim_log(mac, LOG1, "\tHighest MCS supported: 0x%03x", + he_cap->mcs_supported); + lim_log(mac, LOG1, "\tTX BW bitmap: 0x%05x", he_cap->tx_bw_bitmap); + lim_log(mac, LOG1, "\tRX BW bitmap: 0x%05x ", he_cap->rx_bw_bitmap); + + /* HE PPET */ + if (!he_cap->ppe_threshold.present) { + lim_log(mac, LOG1, FL("PPET is not present. Invalid IE")); + return; + } + + lim_log(mac, LOG1, "\tNSS: %d", he_cap->ppe_threshold.nss_count + 1); + lim_log(mac, LOG1, "\tRU Index mask: 0x%04x", + he_cap->ppe_threshold.ru_idx_mask); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, + he_cap->ppe_threshold.ppet, he_cap->ppe_threshold.num_ppet); +} + +/** + * lim_log_he_op() - Print HE Operation + * @mac: pointer to MAC context + * @he_op: pointer to HE Operation + * + * Print HE operation stored as dot11f structure + * + * Return: None + */ +void lim_log_he_op(tpAniSirGlobal mac, tDot11fIEvendor_he_op *he_ops) +{ + tDot11fIEvht_info *vht_info = &he_ops->vht_info; + + lim_log(mac, LOG1, FL("bss_color: %0x, default_pe_duration: %0x, twt_required: %0x, rts_threshold: %0x"), + he_ops->bss_color, he_ops->default_pe, + he_ops->twt_required, he_ops->rts_threshold); + lim_log(mac, LOG1, ("\tpartial_bss_color: %0x, MaxBSSID Indicator: %0x, Tx BSSID Indicator: %0x, BSS color disabled: %0x, Dual beacon: %0x"), + he_ops->partial_bss_col, he_ops->maxbssid_ind, + he_ops->tx_bssid_ind, he_ops->bss_col_disabled, + he_ops->dual_beacon); + + if (!vht_info->present) + lim_log(mac, LOG1, FL("VHT Info not present in HE Operation")); + else + lim_log(mac, LOG1, FL("VHT Info: chan_width: %d, center_freq0: %d, center_freq1: %d"), + vht_info->chan_width, vht_info->center_freq_seg0, + vht_info->center_freq_seg1); +} + +/** + * lim_update_sta_he_capable(): Update he_capable in add sta params + * @mac: pointer to MAC context + * @add_sta_params: pointer to add sta params + * @sta_ds: pointer to dph hash table entry + * @session_entry: pointer to PE session + * + * Return: None + */ +void lim_update_sta_he_capable(tpAniSirGlobal mac, + tpAddStaParams add_sta_params, tpDphHashNode sta_ds, + tpPESession session_entry) +{ + if (LIM_IS_AP_ROLE(session_entry) || LIM_IS_IBSS_ROLE(session_entry)) + add_sta_params->he_capable = sta_ds->mlmStaContext.he_capable; + else + add_sta_params->he_capable = session_entry->he_capable; + + lim_log(mac, LOG1, FL("he_capable: %d"), add_sta_params->he_capable); +} + +/** + * lim_update_bss_he_capable(): Update he_capable in add BSS params + * @mac: pointer to MAC context + * @add_bss: pointer to add BSS params + * + * Return: None + */ +void lim_update_bss_he_capable(tpAniSirGlobal mac, tpAddBssParams add_bss) +{ + add_bss->he_capable = true; + lim_log(mac, LOG1, FL("he_capable: %d"), add_bss->he_capable); +} + +/** + * lim_update_stads_he_capable() - Update he_capable in sta ds context + * @sta_ds: pointer to sta ds + * @assoc_req: pointer to assoc request + * + * Return: None + */ +void lim_update_stads_he_capable(tpDphHashNode sta_ds, tpSirAssocReq assoc_req) +{ + sta_ds->mlmStaContext.he_capable = assoc_req->he_cap.present; +} + +/** + * lim_update_session_he_capable(): Update he_capable in PE session + * @mac: pointer to MAC context + * @session: pointer to PE session + * + * Return: None + */ +void lim_update_session_he_capable(tpAniSirGlobal mac, tpPESession session) +{ + session->he_capable = true; + lim_log(mac, LOG1, FL("he_capable: %d"), session->he_capable); +} + +/** + * lim_update_chan_he_capable(): Update he_capable in chan switch params + * @mac: pointer to MAC context + * @chan: pointer to channel switch params + * + * Return: None + */ +void lim_update_chan_he_capable(tpAniSirGlobal mac, tpSwitchChannelParams chan) +{ + chan->he_capable = true; + lim_log(mac, LOG1, FL("he_capable: %d"), chan->he_capable); +} + +#endif diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index bb56e0bfd1ed..d9c13774b003 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -677,4 +677,145 @@ tSirRetStatus lim_strip_ie(tpAniSirGlobal mac_ctx, uint8_t eid, eSizeOfLenField size_of_len_field, uint8_t *oui, uint8_t out_len, uint8_t *extracted_ie, uint32_t eid_max_len); + +#ifdef WLAN_FEATURE_11AX +void lim_intersect_ap_he_caps(tpPESession session, tpAddBssParams add_bss, + tSchBeaconStruct *pBeaconStruct, tpSirAssocRsp assoc_rsp); +void lim_intersect_sta_he_caps(tpSirAssocReq assoc_req, tpPESession session, + tpDphHashNode sta_ds); +void lim_add_he_cap(tpAddStaParams add_sta_params, tpSirAssocReq assoc_req); +void lim_add_self_he_cap(tpAddStaParams add_sta_params, tpPESession session); +void lim_add_bss_he_cap(tpAddBssParams add_bss, tpSirAssocRsp assoc_rsp); +void lim_copy_bss_he_cap(tpPESession session, + tpSirSmeStartBssReq sme_start_bss_req); +void lim_copy_join_req_he_cap(tpPESession session, + tpSirSmeJoinReq sme_join_req); +void lim_log_he_op(tpAniSirGlobal mac, tDot11fIEvendor_he_op *he_ops); +void lim_log_he_cap(tpAniSirGlobal mac, tDot11fIEvendor_he_cap *he_cap); +void lim_update_stads_he_caps(tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp, + tpPESession session_entry); +void lim_update_usr_he_cap(tpAniSirGlobal mac_ctx, tpPESession session); +void lim_decide_he_op(tpAniSirGlobal mac_ctx, tpAddBssParams add_bss, + tpPESession session); +void lim_update_sta_he_capable(tpAniSirGlobal mac, + tpAddStaParams add_sta_params, tpDphHashNode sta_ds, + tpPESession session_entry); + +static inline bool lim_is_session_he_capable(tpPESession session) +{ + return session->he_capable; +} + +static inline bool lim_is_sta_he_capable(tpDphHashNode sta_ds) +{ + return sta_ds->mlmStaContext.he_capable; +} + +void lim_update_bss_he_capable(tpAniSirGlobal mac, tpAddBssParams add_bss); +void lim_update_stads_he_capable(tpDphHashNode sta_ds, tpSirAssocReq assoc_req); +void lim_update_session_he_capable(tpAniSirGlobal mac, tpPESession session); +void lim_update_chan_he_capable(tpAniSirGlobal mac, tpSwitchChannelParams chan); + +#else +static inline void lim_add_he_cap(tpAddStaParams add_sta_params, + tpSirAssocReq assoc_req) +{ +} + +static inline void lim_add_self_he_cap(tpAddStaParams add_sta_params, + tpPESession session) +{ +} + +static inline void lim_add_bss_he_cap(tpAddBssParams add_bss, + tpSirAssocRsp assoc_rsp) +{ + return; +} + +static inline void lim_intersect_ap_he_caps(tpPESession session, + tpAddBssParams add_bss, tSchBeaconStruct *pBeaconStruct, + tpSirAssocRsp assoc_rsp) +{ + return; +} + +static inline void lim_intersect_sta_he_caps(tpSirAssocReq assoc_req, + tpPESession session, tpDphHashNode sta_ds) +{ +} + +static inline void lim_update_stads_he_caps(tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp, + tpPESession session_entry) +{ + return; +} + +static inline void lim_update_usr_he_cap(tpAniSirGlobal mac_ctx, + tpPESession session) +{ +} + +static inline void lim_decide_he_op(tpAniSirGlobal mac_ctx, + tpAddBssParams add_bss, tpPESession session) +{ +} + +static inline void lim_copy_bss_he_cap(tpPESession session, + tpSirSmeStartBssReq sme_start_bss_req) +{ +} +static inline void lim_copy_join_req_he_cap(tpPESession session, + tpSirSmeJoinReq sme_join_req) +{ +} + +static inline void lim_log_he_op(tpAniSirGlobal mac, + tDot11fIEvendor_he_op *he_ops) +{ +} + +static inline void lim_log_he_cap(tpAniSirGlobal mac, + tDot11fIEvendor_he_cap *he_cap) +{ +} + +static inline void lim_update_sta_he_capable(tpAniSirGlobal mac, + tpAddStaParams add_sta_params, + tpDphHashNode sta_ds, tpPESession session_entry) +{ +} + +static inline bool lim_is_session_he_capable(tpPESession session) +{ + return false; +} + +static inline bool lim_is_sta_he_capable(tpDphHashNode sta_ds) +{ + return false; +} + +static inline void lim_update_bss_he_capable(tpAniSirGlobal mac, + tpAddBssParams add_bss) +{ +} + +static inline void lim_update_stads_he_capable(tpDphHashNode sta_ds, + tpSirAssocReq assoc_req) +{ +} + +static inline void lim_update_session_he_capable(tpAniSirGlobal mac, + tpPESession session) +{ +} + +static inline void lim_update_chan_he_capable(tpAniSirGlobal mac, + tpSwitchChannelParams chan) +{ +} + +#endif + #endif /* __LIM_UTILS_H */ diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c index 6edd75e7d77d..e6c1fff1d6d3 100644 --- a/core/mac/src/pe/sch/sch_beacon_gen.c +++ b/core/mac/src/pe/sch/sch_beacon_gen.c @@ -386,6 +386,15 @@ sch_set_fixed_beacon_fields(tpAniSirGlobal mac_ctx, tpPESession session) populate_dot11f_operating_mode(mac_ctx, &bcn_2->OperatingMode, session); } + + if (lim_is_session_he_capable(session)) { + sch_log(mac_ctx, LOGW, FL("Populate HE IEs")); + populate_dot11f_he_caps(mac_ctx, session, + &bcn_2->vendor_he_cap); + populate_dot11f_he_operation(mac_ctx, session, + &bcn_2->vendor_he_op); + } + if (session->limSystemRole != eLIM_STA_IN_IBSS_ROLE) populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &bcn_2->ExtCap, session); @@ -756,6 +765,21 @@ void lim_update_probe_rsp_template_ie_bitmap_beacon2(tpAniSirGlobal pMac, sizeof(beacon2->ExtCap)); } + if (beacon2->vendor_he_cap.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + DOT11F_EID_VENDOR_HE_CAP); + qdf_mem_copy((void *)&prb_rsp->vendor_he_cap, + (void *)&beacon2->vendor_he_cap, + sizeof(beacon2->vendor_he_cap)); + } + if (beacon2->vendor_he_op.present) { + set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, + DOT11F_EID_VENDOR_HE_OP); + qdf_mem_copy((void *)&prb_rsp->vendor_he_op, + (void *)&beacon2->vendor_he_op, + sizeof(beacon2->vendor_he_op)); + } + } void set_probe_rsp_ie_bitmap(uint32_t *IeBitmap, uint32_t pos) diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index 9d872ac7dca7..72e51003379f 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -2260,6 +2260,11 @@ sir_convert_probe_req_frame2_struct(tpAniSirGlobal pMac, if (pr.P2PProbeReq.present) { pProbeReq->p2pIePresent = 1; } + if (pr.vendor_he_cap.present) { + qdf_mem_copy(&pProbeReq->vendor_he_cap, &pr.vendor_he_cap, + sizeof(tDot11fIEvendor_he_cap)); + lim_log(pMac, LOG1, FL("11AX: HE cap IE present")); + } return eSIR_SUCCESS; } /* End sir_convert_probe_req_frame2_struct. */ @@ -2631,6 +2636,17 @@ tSirRetStatus sir_convert_probe_frame2_struct(tpAniSirGlobal pMac, } } + if (pr->vendor_he_cap.present) { + lim_log(pMac, LOG1, FL("11AX: HE cap IE present")); + qdf_mem_copy(&pProbeResp->vendor_he_cap, &pr->vendor_he_cap, + sizeof(tDot11fIEvendor_he_cap)); + } + if (pr->vendor_he_op.present) { + lim_log(pMac, LOG1, FL("11AX: HE operation IE present")); + qdf_mem_copy(&pProbeResp->vendor_he_op, &pr->vendor_he_op, + sizeof(tDot11fIEvendor_he_op)); + } + qdf_mem_free(pr); return eSIR_SUCCESS; @@ -2838,6 +2854,12 @@ sir_convert_assoc_req_frame2_struct(tpAniSirGlobal pMac, lim_log_vht_cap(pMac, &pAssocReq->VHTCaps); } } + if (ar->vendor_he_cap.present) { + qdf_mem_copy(&pAssocReq->he_cap, &ar->vendor_he_cap, + sizeof(tDot11fIEvendor_he_cap)); + lim_log(pMac, LOG1, + FL("Received Assoc Req with HE Capability IE")); + } qdf_mem_free(ar); return eSIR_SUCCESS; @@ -3064,6 +3086,18 @@ sir_convert_assoc_resp_frame2_struct(tpAniSirGlobal pMac, FL("Received Assoc Response with Vendor specific VHT Oper")); lim_log_vht_operation(pMac, &pAssocRsp->VHTOperation); } + + if (ar.vendor_he_cap.present) { + lim_log(pMac, LOG1, FL("11AX: HE cap IE present")); + qdf_mem_copy(&pAssocRsp->vendor_he_cap, &ar.vendor_he_cap, + sizeof(tDot11fIEvendor_he_cap)); + } + if (ar.vendor_he_op.present) { + lim_log(pMac, LOG1, FL("11AX: HE Operation IE present")); + qdf_mem_copy(&pAssocRsp->vendor_he_op, &ar.vendor_he_op, + sizeof(tDot11fIEvendor_he_op)); + } + return eSIR_SUCCESS; } /* End sir_convert_assoc_resp_frame2_struct. */ @@ -3239,6 +3273,10 @@ sir_convert_reassoc_req_frame2_struct(tpAniSirGlobal pMac, ext_cap->timing_meas, ext_cap->fine_time_meas_initiator, ext_cap->fine_time_meas_responder); } + if (ar.vendor_he_cap.present) { + qdf_mem_copy(&pAssocReq->he_cap, &ar.vendor_he_cap, + sizeof(tDot11fIEvendor_he_cap)); + } return eSIR_SUCCESS; @@ -3836,6 +3874,17 @@ sir_parse_beacon_ie(tpAniSirGlobal pMac, } } + if (pBies->vendor_he_cap.present) { + qdf_mem_copy(&pBeaconStruct->vendor_he_cap, + &pBies->vendor_he_cap, + sizeof(tDot11fIEvendor_he_cap)); + } + if (pBies->vendor_he_op.present) { + qdf_mem_copy(&pBeaconStruct->vendor_he_op, + &pBies->vendor_he_op, + sizeof(tDot11fIEvendor_he_op)); + } + qdf_mem_free(pBies); return eSIR_SUCCESS; } /* End sir_parse_beacon_ie. */ @@ -4214,6 +4263,19 @@ sir_convert_beacon_frame2_struct(tpAniSirGlobal pMac, } } + if (pBeacon->vendor_he_cap.present) { + lim_log(pMac, LOG1, FL("11AX: HE cap IE present")); + qdf_mem_copy(&pBeaconStruct->vendor_he_cap, + &pBeacon->vendor_he_cap, + sizeof(tDot11fIEvendor_he_cap)); + } + if (pBeacon->vendor_he_op.present) { + lim_log(pMac, LOG1, FL("11AX: HE operation IE present")); + qdf_mem_copy(&pBeaconStruct->vendor_he_op, + &pBeacon->vendor_he_op, + sizeof(tDot11fIEvendor_he_op)); + } + qdf_mem_free(pBeacon); return eSIR_SUCCESS; @@ -5912,4 +5974,210 @@ tSirRetStatus populate_dot11f_timing_advert_frame(tpAniSirGlobal mac_ctx, return nSirStatus; } +#ifdef WLAN_FEATURE_11AX +/** + * populate_dot11f_he_caps() - pouldate HE Capability IE + * @mac_ctx: Global MAC context + * @session: PE session + * @he_cap: pointer to HE capability IE + * + * Populdate the HE capability IE based on the session. + */ +QDF_STATUS populate_dot11f_he_caps(tpAniSirGlobal mac_ctx, tpPESession session, + tDot11fIEvendor_he_cap *he_cap) +{ + uint32_t value = 0; + tSirRetStatus status; + + he_cap->present = 1; + + if (!session) { + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_CONTROL, value); + he_cap->htc_he = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_TWT_REQUESTOR, value); + he_cap->twt_request = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_TWT_RESPONDER, value); + he_cap->twt_responder = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_FRAGMENTATION, value); + he_cap->fragmentation = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MAX_FRAG_MSDU, value); + he_cap->max_num_frag_msdu = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MIN_FRAG_SIZE, value); + he_cap->min_frag_size = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_TRIG_PAD, value); + he_cap->trigger_frm_mac_pad = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MTID_AGGR, value); + he_cap->multi_tid_aggr = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_LINK_ADAPTATION, value); + he_cap->he_link_adaptation = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_ALL_ACK, value); + he_cap->all_ack = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_UL_MU_RSP_SCHEDULING, + value); + he_cap->ul_mu_rsp_sched = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_BUFFER_STATUS_RPT, + value); + he_cap->a_bsr = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_BCAST_TWT, value); + he_cap->broadcast_twt = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_BA_32BIT, value); + he_cap->ba_32bit_bitmap = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MU_CASCADING, value); + he_cap->mu_cascade = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MULTI_TID, value); + he_cap->ack_enabled_multitid = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_DL_MU_BA, value); + he_cap->dl_mu_ba = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_OMI, value); + he_cap->omi_a_ctrl = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_OFDMA_RA, value); + he_cap->ofdma_ra = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MAX_AMPDU_LEN, value); + he_cap->max_ampdu_len = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_AMSDU_FRAG, value); + he_cap->amsdu_frag = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_FLEX_TWT_SCHED, value); + he_cap->flex_twt_sched = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_RX_CTRL, value); + he_cap->rx_ctrl_frame = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_BSRP_AMPDU_AGGR, value); + he_cap->bsrp_ampdu_aggr = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_QTP, value); + he_cap->qtp = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_A_BQR, value); + he_cap->a_bqr = value; + + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_DUAL_BAND, value); + he_cap->dual_band = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_CHAN_WIDTH, value); + he_cap->chan_width = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_RX_PREAM_PUNC, value); + he_cap->rx_pream_puncturing = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_CLASS_OF_DEVICE, value); + he_cap->device_class = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_LDPC, value); + he_cap->ldpc_coding = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_LTF_PPDU, value); + he_cap->he_ltf_gi_ppdu = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_LTF_NDP, value); + he_cap->he_ltf_gi_ndp = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_STBC, value); + he_cap->stbc = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_DOPPLER, value); + he_cap->doppler = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_UL_MUMIMO, value); + he_cap->ul_mu = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_DCM_TX, value); + he_cap->dcm_enc_tx = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_DCM_RX, value); + he_cap->dcm_enc_rx = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MU_PPDU, value); + he_cap->ul_he_mu = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_SU_BEAMFORMER, value); + he_cap->su_beamformer = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_SU_BEAMFORMEE, value); + he_cap->su_beamformee = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MU_BEAMFORMER, value); + he_cap->mu_beamformer = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_BFEE_STS_LT80, value); + he_cap->bfee_sts_lt_80 = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_NSTS_TOT_LT80, value); + he_cap->nsts_tol_lt_80 = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_BFEE_STS_GT80, value); + he_cap->bfee_sta_gt_80 = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_NSTS_TOT_GT80, value); + he_cap->nsts_tot_gt_80 = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_NUM_SOUND_LT80, value); + he_cap->num_sounding_lt_80 = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_NUM_SOUND_GT80, value); + he_cap->num_sounding_gt_80 = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_SU_FEED_TONE16, value); + he_cap->su_feedback_tone16 = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MU_FEED_TONE16, value); + he_cap->mu_feedback_tone16 = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_CODEBOOK_SU, value); + he_cap->codebook_su = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_CODEBOOK_MU, value); + he_cap->codebook_mu = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_BFRM_FEED, value); + he_cap->beamforming_feedback = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_ER_SU_PPDU, value); + he_cap->he_er_su_ppdu = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_DL_PART_BW, value); + he_cap->dl_mu_mimo_part_bw = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_PPET_PRESENT, value); + he_cap->ppet_present = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_SRP, value); + he_cap->srp = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_POWER_BOOST, value); + he_cap->power_boost = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_4x_LTF_GI, value); + he_cap->he_ltf_gi_4x = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_NSS, value); + he_cap->nss_supported = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MCS, value); + he_cap->mcs_supported = value; + + value = WNI_CFG_HE_PPET_LEN; + CFG_GET_STR(status, mac_ctx, WNI_CFG_HE_PPET, + (void *)&he_cap->ppe_threshold, value, value); + + return QDF_STATUS_SUCCESS; + } + + qdf_mem_copy(he_cap, &session->he_config, sizeof(*he_cap)); + + lim_log_he_cap(mac_ctx, he_cap); + + return QDF_STATUS_SUCCESS; +} + +/** + * populate_dot11f_he_operation() - pouldate HE Operation IE + * @mac_ctx: Global MAC context + * @session: PE session + * @he_op: pointer to HE Operation IE + * + * Populdate the HE Operation IE based on the session. + */ +QDF_STATUS populate_dot11f_he_operation(tpAniSirGlobal mac_ctx, + tpPESession session, tDot11fIEvendor_he_op *he_op) +{ + tDot11fIEvht_info *vht_info = &he_op->vht_info; + + he_op->present = 1; + + he_op->bss_color = session->he_op.bss_color; + he_op->default_pe = session->he_op.default_pe; + he_op->twt_required = session->he_op.twt_required; + he_op->rts_threshold = session->he_op.rts_threshold; + he_op->partial_bss_col = session->he_op.partial_bss_col; + he_op->maxbssid_ind = session->he_op.maxbssid_ind; + he_op->tx_bssid_ind = session->he_op.tx_bssid_ind; + he_op->bss_col_disabled = session->he_op.bss_col_disabled; + he_op->dual_beacon = session->he_op.dual_beacon; + + vht_info->present = 1; + if (session->ch_width > CH_WIDTH_40MHZ) { + vht_info->chan_width = 1; + vht_info->center_freq_seg0 = + session->ch_center_freq_seg0; + if (session->ch_width == CH_WIDTH_80P80MHZ || + session->ch_width == CH_WIDTH_160MHZ) + vht_info->center_freq_seg1 = + session->ch_center_freq_seg1; + else + vht_info->center_freq_seg1 = 0; + } else { + vht_info->chan_width = 0; + vht_info->center_freq_seg0 = 0; + vht_info->center_freq_seg1 = 0; + } + + lim_log_he_op(mac_ctx, he_op); + + return QDF_STATUS_SUCCESS; +} +#endif + /* parser_api.c ends here. */ diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 9393ba3d6da9..203e2fc2caf3 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -971,6 +971,9 @@ typedef struct tagCsrRoamSession { uint8_t bRefAssocStartCnt; /* Tracking assoc start indication */ tSirHTConfig htConfig; struct sir_vht_config vht_config; +#ifdef WLAN_FEATURE_11AX + tDot11fIEvendor_he_cap he_config; +#endif #ifdef FEATURE_WLAN_SCAN_PNO bool pnoStarted; #endif diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7240d2f21a7c..db9272a770d3 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -2195,6 +2195,173 @@ static void csr_get_he_config_param(tCsrConfigParam *param, param->enable_ul_ofdma = mac_ctx->roam.configParam.enable_ul_ofdma; param->enable_ul_mimo = mac_ctx->roam.configParam.enable_ul_mimo; } + + +/** + * csr_join_req_copy_he_cap() - Copy HE cap into CSR Join Req + * @csr_join_req: pointer to CSR Join Req + * @session: pointer to CSR session + * + * Return: None + */ +static void csr_join_req_copy_he_cap(tSirSmeJoinReq *csr_join_req, + tCsrRoamSession *session) +{ + qdf_mem_copy(&csr_join_req->he_config, &session->he_config, + sizeof(session->he_config)); +} + +/** + * csr_start_bss_copy_he_cap() - Copy HE cap into CSR Join Req + * @req: pointer to START BSS Req + * @session: pointer to CSR session + * + * Return: None + */ +static void csr_start_bss_copy_he_cap(tSirSmeStartBssReq *req, + tCsrRoamSession *session) +{ + qdf_mem_copy(&req->he_config, &session->he_config, + sizeof(session->he_config)); +} + +static void csr_update_session_he_cap(tpAniSirGlobal mac_ctx, + tCsrRoamSession *session) +{ + uint32_t value = 0; + tDot11fIEvendor_he_cap *he_cap = &session->he_config; + + he_cap->present = true; + + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_CONTROL, &value); + he_cap->htc_he = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_TWT_REQUESTOR, &value); + he_cap->twt_request = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_TWT_RESPONDER, &value); + he_cap->twt_responder = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_FRAGMENTATION, &value); + he_cap->fragmentation = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MAX_FRAG_MSDU, &value); + he_cap->max_num_frag_msdu = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MIN_FRAG_SIZE, &value); + he_cap->min_frag_size = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_TRIG_PAD, &value); + he_cap->trigger_frm_mac_pad = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MTID_AGGR, &value); + he_cap->multi_tid_aggr = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_LINK_ADAPTATION, &value); + he_cap->he_link_adaptation = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_ALL_ACK, &value); + he_cap->all_ack = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_UL_MU_RSP_SCHEDULING, &value); + he_cap->ul_mu_rsp_sched = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_BUFFER_STATUS_RPT, &value); + he_cap->a_bsr = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_BCAST_TWT, &value); + he_cap->broadcast_twt = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_BA_32BIT, &value); + he_cap->ba_32bit_bitmap = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MU_CASCADING, &value); + he_cap->mu_cascade = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MULTI_TID, &value); + he_cap->ack_enabled_multitid = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_DL_MU_BA, &value); + he_cap->dl_mu_ba = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_OMI, &value); + he_cap->omi_a_ctrl = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_OFDMA_RA, &value); + he_cap->ofdma_ra = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MAX_AMPDU_LEN, &value); + he_cap->max_ampdu_len = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_AMSDU_FRAG, &value); + he_cap->amsdu_frag = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_FLEX_TWT_SCHED, &value); + he_cap->flex_twt_sched = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_RX_CTRL, &value); + he_cap->rx_ctrl_frame = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_BSRP_AMPDU_AGGR, &value); + he_cap->bsrp_ampdu_aggr = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_QTP, &value); + he_cap->qtp = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_A_BQR, &value); + he_cap->a_bqr = value; + + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_DUAL_BAND, &value); + he_cap->dual_band = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_CHAN_WIDTH, &value); + he_cap->chan_width = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_RX_PREAM_PUNC, &value); + he_cap->rx_pream_puncturing = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_CLASS_OF_DEVICE, &value); + he_cap->device_class = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_LDPC, &value); + he_cap->ldpc_coding = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_LTF_PPDU, &value); + he_cap->he_ltf_gi_ppdu = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_LTF_NDP, &value); + he_cap->he_ltf_gi_ndp = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_STBC, &value); + he_cap->stbc = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_DOPPLER, &value); + he_cap->doppler = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_UL_MUMIMO, &value); + he_cap->ul_mu = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_DCM_TX, &value); + he_cap->dcm_enc_tx = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_DCM_RX, &value); + he_cap->dcm_enc_rx = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MU_PPDU, &value); + he_cap->ul_he_mu = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_SU_BEAMFORMER, &value); + he_cap->su_beamformer = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_SU_BEAMFORMEE, &value); + he_cap->su_beamformee = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MU_BEAMFORMER, &value); + he_cap->mu_beamformer = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_BFEE_STS_LT80, &value); + he_cap->bfee_sts_lt_80 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_NSTS_TOT_LT80, &value); + he_cap->nsts_tol_lt_80 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_BFEE_STS_GT80, &value); + he_cap->bfee_sta_gt_80 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_NSTS_TOT_GT80, &value); + he_cap->nsts_tot_gt_80 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_NUM_SOUND_LT80, &value); + he_cap->num_sounding_lt_80 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_NUM_SOUND_GT80, &value); + he_cap->num_sounding_gt_80 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_SU_FEED_TONE16, &value); + he_cap->su_feedback_tone16 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MU_FEED_TONE16, &value); + he_cap->mu_feedback_tone16 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_CODEBOOK_SU, &value); + he_cap->codebook_su = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_CODEBOOK_MU, &value); + he_cap->codebook_mu = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_BFRM_FEED, &value); + he_cap->beamforming_feedback = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_ER_SU_PPDU, &value); + he_cap->he_er_su_ppdu = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_DL_PART_BW, &value); + he_cap->dl_mu_mimo_part_bw = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_PPET_PRESENT, &value); + he_cap->ppet_present = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_SRP, &value); + he_cap->srp = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_POWER_BOOST, &value); + he_cap->power_boost = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_4x_LTF_GI, &value); + he_cap->he_ltf_gi_4x = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_NSS, &value); + he_cap->nss_supported = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MCS, &value); + he_cap->mcs_supported = value; + + value = WNI_CFG_HE_PPET_LEN; + sme_cfg_get_str(mac_ctx, WNI_CFG_HE_PPET, + (void *)&he_cap->ppe_threshold, &value); +} + #else static inline void csr_update_he_config_param(tpAniSirGlobal mac_ctx, tCsrConfigParam *param) @@ -2205,6 +2372,22 @@ static inline void csr_get_he_config_param(tCsrConfigParam *param, tpAniSirGlobal mac_ctx) { } + +static inline void csr_join_req_copy_he_cap(tSirSmeJoinReq *csr_join_req, + tCsrRoamSession *session) +{ +} + +static inline void csr_start_bss_copy_he_cap(tSirSmeStartBssReq *req, + tCsrRoamSession *session) +{ +} + +static inline void csr_update_session_he_cap(tpAniSirGlobal mac_ctx, + tCsrRoamSession *session) +{ +} + #endif QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, @@ -14483,6 +14666,10 @@ QDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, FL("ht capability 0x%x VHT capability 0x%x"), (unsigned int)(*(uint32_t *) &csr_join_req->htConfig), (unsigned int)(*(uint32_t *) &csr_join_req->vht_config)); + + if (IS_DOT11_MODE_HE(csr_join_req->dot11mode)) + csr_join_req_copy_he_cap(csr_join_req, pSession); + if (wlan_cfg_get_int(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, &value) != eSIR_SUCCESS) QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, @@ -15302,6 +15489,9 @@ QDF_STATUS csr_send_mb_start_bss_req_msg(tpAniSirGlobal pMac, uint32_t sessionId sms_log(pMac, LOG2, FL("ht capability 0x%x VHT capability 0x%x"), (uint32_t)(*(uint32_t *) &pMsg->htConfig), (uint32_t)(*(uint32_t *) &pMsg->vht_config)); + if (IS_DOT11_MODE_HE(pMsg->dot11mode)) + csr_start_bss_copy_he_cap(pMsg, pSession); + qdf_mem_copy(&pMsg->addIeParams, &pParam->addIeParams, sizeof(pParam->addIeParams)); @@ -15719,6 +15909,8 @@ QDF_STATUS csr_roam_open_session(tpAniSirGlobal mac_ctx, &nCfgValue); session->vht_config.max_ampdu_lenexp = nCfgValue; + csr_update_session_he_cap(mac_ctx, session); + status = csr_issue_add_sta_for_session_req(mac_ctx, i, pSelfMacAddr, type, subType); diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 32f51de5044f..5e278399dd70 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1089,6 +1089,10 @@ struct wma_txrx_node { tSirHostOffloadReq ns_offload_req; bool is_vdev_valid; struct sir_vdev_wow_stats wow_stats; +#ifdef WLAN_FEATURE_11AX + bool he_capable; + uint32_t he_ops; +#endif }; #if defined(QCA_WIFI_FTM) @@ -1696,6 +1700,7 @@ struct wma_target_req { * @preferred_rx_streams: policy manager indicates the preferred * number of receive streams * @he_capable: HE capability + * @he_ops: HE operation */ struct wma_vdev_start_req { uint32_t beacon_intval; @@ -1720,7 +1725,10 @@ struct wma_vdev_start_req { uint32_t preferred_tx_streams; uint32_t preferred_rx_streams; uint8_t beacon_tx_rate; +#ifdef WLAN_FEATURE_11AX bool he_capable; + uint32_t he_ops; +#endif }; /** diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 4ad2ba63805f..eea9c8bde47b 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -304,4 +304,5 @@ QDF_STATUS wma_set_sar_limit(WMA_HANDLE handle, * Return: QDF_STATUS_SUCCESS on success, error number otherwise */ QDF_STATUS wma_set_qpower_config(uint8_t vdev_id, uint8_t qpower); + #endif diff --git a/core/wma/inc/wma_he.h b/core/wma/inc/wma_he.h index 01b9baf5e3bd..61e66a47eba1 100644 --- a/core/wma/inc/wma_he.h +++ b/core/wma/inc/wma_he.h @@ -24,19 +24,39 @@ #ifdef WLAN_FEATURE_11AX void wma_print_he_cap(tDot11fIEvendor_he_cap *he_cap); -void wma_print_he_ppet(wmi_ppe_threshold *ppet); +void wma_print_he_ppet(void *ppet); void wma_print_he_phy_cap(uint32_t *phy_cap); void wma_print_he_mac_cap(uint32_t mac_cap); +void wma_print_he_op(tDot11fIEvendor_he_op *he_ops); void wma_update_target_ext_he_cap(tp_wma_handle wma_handle, struct wma_tgt_cfg *tgt_cfg); void wma_he_update_tgt_services(tp_wma_handle wma, struct wma_tgt_services *cfg); +void wma_populate_peer_he_cap(struct peer_assoc_params *peer, + tpAddStaParams params); +void wma_update_vdev_he_ops(struct wma_vdev_start_req *req, + tpAddBssParams add_bss); +void wma_copy_txrxnode_he_ops(struct wma_txrx_node *node, + struct wma_vdev_start_req *req); +void wma_copy_vdev_start_he_ops(struct vdev_start_params *params, + struct wma_vdev_start_req *req); +void wma_vdev_set_he_bss_params(tp_wma_handle wma, uint8_t vdev_id, + struct wma_vdev_start_req *req); + +static inline bool wma_is_peer_he_capable(tpAddStaParams params) +{ + return params->he_capable; +} + +void wma_update_vdev_he_capable(struct wma_vdev_start_req *req, + tpSwitchChannelParams params); + #else static inline void wma_print_he_cap(tDot11fIEvendor_he_cap *he_cap) { } -static inline void wma_print_he_ppet(wmi_ppe_threshold *ppet) +static inline void wma_print_he_ppet(void *ppet) { } @@ -48,6 +68,10 @@ static inline void wma_print_he_mac_cap(uint32_t mac_cap) { } +static inline void wma_print_he_op(tDot11fIEvendor_he_op *he_ops) +{ +} + static inline void wma_update_target_ext_he_cap(tp_wma_handle wma_handle, struct wma_tgt_cfg *tgt_cfg) { @@ -60,6 +84,39 @@ static inline void wma_he_update_tgt_services(tp_wma_handle wma, return; } +static inline void wma_populate_peer_he_cap(struct peer_assoc_params *peer, + tpAddStaParams params) +{ +} + +static inline void wma_update_vdev_he_ops(struct wma_vdev_start_req *req, + tpAddBssParams add_bss) +{ +} +static inline void wma_copy_txrxnode_he_ops(struct wma_txrx_node *intr, + struct wma_vdev_start_req *req) +{ +} + +static inline void wma_copy_vdev_start_he_ops(struct vdev_start_params *params, + struct wma_vdev_start_req *req) +{ +} + +static inline void wma_vdev_set_he_bss_params(tp_wma_handle wma, + uint8_t vdev_id, struct wma_vdev_start_req *req) +{ +} + +static inline bool wma_is_peer_he_capable(tpAddStaParams params) +{ + return false; +} + +static inline void wma_update_vdev_he_capable(struct wma_vdev_start_req *req, + tpSwitchChannelParams params) +{ +} #endif #endif /* __WMA_HE_H */ diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index c22bf9047a11..b7e24368dc76 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -325,6 +325,11 @@ typedef struct { uint32_t peerAtimWindowLength; uint8_t nonRoamReassoc; uint32_t nss; +#ifdef WLAN_FEATURE_11AX + bool he_capable; + tDot11fIEvendor_he_cap he_config; + tDot11fIEvendor_he_op he_op; +#endif } tAddStaParams, *tpAddStaParams; /** @@ -517,7 +522,11 @@ typedef struct { uint8_t beacon_tx_rate; uint32_t tx_aggregation_size; uint32_t rx_aggregation_size; +#ifdef WLAN_FEATURE_11AX bool he_capable; + tDot11fIEvendor_he_cap he_config; + tDot11fIEvendor_he_op he_op; +#endif } tAddBssParams, *tpAddBssParams; /** @@ -912,7 +921,9 @@ typedef struct { uint8_t restart_on_chan_switch; uint8_t nss; +#ifdef WLAN_FEATURE_11AX bool he_capable; +#endif } tSwitchChannelParams, *tpSwitchChannelParams; typedef void (*tpSetLinkStateCallback)(tpAniSirGlobal pMac, void *msgParam, diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index d16312f30394..815b8c0f0eaf 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -894,7 +894,7 @@ bool wma_is_sta_active(tp_wma_handle wma_handle); WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type, uint8_t is_ht, uint8_t ch_width, - uint8_t is_vht); + uint8_t is_vht, bool is_he); int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle, uint8_t vdev_id, uint32_t value); diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 8207366e5b18..c9ad92c375cb 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -78,6 +78,8 @@ #include #include "wlan_pmo_ucfg_api.h" +#include "wma_he.h" + /** * wma_find_vdev_by_addr() - find vdev_id from mac address * @wma: wma handle @@ -1928,6 +1930,7 @@ QDF_STATUS wma_vdev_start(tp_wma_handle wma, CFG_TGT_DEFAULT_GTX_BW_MASK; intr[params.vdev_id].mhz = params.chan_freq; intr[params.vdev_id].chan_width = req->chan_width; + wma_copy_txrxnode_he_ops(&intr[params.vdev_id], req); temp_chan_info &= 0xffffffc0; temp_chan_info |= params.chan_mode; @@ -2064,6 +2067,8 @@ QDF_STATUS wma_vdev_start(tp_wma_handle wma, params.preferred_rx_streams = req->preferred_rx_streams; params.preferred_tx_streams = req->preferred_tx_streams; + wma_copy_vdev_start_he_ops(¶ms, req); + /* Store vdev params in SAP mode which can be used in vdev restart */ if (intr[req->vdev_id].type == WMI_VDEV_TYPE_AP && intr[req->vdev_id].sub_type == 0) { @@ -2830,6 +2835,7 @@ wma_vdev_set_bss_params(tp_wma_handle wma, int vdev_id, /* Initialize protection mode in case of coexistence */ wma_update_protection_mode(wma, vdev_id, llbCoexist); + } #ifdef WLAN_FEATURE_11W @@ -2935,7 +2941,8 @@ static void wma_add_bss_ap_mode(tp_wma_handle wma, tpAddBssParams add_bss) req.ch_center_freq_seg0 = add_bss->ch_center_freq_seg0; req.ch_center_freq_seg1 = add_bss->ch_center_freq_seg1; req.vht_capable = add_bss->vhtCapable; - req.he_capable = add_bss->he_capable; + wma_update_vdev_he_ops(&req, add_bss); + req.max_txpow = add_bss->maxTxPower; maxTxPower = add_bss->maxTxPower; @@ -2975,6 +2982,8 @@ static void wma_add_bss_ap_mode(tp_wma_handle wma, tpAddBssParams add_bss) add_bss->shortSlotTimeSupported, add_bss->llbCoexist, maxTxPower); + wma_vdev_set_he_bss_params(wma, vdev_id, &req); + return; peer_cleanup: diff --git a/core/wma/src/wma_he.c b/core/wma/src/wma_he.c index c3968bcc520a..3fbbbf472192 100644 --- a/core/wma/src/wma_he.c +++ b/core/wma/src/wma_he.c @@ -25,6 +25,7 @@ #include "wma_he.h" #include "wmi_unified_api.h" #include "cds_utils.h" +#include "wma_internal.h" /** * wma_he_ppet_merge() - Merge PPET8 and PPET16 for a given ru and nss @@ -126,7 +127,7 @@ static void wma_he_find_ppet(uint32_t *ppet, int nss, int ru, * Return: None */ static void wma_convert_he_ppet(tDot11fIEppe_threshold *he_ppet, - wmi_ppe_threshold *ppet) + struct wmi_host_ppe_threshold *ppet) { int bits, req_byte; uint8_t *host_ppet, ru_count, mask; @@ -139,7 +140,7 @@ static void wma_convert_he_ppet(tDot11fIEppe_threshold *he_ppet, he_ppet->present = true; he_ppet->nss_count = ppet->numss_m1; - he_ppet->ru_idx_mask = ppet->ru_mask; + he_ppet->ru_idx_mask = ppet->ru_bit_mask; mask = he_ppet->ru_idx_mask; for (ru_count = 0; mask; mask >>= 1) @@ -184,7 +185,7 @@ static void wma_convert_he_ppet(tDot11fIEppe_threshold *he_ppet, * @he_cap: pointer to dot11f structure * @mac_cap: Received HE MAC capability * @phy_cap: Received HE PHY capability - * @ppet: Received HE PPE threshold + * @he_ppet: Received HE PPE threshold * @mcs: Max MCS supported (Tx/Rx) * @nss: Max NSS supported (Tx/Rx) * @@ -195,9 +196,11 @@ static void wma_convert_he_ppet(tDot11fIEppe_threshold *he_ppet, * Return: None */ static void wma_convert_he_cap(tDot11fIEvendor_he_cap *he_cap, uint32_t mac_cap, - uint32_t *phy_cap, wmi_ppe_threshold *ppet, + uint32_t *phy_cap, void *he_ppet, uint8_t mcs, uint8_t nss) { + struct wmi_host_ppe_threshold *ppet = he_ppet; + he_cap->present = true; /* HE MAC capabilities */ @@ -466,7 +469,7 @@ void wma_print_he_cap(tDot11fIEvendor_he_cap *he_cap) /** * wma_print_he_ppet() - Prints HE PPE Threshold - * @ppet: PPE Threshold + * @he_ppet: PPE Threshold * * This function prints HE PPE Threshold as received from FW. * Refer to the definition of wmi_ppe_threshold to understand @@ -474,9 +477,10 @@ void wma_print_he_cap(tDot11fIEvendor_he_cap *he_cap) * * Return: none */ -void wma_print_he_ppet(wmi_ppe_threshold *ppet) +void wma_print_he_ppet(void *he_ppet) { - int numss, ru_count, ru_mask, i, j; + int numss, ru_count, ru_bit_mask, i, j; + struct wmi_host_ppe_threshold *ppet = he_ppet; if (!ppet) { WMA_LOGI(FL("PPET is NULL")); @@ -484,22 +488,22 @@ void wma_print_he_ppet(wmi_ppe_threshold *ppet) } numss = ppet->numss_m1 + 1; - ru_mask = ppet->ru_mask; + ru_bit_mask = ppet->ru_bit_mask; - WMA_LOGI(FL("HE PPET: ru_idx_mask: %04x"), ru_mask); - for (ru_count = 0; ru_mask; ru_mask >>= 1) - if (ru_mask & 0x1) + WMA_LOGI(FL("HE PPET: ru_idx_mask: %04x"), ru_bit_mask); + for (ru_count = 0; ru_bit_mask; ru_bit_mask >>= 1) + if (ru_bit_mask & 0x1) ru_count++; if (ru_count > 0) { WMA_LOGI(FL("PPET has following RU INDEX,")); - if (ppet->ru_mask & HE_RU_ALLOC_INDX0_MASK) + if (ppet->ru_bit_mask & HE_RU_ALLOC_INDX0_MASK) WMA_LOGI("\tRU ALLOCATION INDEX 0"); - if (ppet->ru_mask & HE_RU_ALLOC_INDX1_MASK) + if (ppet->ru_bit_mask & HE_RU_ALLOC_INDX1_MASK) WMA_LOGI("\tRU ALLOCATION INDEX 1"); - if (ppet->ru_mask & HE_RU_ALLOC_INDX2_MASK) + if (ppet->ru_bit_mask & HE_RU_ALLOC_INDX2_MASK) WMA_LOGI("\tRU ALLOCATION INDEX 2"); - if (ppet->ru_mask & HE_RU_ALLOC_INDX3_MASK) + if (ppet->ru_bit_mask & HE_RU_ALLOC_INDX3_MASK) WMA_LOGI("\tRU ALLOCATION INDEX 3"); } @@ -674,7 +678,7 @@ void wma_update_target_ext_he_cap(tp_wma_handle wma_handle, int i, j = 0, max_mac; uint32_t he_mac; uint32_t he_phy[WMI_MAX_HECAP_PHY_SIZE]; - wmi_ppe_threshold he_ppet; + uint8_t *he_ppet; struct extended_caps *phy_caps; WMI_MAC_PHY_CAPABILITIES *mac_cap; tDot11fIEvendor_he_cap he_cap_mac0 = {0}, he_cap_mac1 = {0}; @@ -705,14 +709,14 @@ void wma_update_target_ext_he_cap(tp_wma_handle wma_handle, he_mac = mac_cap->he_cap_info_2G; qdf_mem_copy(he_phy, mac_cap->he_cap_phy_info_2G, WMI_MAX_HECAP_PHY_SIZE * 4); - he_ppet = mac_cap->he_ppet2G; + he_ppet = (uint8_t *)&mac_cap->he_ppet2G; mcs = mac_cap->he_supp_mcs_2G; nss = (mac_cap->tx_chain_mask_2G > mac_cap->rx_chain_mask_2G) ? mac_cap->tx_chain_mask_2G : mac_cap->rx_chain_mask_2G; wma_convert_he_cap(&he_cap_mac0, he_mac, he_phy, - &he_ppet, mcs, nss); + he_ppet, mcs, nss); if (he_cap_mac0.present) wma_derive_ext_he_cap(wma_handle, &tmp_he_cap, &he_cap_mac0); @@ -720,14 +724,14 @@ void wma_update_target_ext_he_cap(tp_wma_handle wma_handle, he_mac = mac_cap->he_cap_info_5G; qdf_mem_copy(he_phy, mac_cap->he_cap_phy_info_5G, WMI_MAX_HECAP_PHY_SIZE * 4); - he_ppet = mac_cap->he_ppet5G; + he_ppet = (uint8_t *)&mac_cap->he_ppet5G; mcs = mac_cap->he_supp_mcs_5G; nss = (mac_cap->tx_chain_mask_5G > mac_cap->rx_chain_mask_5G) ? mac_cap->tx_chain_mask_5G : mac_cap->rx_chain_mask_5G; wma_convert_he_cap(&he_cap_mac1, he_mac, he_phy, - &he_ppet, mcs, nss); + he_ppet, mcs, nss); if (he_cap_mac1.present) wma_derive_ext_he_cap(wma_handle, &tmp_he_cap, &he_cap_mac1); @@ -758,3 +762,337 @@ void wma_he_update_tgt_services(tp_wma_handle wma, struct wma_tgt_services *cfg) WMA_LOGI(FL("11ax is not enabled")); } } + +/** + * @wma_print_he_op() - Print HE Operation + * @he_cap: pointer to HE Operation + * + * Print HE operation stored as dot11f structure + * + * Return: None + */ +void wma_print_he_op(tDot11fIEvendor_he_op *he_ops) +{ + WMA_LOGI(FL("bss_color: %0x, default_pe_duration: %0x, twt_required: %0x, rts_threshold: %0x"), + he_ops->bss_color, he_ops->default_pe, + he_ops->twt_required, he_ops->rts_threshold); + WMA_LOGI(("\tpartial_bss_color: %0x, MaxBSSID Indicator: %0x, Tx BSSID Indicator: %0x, BSS color disabled: %0x, Dual beacon: %0x"), + he_ops->partial_bss_col, he_ops->maxbssid_ind, + he_ops->tx_bssid_ind, he_ops->bss_col_disabled, + he_ops->dual_beacon); +} + +/** + * wma_parse_he_ppet() - Convert PPET stored in dot11f structure into FW + * structure. + * @dot11f_ppet: pointer to dot11f format PPET + * @peer_ppet: pointer peer_ppet to be sent in peer assoc + * + * This function converts the sequence of PPET stored in the host in OTA type + * structure into FW understandable structure to be sent as part of peer assoc + * command. + */ +static void wma_parse_he_ppet(tDot11fIEppe_threshold *dot11f_ppet, + struct wmi_host_ppe_threshold *peer_ppet) +{ + uint8_t num_ppet, mask, mask1, mask2; + uint32_t ppet1, ppet2, ppet; + uint8_t bits, pad, pad_bits, req_byte; + uint8_t byte_idx, start, i, j, parsed; + uint32_t *ppet_r = peer_ppet->ppet16_ppet8_ru3_ru0; + uint8_t *rcvd_ppet; + uint8_t nss, ru; + + nss = dot11f_ppet->nss_count + 1; + mask = dot11f_ppet->ru_idx_mask; + + for (ru = 0; mask; mask >>= 1) { + if (mask & 0x1) + ru++; + } + + WMA_LOGI(FL("Rcvd nss=%d ru_idx_mask: %0x ru_count=%d"), + nss, mask, ru); + + /* rcvd_ppet will store the ppet array and first byte of the ppet */ + rcvd_ppet = qdf_mem_malloc(sizeof(*rcvd_ppet) * + (dot11f_ppet->num_ppet + 1)); + if (!rcvd_ppet) { + WMA_LOGE(FL("mem alloc failed")); + return; + } + + rcvd_ppet[0] = (dot11f_ppet->ppet_b1 << 7); + qdf_mem_copy(&rcvd_ppet[1], dot11f_ppet->ppet, dot11f_ppet->num_ppet); + + peer_ppet->numss_m1 = nss - 1; + peer_ppet->ru_bit_mask = dot11f_ppet->ru_idx_mask; + + /* each nss-ru pair have 2 PPET (PPET8/PPET16) */ + bits = HE_PPET_NSS_RU_LEN + (nss + ru) * (HE_PPET_SIZE * 2); + pad = bits % HE_BYTE_SIZE; + pad_bits = HE_BYTE_SIZE - pad; + req_byte = (bits + pad_bits) / HE_BYTE_SIZE; + + /* + * PPE Threshold Field Format + * +-----------+--------------+--------------------+-------------+ + * | NSS | RU idx mask | PPE Threshold info | Padding | + * +-----------+--------------+--------------------+-------------+ + * 3 4 1 + variable variable (bits) + * + * PPE Threshold Info field: + * number of NSS:n, number of RU: m + * +------------+-----------+-----+------------+-----------+-----+-----------+-----------+ + * | PPET16 for | PPET8 for | ... | PPET16 for | PPET8 for | ... | PET16 for | PPET8 for | + * | NSS1, RU1 | NSS1, RU1 | ... | NSS1, RUm | NSS1, RUm | ... | NSSn, RUm | NSSn, RUm | + * +------------+-----------+-----+------------+-----------+-----+-----------+-----------+ + * 3 3 ... 3 3 ... 3 3 + */ + + /* first bit of first PPET is in the last bit of first byte */ + parsed = 7; + + /* + * refer wmi_ppe_threshold defn to understand how ppet is stored. + * Index of ppet array(ppet16_ppet8_ru3_ru0) is the NSS value. + * Each item in ppet16_ppet8_ru3_ru0 holds ppet for all the RUs. + */ + num_ppet = ru * 2; /* for each NSS */ + for (i = 0; i < nss; i++) { + for (j = 1; j <= num_ppet; j++) { + start = parsed + (i * (num_ppet * HE_PPET_SIZE)) + + (j-1) * HE_PPET_SIZE; + byte_idx = start / HE_BYTE_SIZE; + start = start % HE_BYTE_SIZE; + + if (start <= HE_BYTE_SIZE - HE_PPET_SIZE) { + mask = 0x07 << start; + ppet = (rcvd_ppet[byte_idx] & mask) >> start; + ppet_r[i] |= (ppet << (j - 1) * HE_PPET_SIZE); + } else { + mask1 = 0x07 << start; + ppet1 = (rcvd_ppet[byte_idx] & mask1) >> start; + mask2 = 0x07 >> (HE_BYTE_SIZE - start); + ppet2 = (rcvd_ppet[byte_idx + 1] & mask2) << + (HE_BYTE_SIZE - start); + ppet = ppet1 | ppet2; + ppet_r[i] |= (ppet << (j - 1) * HE_PPET_SIZE); + } + WMA_LOGI(FL("nss:%d ru:%d ppet_r:%0x"), i, j/2, + ppet_r[i]); + } + } + + qdf_mem_free(rcvd_ppet); +} + +/** + * wma_populate_peer_he_cap() - populate peer HE capabilities in peer assoc cmd + * @peer: pointer to peer assoc params + * @params: pointer to ADD STA params + * + * Return: None + */ +void wma_populate_peer_he_cap(struct peer_assoc_params *peer, + tpAddStaParams params) +{ + tDot11fIEvendor_he_cap *he_cap = ¶ms->he_config; + tDot11fIEvendor_he_op *he_op = ¶ms->he_op; + uint32_t *phy_cap = peer->peer_he_cap_phyinfo; + uint32_t mac_cap = 0, he_ops = 0; + uint8_t temp; + + if (params->he_capable) + peer->peer_flags |= WMI_PEER_HE; + else + return; + + /* HE MAC capabilities */ + WMI_HECAP_MAC_HECTRL_SET(mac_cap, he_cap->htc_he); + WMI_HECAP_MAC_TWTREQ_SET(mac_cap, he_cap->twt_request); + WMI_HECAP_MAC_TWTRSP_SET(mac_cap, he_cap->twt_responder); + WMI_HECAP_MAC_HEFRAG_SET(mac_cap, he_cap->fragmentation); + WMI_HECAP_MAC_MAXFRAGMSDU_SET(mac_cap, he_cap->max_num_frag_msdu); + WMI_HECAP_MAC_MINFRAGSZ_SET(mac_cap, he_cap->min_frag_size); + WMI_HECAP_MAC_TRIGPADDUR_SET(mac_cap, he_cap->trigger_frm_mac_pad); + WMI_HECAP_MAC_ACKMTIDAMPDU_SET(mac_cap, he_cap->multi_tid_aggr); + WMI_HECAP_MAC_HELKAD_SET(mac_cap, he_cap->he_link_adaptation); + WMI_HECAP_MAC_AACK_SET(mac_cap, he_cap->all_ack); + WMI_HECAP_MAC_ULMURSP_SET(mac_cap, he_cap->ul_mu_rsp_sched); + WMI_HECAP_MAC_BSR_SET(mac_cap, he_cap->a_bsr); + WMI_HECAP_MAC_BCSTTWT_SET(mac_cap, he_cap->broadcast_twt); + WMI_HECAP_MAC_32BITBA_SET(mac_cap, he_cap->ba_32bit_bitmap); + WMI_HECAP_MAC_MUCASCADE_SET(mac_cap, he_cap->mu_cascade); + WMI_HECAP_MAC_ACKMTIDAMPDU_SET(mac_cap, he_cap->ack_enabled_multitid); + WMI_HECAP_MAC_GROUPMSTABA_SET(mac_cap, he_cap->dl_mu_ba); + WMI_HECAP_MAC_OMI_SET(mac_cap, he_cap->omi_a_ctrl); + WMI_HECAP_MAC_OFDMARA_SET(mac_cap, he_cap->ofdma_ra); + WMI_HECAP_MAC_MAXAMPDULEN_EXP_SET(mac_cap, he_cap->max_ampdu_len); + WMI_HECAP_MAC_AMSDUFRAG_SET(mac_cap, he_cap->amsdu_frag); + WMI_HECAP_MAC_FLEXTWT_SET(mac_cap, he_cap->flex_twt_sched); + WMI_HECAP_MAC_MBSS_SET(mac_cap, he_cap->rx_ctrl_frame); + WMI_HECAP_MAC_BSRPAMPDU_SET(mac_cap, he_cap->bsrp_ampdu_aggr); + WMI_HECAP_MAC_QTP_SET(mac_cap, he_cap->qtp); + peer->peer_he_cap_macinfo = mac_cap; + + /* HE PHY capabilities */ + WMI_HECAP_PHY_DB_SET(phy_cap, he_cap->dual_band); + WMI_HECAP_PHY_CBW_SET(phy_cap, he_cap->chan_width); + WMI_HECAP_PHY_PREAMBLEPUNCRX_SET(phy_cap, he_cap->rx_pream_puncturing); + WMI_HECAP_PHY_COD_SET(phy_cap, he_cap->device_class); + WMI_HECAP_PHY_LDPC_SET(phy_cap, he_cap->ldpc_coding); + WMI_HECAP_PHY_LTFGIFORHE_SET(phy_cap, he_cap->he_ltf_gi_ppdu); + WMI_HECAP_PHY_LTFGIFORNDP_SET(phy_cap, he_cap->he_ltf_gi_ndp); + + temp = he_cap->stbc & 0x1; + WMI_HECAP_PHY_RXSTBC_SET(phy_cap, temp); + temp = he_cap->stbc >> 0x1; + WMI_HECAP_PHY_TXSTBC_SET(phy_cap, temp); + + temp = he_cap->doppler & 0x1; + WMI_HECAP_PHY_RXDOPPLER_SET(phy_cap, temp); + temp = he_cap->doppler >> 0x1; + WMI_HECAP_PHY_TXDOPPLER_SET(phy_cap, temp); + + WMI_HECAP_PHY_UL_MU_MIMO_SET(phy_cap, he_cap->ul_mu); + WMI_HECAP_PHY_DCMTX_SET(phy_cap, he_cap->dcm_enc_tx); + WMI_HECAP_PHY_DCMRX_SET(phy_cap, he_cap->dcm_enc_rx); + WMI_HECAP_PHY_ULHEMU_SET(phy_cap, he_cap->ul_he_mu); + WMI_HECAP_PHY_SUBFMR_SET(phy_cap, he_cap->su_beamformer); + WMI_HECAP_PHY_SUBFME_SET(phy_cap, he_cap->su_beamformee); + WMI_HECAP_PHY_MUBFMR_SET(phy_cap, he_cap->mu_beamformer); + WMI_HECAP_PHY_BFMESTSLT80MHZ_SET(phy_cap, he_cap->bfee_sts_lt_80); + WMI_HECAP_PHY_NSTSLT80MHZ_SET(phy_cap, he_cap->nsts_tol_lt_80); + WMI_HECAP_PHY_BFMESTSGT80MHZ_SET(phy_cap, he_cap->bfee_sta_gt_80); + WMI_HECAP_PHY_NSTSGT80MHZ_SET(phy_cap, he_cap->nsts_tot_gt_80); + WMI_HECAP_PHY_NUMSOUNDLT80MHZ_SET(phy_cap, he_cap->num_sounding_lt_80); + WMI_HECAP_PHY_NUMSOUNDGT80MHZ_SET(phy_cap, he_cap->num_sounding_gt_80); + WMI_HECAP_PHY_NG16SUFEEDBACKLT80_SET(phy_cap, + he_cap->su_feedback_tone16); + WMI_HECAP_PHY_NG16MUFEEDBACKGT80_SET(phy_cap, + he_cap->mu_feedback_tone16); + WMI_HECAP_PHY_CODBK42SU_SET(phy_cap, he_cap->codebook_su); + WMI_HECAP_PHY_CODBK75MU_SET(phy_cap, he_cap->codebook_mu); + WMI_HECAP_PHY_BFFEEDBACKTRIG_SET(phy_cap, he_cap->beamforming_feedback); + WMI_HECAP_PHY_HEERSU_SET(phy_cap, he_cap->he_er_su_ppdu); + WMI_HECAP_PHY_DLMUMIMOPARTIALBW_SET(phy_cap, + he_cap->dl_mu_mimo_part_bw); + WMI_HECAP_PHY_PETHRESPRESENT_SET(phy_cap, he_cap->ppet_present); + WMI_HECAP_PHY_SRPPRESENT_SET(phy_cap, he_cap->srp); + WMI_HECAP_PHY_PWRBOOSTAR_SET(phy_cap, he_cap->power_boost); + WMI_HECAP_PHY_4XLTFAND800NSECSGI_SET(phy_cap, he_cap->he_ltf_gi_4x); + + WMI_HEOPS_COLOR_SET(he_ops, he_op->bss_color); + WMI_HEOPS_DEFPE_SET(he_ops, he_op->default_pe); + WMI_HEOPS_TWT_SET(he_ops, he_op->twt_required); + WMI_HEOPS_RTSTHLD_SET(he_ops, he_op->rts_threshold); + WMI_HEOPS_PARTBSSCOLOR_SET(he_ops, he_op->partial_bss_col); + WMI_HEOPS_MAXBSSID_SET(he_ops, he_op->maxbssid_ind); + WMI_HEOPS_TXBSSID_SET(he_ops, he_op->tx_bssid_ind); + WMI_HEOPS_BSSCOLORDISABLE_SET(he_ops, he_op->bss_col_disabled); + WMI_HEOPS_DUALBEACON_SET(he_ops, he_op->dual_beacon); + peer->peer_he_ops = he_ops; + + wma_parse_he_ppet(&he_cap->ppe_threshold, &peer->peer_ppet); + + wma_print_he_cap(he_cap); + WMA_LOGI(FL("Peer HE Capabilities:")); + wma_print_he_phy_cap(phy_cap); + wma_print_he_mac_cap(mac_cap); + wma_print_he_ppet(&peer->peer_ppet); + + return; +} + +/** + * wma_update_vdev_he_ops() - update he ops in vdev start request + * @req: pointer to vdev start request + * @add_bss: pointer to ADD BSS params + * + * Return: None + */ +void wma_update_vdev_he_ops(struct wma_vdev_start_req *req, + tpAddBssParams add_bss) +{ + uint32_t he_ops = req->he_ops; + tDot11fIEvendor_he_op *he_op = &add_bss->he_op; + + req->he_capable = add_bss->he_capable; + + WMI_HEOPS_COLOR_SET(he_ops, he_op->bss_color); + WMI_HEOPS_DEFPE_SET(he_ops, he_op->default_pe); + WMI_HEOPS_TWT_SET(he_ops, he_op->twt_required); + WMI_HEOPS_RTSTHLD_SET(he_ops, he_op->rts_threshold); + WMI_HEOPS_PARTBSSCOLOR_SET(he_ops, he_op->partial_bss_col); + WMI_HEOPS_MAXBSSID_SET(he_ops, he_op->maxbssid_ind); + WMI_HEOPS_TXBSSID_SET(he_ops, he_op->tx_bssid_ind); + WMI_HEOPS_BSSCOLORDISABLE_SET(he_ops, he_op->bss_col_disabled); + WMI_HEOPS_DUALBEACON_SET(he_ops, he_op->dual_beacon); +} + +/** + * wma_copy_txrxnode_he_ops() - copy HE ops from vdev start req to txrx node + * @node: pointer to txrx node + * @req: pointer to vdev start request + * + * Return: None + */ +void wma_copy_txrxnode_he_ops(struct wma_txrx_node *node, + struct wma_vdev_start_req *req) +{ + node->he_capable = req->he_capable; + node->he_ops = req->he_ops; +} + +/** + * wma_copy_vdev_start_he_ops() - copy HE ops from vdev start req to vdev start + * @params: pointer to vdev_start_params + * @req: pointer to vdev start request + * + * Return: None + */ +void wma_copy_vdev_start_he_ops(struct vdev_start_params *params, + struct wma_vdev_start_req *req) +{ + params->he_ops = req->he_ops; +} + +/** + * wma_vdev_set_he_bss_params() - set HE OPs in vdev start + * @wma: pointer to wma handle + * @vdev_id: VDEV id + * @req: pointer to vdev start request + * + * Return: None + */ +void wma_vdev_set_he_bss_params(tp_wma_handle wma, uint8_t vdev_id, + struct wma_vdev_start_req *req) +{ + QDF_STATUS ret; + struct wma_txrx_node *intr = wma->interfaces; + + if (!req->he_capable) + return; + + ret = wma_vdev_set_param(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_HEOPS_0_31, req->he_ops); + + if (QDF_IS_STATUS_ERROR(ret)) + WMA_LOGE(FL("Failed to set HE OPs")); + else + intr[vdev_id].he_ops = req->he_ops; +} + +/** + * wma_update_vdev_he_capable() - update vdev start request he capability + * @req: pointer to vdev start request + * @params: pointer to chan switch params + * + * Return: None + */ +void wma_update_vdev_he_capable(struct wma_vdev_start_req *req, + tpSwitchChannelParams params) +{ + req->he_capable = params->he_capable; +} diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 0a3b5db7d7a8..5830f20506de 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -77,6 +77,7 @@ #include "wlan_objmgr_vdev_obj.h" #include "wlan_lmac_if_api.h" #include +#include "wma_he.h" /** * wma_send_bcn_buf_ll() - prepare and send beacon buffer to fw for LL @@ -948,6 +949,7 @@ QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma, uint32_t peer_nss = 1; uint32_t disable_abg_rate; struct wma_txrx_node *intr = NULL; + bool is_he; QDF_STATUS status; cmd = qdf_mem_malloc(sizeof(struct peer_assoc_params)); @@ -972,10 +974,10 @@ QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma, qdf_mem_zero(&peer_ht_rates, sizeof(wmi_rate_set)); qdf_mem_zero(cmd, sizeof(struct peer_assoc_params)); + is_he = wma_is_peer_he_capable(params); phymode = wma_peer_phymode(nw_type, params->staType, - params->htCapable, - params->ch_width, - params->vhtCapable); + params->htCapable, params->ch_width, + params->vhtCapable, is_he); if (wlan_cfg_get_int(wma->mac_context, WNI_CFG_DISABLE_ABG_RATE_FOR_TX_DATA, @@ -1235,6 +1237,8 @@ QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma, */ wma_update_txrx_chainmask(wma->num_rf_chains, &cmd->peer_nss); + wma_populate_peer_he_cap(cmd, params); + intr->nss = cmd->peer_nss; cmd->peer_phymode = phymode; WMA_LOGD("%s: vdev_id %d associd %d peer_flags %x rate_caps %x " diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 324711f74988..60df1d1875c1 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -72,6 +72,8 @@ /* This is temporary, should be removed */ #include "ol_htt_api.h" #include +#include "wma_he.h" + #define WMA_MCC_MIRACAST_REST_TIME 400 #define WMA_SCAN_ID_MASK 0x0fff @@ -2938,13 +2940,13 @@ void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params) req.is_quarter_rate = 1; req.vht_capable = params->vhtCapable; - req.he_capable = params->he_capable; req.ch_center_freq_seg0 = params->ch_center_freq_seg0; req.ch_center_freq_seg1 = params->ch_center_freq_seg1; req.dot11_mode = params->dot11_mode; + wma_update_vdev_he_capable(&req, params); - WMA_LOGI(FL("vht_capable: %d, he_capable: %d, dot11_mode: %d"), - req.vht_capable, req.he_capable, req.dot11_mode); + WMA_LOGI(FL("vht_capable: %d, dot11_mode: %d"), + req.vht_capable, req.dot11_mode); status = wma_get_current_hw_mode(&hw_mode); if (!QDF_IS_STATUS_SUCCESS(status)) diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 438a863c1679..91bfda4f0887 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -2075,44 +2075,54 @@ bool wma_is_sta_active(tp_wma_handle wma_handle) * @nw_type: nw type * @sta_type: sta type * @is_ht: is ht supported - * @is_cw40: is channel width 40 supported + * @ch_width: supported channel width * @is_vht: is vht supported - * @is_cw_vht: is channel width 80 supported + * @is_he: is HE supported * * Return: WLAN_PHY_MODE */ WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type, uint8_t is_ht, uint8_t ch_width, - uint8_t is_vht) + uint8_t is_vht, bool is_he) { WLAN_PHY_MODE phymode = MODE_UNKNOWN; switch (nw_type) { case eSIR_11B_NW_TYPE: phymode = MODE_11B; - if (is_ht || is_vht) + if (is_ht || is_vht || is_he) WMA_LOGE("HT/VHT is enabled with 11B NW type"); break; case eSIR_11G_NW_TYPE: - if (!(is_ht || is_vht)) { + if (!(is_ht || is_vht || is_he)) { phymode = MODE_11G; break; } if (CH_WIDTH_40MHZ < ch_width) WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz"); if (ch_width) - phymode = (is_vht) ? - MODE_11AC_VHT40_2G : MODE_11NG_HT40; + phymode = (is_he) ? MODE_11AX_HE40_2G : (is_vht) ? + MODE_11AC_VHT40_2G : MODE_11NG_HT40; else - phymode = (is_vht) ? - MODE_11AC_VHT20_2G : MODE_11NG_HT20; + phymode = (is_he) ? MODE_11AX_HE20_2G : (is_vht) ? + MODE_11AC_VHT20_2G : MODE_11NG_HT20; break; case eSIR_11A_NW_TYPE: - if (!(is_ht || is_vht)) { + if (!(is_ht || is_vht || is_he)) { phymode = MODE_11A; break; } - if (is_vht) { + if (is_he) { + if (ch_width == CH_WIDTH_160MHZ) + phymode = MODE_11AX_HE160; + else if (ch_width == CH_WIDTH_80P80MHZ) + phymode = MODE_11AX_HE80_80; + else if (ch_width == CH_WIDTH_80MHZ) + phymode = MODE_11AX_HE80; + else + phymode = (ch_width) ? + MODE_11AX_HE40 : MODE_11AX_HE20; + } else if (is_vht) { if (ch_width == CH_WIDTH_160MHZ) phymode = MODE_11AC_VHT160; else if (ch_width == CH_WIDTH_80P80MHZ) @@ -2129,8 +2139,8 @@ WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type, WMA_LOGP("%s: Invalid nw type %d", __func__, nw_type); break; } - WMA_LOGD("%s: nw_type %d is_ht %d ch_width %d is_vht %d phymode %d", - __func__, nw_type, is_ht, ch_width, is_vht, phymode); + WMA_LOGD(FL("nw_type %d is_ht %d ch_width %d is_vht %d is_he %d phymode %d"), + nw_type, is_ht, ch_width, is_vht, is_he, phymode); return phymode; }