diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h index cd715f87b7..c2cfcc4997 100644 --- a/components/mlme/core/inc/wlan_mlme_main.h +++ b/components/mlme/core/inc/wlan_mlme_main.h @@ -431,6 +431,7 @@ struct wait_for_key_timer { * @ba_2k_jump_iot_ap: This is set to true if connected to the ba 2k jump IOT AP * @is_usr_ps_enabled: Is Power save enabled * @notify_co_located_ap_upt_rnr: Notify co located AP to update RNR or not + * @max_mcs_index: Max supported mcs index of vdev */ struct mlme_legacy_priv { bool chan_switch_in_progress; @@ -472,6 +473,9 @@ struct mlme_legacy_priv { bool ba_2k_jump_iot_ap; bool is_usr_ps_enabled; bool notify_co_located_ap_upt_rnr; +#ifdef WLAN_FEATURE_SON + uint8_t max_mcs_index; +#endif }; /** diff --git a/components/mlme/dispatcher/inc/wlan_mlme_api.h b/components/mlme/dispatcher/inc/wlan_mlme_api.h index 487febb278..f732ef949d 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -3520,4 +3520,46 @@ wlan_mlme_get_user_mcc_duty_cycle_percentage(struct wlan_objmgr_psoc *psoc) return 0; } #endif /* WLAN_FEATURE_MCC_QUOTA */ + +/** + * mlme_get_max_he_mcs_idx() - get max mcs index from he cap information + * @mcs_ch_width: channel width + * @hecap_rxmcsnssmap: rx mcs map from he cap + * @hecap_txmcsnssmap: tx mcs map from he cap + * + * Return: the maximum MCS supported + */ +uint8_t mlme_get_max_he_mcs_idx(enum phy_ch_width mcs_ch_width, + u_int16_t *hecap_rxmcsnssmap, + u_int16_t *hecap_txmcsnssmap); + +/** + * mlme_get_max_vht_mcs_idx() - get max mcs index from vht cap information + * @rx_vht_mcs_map: rx mcs map from vht cap + * @tx_vht_mcs_map: tx mcs map from vht cap + * + * Return: the maximum MCS supported + */ +uint8_t mlme_get_max_vht_mcs_idx(u_int16_t rx_vht_mcs_map, + u_int16_t tx_vht_mcs_map); + +#ifdef WLAN_FEATURE_SON +/** + * mlme_set_vdev_max_mcs_idx() - Save max mcs index of vdev + * @vdev: pointer to vdev object + * @max_mcs_idx: max_mcs_idx to save + * + * Return: QDF Status + */ +QDF_STATUS mlme_save_vdev_max_mcs_idx(struct wlan_objmgr_vdev *vdev, + uint8_t max_mcs_idx); + +/** + * mlme_get_vdev_max_mcs_idx() - Get max mcs index of vdev + * @vdev: pointer to vdev object + * + * Return max mcs index of vdev + */ +uint8_t mlme_get_vdev_max_mcs_idx(struct wlan_objmgr_vdev *vdev); +#endif /* WLAN_FEATURE_SON */ #endif /* _WLAN_MLME_API_H_ */ diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 80e020eefb..6cd2529b7c 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -104,6 +104,11 @@ /* Default beacon interval of 100 ms */ #define CUSTOM_CONC_GO_BI 100 +#define HECAP_TXRX_MCS_NSS_IDX_80 (0) +#define HECAP_TXRX_MCS_NSS_IDX_160 (1) +#define HECAP_TXRX_MCS_NSS_IDX_80_80 (2) +#define INVALID_MCS_NSS_INDEX 0xff + enum diagwlan_status_eventsubtype { DIAG_WLAN_STATUS_CONNECT = 0, DIAG_WLAN_STATUS_DISCONNECT diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 09d156ebea..082a0f7612 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -4530,4 +4530,18 @@ ucfg_mlme_get_wds_mode(struct wlan_objmgr_psoc *psoc) { return wlan_mlme_get_wds_mode(psoc); } + +#ifdef WLAN_FEATURE_SON +/** + * ucfg_mlme_get_vdev_max_mcs_idx() - Get max mcs idx of given vdev + * @vdev: pointer to vdev object + * + * Return: max mcs idx of given vdev + */ +static inline uint8_t +ucfg_mlme_get_vdev_max_mcs_idx(struct wlan_objmgr_vdev *vdev) +{ + return mlme_get_vdev_max_mcs_idx(vdev); +} +#endif /* WLAN_FEATURE_SON */ #endif /* _WLAN_MLME_UCFG_API_H_ */ diff --git a/components/mlme/dispatcher/src/wlan_mlme_api.c b/components/mlme/dispatcher/src/wlan_mlme_api.c index 44223ec4a8..fb84221eb9 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -5607,3 +5607,101 @@ wlan_mlme_get_user_mcc_duty_cycle_percentage(struct wlan_objmgr_psoc *psoc) return quota_value; } #endif /* WLAN_FEATURE_MCC_QUOTA */ + +uint8_t mlme_get_max_he_mcs_idx(enum phy_ch_width mcs_ch_width, + u_int16_t *hecap_rxmcsnssmap, + u_int16_t *hecap_txmcsnssmap) +{ + uint8_t rx_max_mcs, tx_max_mcs, max_mcs = INVALID_MCS_NSS_INDEX; + + switch (mcs_ch_width) { + case CH_WIDTH_80P80MHZ: + if (hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80] && + hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80]) { + rx_max_mcs = hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80] & 0x03; + tx_max_mcs = hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80] & 0x03; + max_mcs = rx_max_mcs < tx_max_mcs ? rx_max_mcs : tx_max_mcs; + if (max_mcs < 0x03) + max_mcs = 7 + 2 * max_mcs; + } + /* fallthrough */ + case CH_WIDTH_160MHZ: + if (hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160] && + hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160]) { + rx_max_mcs = hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160] & 0x03; + tx_max_mcs = hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160] & 0x03; + max_mcs = rx_max_mcs < tx_max_mcs ? rx_max_mcs : tx_max_mcs; + if (max_mcs < 0x03) + max_mcs = 7 + 2 * max_mcs; + } + /* fallthrough */ + default: + if (hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80] && + hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80]) { + rx_max_mcs = hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80] & 0x03; + tx_max_mcs = hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80] & 0x03; + max_mcs = rx_max_mcs < tx_max_mcs ? rx_max_mcs : tx_max_mcs; + if (max_mcs < 0x03) + max_mcs = 7 + 2 * max_mcs; + } + } + + return max_mcs; +} + +uint8_t mlme_get_max_vht_mcs_idx(u_int16_t rx_vht_mcs_map, + u_int16_t tx_vht_mcs_map) +{ + uint8_t rx_max_mcs, tx_max_mcs, max_mcs = INVALID_MCS_NSS_INDEX; + + if (rx_vht_mcs_map && tx_vht_mcs_map) { + rx_max_mcs = rx_vht_mcs_map & 0x03; + tx_max_mcs = tx_vht_mcs_map & 0x03; + max_mcs = rx_max_mcs < tx_max_mcs ? rx_max_mcs : tx_max_mcs; + if (max_mcs < 0x03) + return 7 + max_mcs; + } + + return max_mcs; +} + +#ifdef WLAN_FEATURE_SON +QDF_STATUS mlme_save_vdev_max_mcs_idx(struct wlan_objmgr_vdev *vdev, + uint8_t max_mcs_idx) +{ + struct mlme_legacy_priv *mlme_priv; + + if (!vdev) { + mlme_legacy_err("invalid vdev"); + return QDF_STATUS_E_INVAL; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + mlme_priv->max_mcs_index = max_mcs_idx; + + return QDF_STATUS_SUCCESS; +} + +uint8_t mlme_get_vdev_max_mcs_idx(struct wlan_objmgr_vdev *vdev) +{ + struct mlme_legacy_priv *mlme_priv; + + if (!vdev) { + mlme_legacy_err("invalid vdev"); + return INVALID_MCS_NSS_INDEX; + } + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return INVALID_MCS_NSS_INDEX; + } + + return mlme_priv->max_mcs_index; +} +#endif /* WLAN_FEATURE_SON */ diff --git a/components/son/dispatcher/inc/son_api.h b/components/son/dispatcher/inc/son_api.h index 9d23122446..e6a2311133 100644 --- a/components/son/dispatcher/inc/son_api.h +++ b/components/son/dispatcher/inc/son_api.h @@ -447,19 +447,6 @@ int wlan_son_anqp_frame(struct wlan_objmgr_vdev *vdev, int subtype, */ uint8_t wlan_son_get_node_tx_power(struct element_info assoc_req_ies); -/** - * wlan_son_get_max_mcs() - calculate the max mcs supported by the node - * @mode: current phymode - * @supp_idx: max supported idx - * @ext_idx: max extended idx - * @ht_mcs_idx: max mcs index for HT - * @vht_mcs_map: mcs map for VHT - * - * return: max_mcs for the node - */ -uint8_t wlan_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, - uint8_t ht_mcs_idx, uint8_t vht_mcs_map); - /** * wlan_son_get_peer_rrm_info() - Get RRM info for peer * @assoc_req_ies: assoc req ies @@ -548,13 +535,6 @@ uint8_t wlan_son_get_node_tx_power(struct element_info assoc_req_ies) return 0; } -static inline -uint8_t wlan_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, - uint8_t ht_mcs_idx, uint8_t vht_mcs_map) -{ - return 0; -} - static inline QDF_STATUS wlan_son_get_peer_rrm_info(struct element_info assoc_req_ies, uint8_t *rrmcaps, diff --git a/components/son/dispatcher/inc/son_ucfg_api.h b/components/son/dispatcher/inc/son_ucfg_api.h index efebee1e51..6532f549f0 100644 --- a/components/son/dispatcher/inc/son_ucfg_api.h +++ b/components/son/dispatcher/inc/son_ucfg_api.h @@ -178,19 +178,6 @@ int ucfg_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev, */ uint8_t ucfg_son_get_tx_power(struct element_info assoc_req_ies); -/** - * ucfg_get_max_mcs() - calculate the max mcs supported by the node - * @mode: current phy mode - * @supp_idx: max supported idx - * @ext_idx: max extended idx - * @ht_mcs_idx: max mcs index for HT - * @vht_mcs_map: mcs map for VHT - * - * Return: max_mcs for the node - */ -uint8_t ucfg_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, - uint8_t ht_mcs_idx, uint8_t vht_mcs_map); - /** * ucfg_son_get_peer_rrm_info() - Get RRM info for peer * @assoc_req_ies: assoc req ies diff --git a/components/son/dispatcher/src/son_api.c b/components/son/dispatcher/src/son_api.c index 6a9501d678..dd9f3b9a2c 100644 --- a/components/son/dispatcher/src/son_api.c +++ b/components/son/dispatcher/src/son_api.c @@ -1341,29 +1341,6 @@ uint8_t wlan_son_get_node_tx_power(struct element_info assoc_req_ies) return 0; } -uint8_t wlan_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, - uint8_t ht_mcs_idx, uint8_t vht_mcs_map) -{ - uint8_t maxidx = MAX_HE_MCS_IDX; - - /* check supported rates */ - if (supp_idx != 0xff && maxidx < supp_idx) - maxidx = supp_idx; - - /* check extended rates */ - if (ext_idx != 0xff && maxidx < ext_idx) - maxidx = ext_idx; - - /* check for HT Mode */ - if (mode == SIR_SME_PHY_MODE_HT) - maxidx = ht_mcs_idx; - - if (mode == SIR_SME_PHY_MODE_VHT) - maxidx = (vht_mcs_map & DATA_RATE_11AC_MCS_MASK); - - return maxidx; -} - QDF_STATUS wlan_son_get_peer_rrm_info(struct element_info assoc_req_ies, uint8_t *rrmcaps, bool *is_beacon_meas_supported) diff --git a/components/son/dispatcher/src/son_ucfg_api.c b/components/son/dispatcher/src/son_ucfg_api.c index 860c8ad5b9..8702987416 100644 --- a/components/son/dispatcher/src/son_ucfg_api.c +++ b/components/son/dispatcher/src/son_ucfg_api.c @@ -130,13 +130,6 @@ uint8_t ucfg_son_get_tx_power(struct element_info assoc_req_ies) return wlan_son_get_node_tx_power(assoc_req_ies); } -uint8_t ucfg_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, - uint8_t ht_mcs_idx, uint8_t vht_mcs_map) -{ - return wlan_son_get_max_mcs(mode, supp_idx, ext_idx, ht_mcs_idx, - vht_mcs_map); -} - QDF_STATUS ucfg_son_get_peer_rrm_info(struct element_info assoc_req_ies, uint8_t *rrmcaps, bool *is_beacon_meas_supported) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 5dbccbb08e..373993492c 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1589,6 +1589,7 @@ static void hdd_fill_station_info(struct hdd_adapter *adapter, stainfo->max_supp_idx = event->max_supp_idx; stainfo->max_ext_idx = event->max_ext_idx; stainfo->max_mcs_idx = event->max_mcs_idx; + stainfo->max_real_mcs_idx = event->max_real_mcs_idx; stainfo->rx_mcs_map = event->rx_mcs_map; stainfo->tx_mcs_map = event->tx_mcs_map; stainfo->assoc_ts = qdf_system_ticks(); diff --git a/core/hdd/src/wlan_hdd_son.c b/core/hdd/src/wlan_hdd_son.c index ccab39ff96..050afee123 100644 --- a/core/hdd/src/wlan_hdd_son.c +++ b/core/hdd/src/wlan_hdd_son.c @@ -2303,11 +2303,11 @@ static QDF_STATUS hdd_son_get_node_info(struct wlan_objmgr_vdev *vdev, ucfg_mlme_get_peer_phymode(psoc, mac_addr, &peer_phymode); node_info->phymode = wlan_hdd_son_get_ieee_phymode(peer_phymode); node_info->max_txpower = ucfg_son_get_tx_power(sta_info->assoc_req_ies); - node_info->max_MCS = ucfg_son_get_max_mcs(sta_info->mode, - sta_info->max_supp_idx, - sta_info->max_ext_idx, - sta_info->max_mcs_idx, - sta_info->rx_mcs_map); + node_info->max_MCS = sta_info->max_real_mcs_idx; + if (node_info->max_MCS == INVALID_MCS_NSS_INDEX) { + hdd_err("invalid mcs"); + return QDF_STATUS_E_FAILURE; + } if (sta_info->vht_present) node_info->is_mu_mimo_supported = sta_info->vht_caps.vht_cap_info @@ -2397,7 +2397,7 @@ uint32_t hdd_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev, return ret; } - ret = sta_info->max_mcs_idx; + ret = sta_info->max_real_mcs_idx; hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true, STA_INFO_SOFTAP_GET_STA_INFO); diff --git a/core/hdd/src/wlan_hdd_sta_info.h b/core/hdd/src/wlan_hdd_sta_info.h index b6221d8c8c..4cf4e406d6 100644 --- a/core/hdd/src/wlan_hdd_sta_info.h +++ b/core/hdd/src/wlan_hdd_sta_info.h @@ -202,7 +202,10 @@ char *sta_info_string_from_dbgid(wlan_sta_info_dbgid id); * @mode: Mode of the connection * @max_supp_idx: Max supported rate index of the station * @max_ext_idx: Max extended supported rate index of the station - * @max_mcs_idx: Max supported mcs index of the station + * @max_mcs_idx: Max supported mcs index from ht cap of the station + * @max_real_mcs_idx: Max supported mcs index from biggest cap of the station. + * For example, if station supports HE , first check he cap, + * then vht cap and so on. * @rx_mcs_map: VHT Rx mcs map * @tx_mcs_map: VHT Tx mcs map * @freq : Frequency of the current station @@ -273,6 +276,7 @@ struct hdd_station_info { uint8_t max_supp_idx; uint8_t max_ext_idx; uint8_t max_mcs_idx; + uint8_t max_real_mcs_idx; uint8_t rx_mcs_map; uint8_t tx_mcs_map; uint32_t freq; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 64f70e3d8d..a2fd4823d7 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -993,6 +993,7 @@ struct assoc_ind { uint8_t max_supp_idx; uint8_t max_ext_idx; uint8_t max_mcs_idx; + uint8_t max_real_mcs_idx; uint8_t rx_mcs_map; uint8_t tx_mcs_map; /* Extended CSA capability of station */ 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 a737737e34..d51b32c41a 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 @@ -2872,20 +2872,6 @@ static void lim_fill_assoc_ind_info(struct mac_context *mac_ctx, return; } -static uint8_t lim_get_max_rate_idx(tSirMacRateSet *rateset) -{ - uint8_t maxidx; - int i; - - maxidx = rateset->rate[0] & 0x7f; - for (i = 1; i < rateset->numRates; i++) { - if ((rateset->rate[i] & 0x7f) > maxidx) - maxidx = rateset->rate[i] & 0x7f; - } - - return maxidx; -} - static void fill_mlm_assoc_ind_vht(tpSirAssocReq assocreq, tpDphHashNode stads, tpLimMlmAssocInd assocind) @@ -2964,6 +2950,42 @@ static void lim_fill_assoc_ind_he_bw_info(tpLimMlmAssocInd assoc_ind, } } +/** + * lim_fill_assoc_ind_real_max_mcs_idx() - fill max real mcs index to assoc ind + * @assoc_ind: assoc_ind to fill + * @assoc_req: pointer to tpSirAssocReq + * @sta_ds: pointer to tpDphHashNode + * @session: pointer to session + * + * Return: void + */ +static void lim_fill_assoc_ind_real_max_mcs_idx(tpLimMlmAssocInd assoc_ind, + tpSirAssocReq assoc_req, + tpDphHashNode sta_ds, + struct pe_session *session) +{ + assoc_ind->max_real_mcs_idx = INVALID_MCS_NSS_INDEX; + + if (lim_is_sta_he_capable(sta_ds) && + lim_is_session_he_capable(session)) + assoc_ind->max_real_mcs_idx = lim_get_he_max_mcs_idx( + sta_ds->ch_width, &assoc_req->he_cap); + + if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX && + sta_ds->mlmStaContext.vhtCapability) + assoc_ind->max_real_mcs_idx = + lim_get_vht_max_mcs_idx(&assoc_req->VHTCaps); + + if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX) + assoc_ind->max_real_mcs_idx = assoc_ind->max_mcs_idx; + + if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX) + assoc_ind->max_real_mcs_idx = assoc_ind->max_ext_idx; + + if (assoc_ind->max_real_mcs_idx == INVALID_MCS_NSS_INDEX) + assoc_ind->max_real_mcs_idx = assoc_ind->max_supp_idx; +} + bool lim_fill_lim_assoc_ind_params( tpLimMlmAssocInd assoc_ind, struct mac_context *mac_ctx, @@ -2974,7 +2996,6 @@ bool lim_fill_lim_assoc_ind_params( uint16_t rsn_len; uint32_t phy_mode; const uint8_t *wpsie = NULL; - uint8_t maxidx, i; bool wme_enable; struct wlan_objmgr_vdev *vdev; struct vdev_mlme_obj *mlme_obj; @@ -3132,9 +3153,9 @@ bool lim_fill_lim_assoc_ind_params( assoc_ind->rx_stbc = false; assoc_ind->ch_width = eHT_CHANNEL_WIDTH_20MHZ; assoc_ind->mode = SIR_SME_PHY_MODE_LEGACY; - assoc_ind->max_supp_idx = 0xff; - assoc_ind->max_ext_idx = 0xff; - assoc_ind->max_mcs_idx = 0xff; + assoc_ind->max_supp_idx = INVALID_MCS_NSS_INDEX; + assoc_ind->max_ext_idx = INVALID_MCS_NSS_INDEX; + assoc_ind->max_mcs_idx = INVALID_MCS_NSS_INDEX; assoc_ind->rx_mcs_map = 0xff; assoc_ind->tx_mcs_map = 0xff; @@ -3164,13 +3185,8 @@ bool lim_fill_lim_assoc_ind_params( eHT_CHANNEL_WIDTH_20MHZ; /* mode */ assoc_ind->mode = SIR_SME_PHY_MODE_HT; - maxidx = 0; - for (i = 0; i < 8; i++) { - if (assoc_req->HTCaps.supportedMCSSet[0] & - (1 << i)) - maxidx = i; - } - assoc_ind->max_mcs_idx = maxidx; + assoc_ind->max_mcs_idx = lim_get_ht_max_mcs_idx( + &assoc_req->HTCaps); } fill_mlm_assoc_ind_vht(assoc_req, sta_ds, assoc_ind); if (assoc_req->ExtCap.present) { @@ -3218,6 +3234,8 @@ bool lim_fill_lim_assoc_ind_params( assoc_req->is_sae_authenticated; /* updates HE bandwidth in assoc indication */ lim_fill_assoc_ind_he_bw_info(assoc_ind, sta_ds, session_entry); + lim_fill_assoc_ind_real_max_mcs_idx(assoc_ind, assoc_req, + sta_ds, session_entry); vdev = session_entry->vdev; if (!vdev) diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 38db27b39b..dfff1db27a 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -787,6 +787,7 @@ lim_fill_sme_assoc_ind_params( sme_assoc_ind->max_supp_idx = assoc_ind->max_supp_idx; sme_assoc_ind->max_ext_idx = assoc_ind->max_ext_idx; sme_assoc_ind->max_mcs_idx = assoc_ind->max_mcs_idx; + sme_assoc_ind->max_real_mcs_idx = assoc_ind->max_real_mcs_idx; sme_assoc_ind->rx_mcs_map = assoc_ind->rx_mcs_map; sme_assoc_ind->tx_mcs_map = assoc_ind->tx_mcs_map; sme_assoc_ind->ecsa_capable = assoc_ind->ecsa_capable; 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 d10d56657d..4a1d6ee496 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 @@ -741,6 +741,58 @@ static inline void lim_fill_cc_mode(struct mac_context *mac_ctx, } #endif +#ifdef WLAN_FEATURE_SON +/** + * lim_save_max_mcs_idx() - save max mcs index to mlme component + * @mac_ctx: Pointer to Global MAC structure + * @session: pointer to pe session + * + * Return: void + */ +static void +lim_save_max_mcs_idx(struct mac_context *mac_ctx, struct pe_session *session) +{ + tDot11fIEVHTCaps vht_cap; + tDot11fIEhe_cap he_cap; + tDot11fIEHTCaps ht_cap; + u_int8_t session_max_mcs_idx = INVALID_MCS_NSS_INDEX; + + if (IS_DOT11_MODE_HE(session->dot11mode)) { + qdf_mem_zero(&he_cap, sizeof(tDot11fIEhe_cap)); + populate_dot11f_he_caps(mac_ctx, session, &he_cap); + session_max_mcs_idx = lim_get_he_max_mcs_idx(session->ch_width, + &he_cap); + } + if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX && + IS_DOT11_MODE_VHT(session->dot11mode)) { + qdf_mem_zero(&vht_cap, sizeof(tDot11fIEVHTCaps)); + populate_dot11f_vht_caps(mac_ctx, session, &vht_cap); + session_max_mcs_idx = lim_get_vht_max_mcs_idx(&vht_cap); + } + if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX && + IS_DOT11_MODE_HT(session->dot11mode)) { + qdf_mem_zero(&ht_cap, sizeof(tDot11fIEHTCaps)); + populate_dot11f_ht_caps(mac_ctx, session, &ht_cap); + session_max_mcs_idx = lim_get_ht_max_mcs_idx(&ht_cap); + } + if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX && + session->extRateSet.numRates) + session_max_mcs_idx = + lim_get_max_rate_idx(&session->extRateSet); + + if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX && + session->rateSet.numRates) + session_max_mcs_idx = + lim_get_max_rate_idx(&session->rateSet); + + mlme_save_vdev_max_mcs_idx(session->vdev, session_max_mcs_idx); +} +#else +static void +lim_save_max_mcs_idx(struct mac_context *mac_ctx, struct pe_session *session) +{ +} +#endif /** * __lim_handle_sme_start_bss_request() - process SME_START_BSS_REQ message @@ -1146,7 +1198,7 @@ __lim_handle_sme_start_bss_request(struct mac_context *mac_ctx, uint32_t *msg_bu mac_ctx->mlme_cfg->power.local_power_constraint = 0; mlm_start_req->beacon_tx_rate = session->beacon_tx_rate; - + lim_save_max_mcs_idx(mac_ctx, session); session->limPrevSmeState = session->limSmeState; session->limSmeState = eLIM_SME_WT_START_BSS_STATE; diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index f6eb56f9ec..4a6e99ec2d 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -238,6 +238,7 @@ typedef struct sLimMlmAssocInd { uint8_t max_supp_idx; uint8_t max_ext_idx; uint8_t max_mcs_idx; + uint8_t max_real_mcs_idx; uint8_t rx_mcs_map; uint8_t tx_mcs_map; uint8_t ecsa_capable; diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 7936481e1f..7d1da7ce15 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -9989,3 +9989,71 @@ QDF_STATUS lim_pre_vdev_start(struct mac_context *mac, return lim_set_ch_phy_mode(mlme_obj->vdev, session->dot11mode); } + +uint8_t lim_get_he_max_mcs_idx(enum phy_ch_width ch_width, + tDot11fIEhe_cap *he_cap) +{ + uint16_t hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80 + 1]; + uint16_t hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80 + 1]; + + qdf_mem_zero(hecap_rxmcsnssmap, sizeof(hecap_rxmcsnssmap)); + qdf_mem_zero(hecap_txmcsnssmap, sizeof(hecap_txmcsnssmap)); + + qdf_mem_copy(&hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80], + &he_cap->rx_he_mcs_map_lt_80, + sizeof(u_int16_t)); + qdf_mem_copy(&hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80], + &he_cap->tx_he_mcs_map_lt_80, + sizeof(u_int16_t)); + if (he_cap->chan_width_2) { + qdf_mem_copy(&hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160], + &he_cap->rx_he_mcs_map_160, + sizeof(u_int16_t)); + qdf_mem_copy(&hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160], + &he_cap->tx_he_mcs_map_160, + sizeof(u_int16_t)); + } + if (he_cap->chan_width_3) { + qdf_mem_copy(&hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80], + &he_cap->rx_he_mcs_map_80_80, + sizeof(u_int16_t)); + qdf_mem_copy(&hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80], + &he_cap->tx_he_mcs_map_80_80, + sizeof(u_int16_t)); + } + + return mlme_get_max_he_mcs_idx(ch_width, hecap_rxmcsnssmap, + hecap_txmcsnssmap); +} + +uint8_t lim_get_vht_max_mcs_idx(tDot11fIEVHTCaps *vht_cap) +{ + return mlme_get_max_vht_mcs_idx(vht_cap->rxMCSMap & 0xff, + vht_cap->txMCSMap & 0xff); +} + +uint8_t lim_get_ht_max_mcs_idx(tDot11fIEHTCaps *ht_cap) +{ + uint8_t i, maxidx = INVALID_MCS_NSS_INDEX; + + for (i = 0; i < 8; i++) { + if (ht_cap->supportedMCSSet[0] & (1 << i)) + maxidx = i; + } + + return maxidx; +} + +uint8_t lim_get_max_rate_idx(tSirMacRateSet *rateset) +{ + uint8_t maxidx; + int i; + + maxidx = rateset->rate[0] & 0x7f; + for (i = 1; i < rateset->numRates; i++) { + if ((rateset->rate[i] & 0x7f) > maxidx) + maxidx = rateset->rate[i] & 0x7f; + } + + return maxidx; +} diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index 31e1c4d42e..742710d886 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -2817,4 +2817,37 @@ static inline void lim_process_sae_msg(struct mac_context *mac, void *body); {} #endif +/** + * lim_get_he_max_mcs_idx() - get max mcs index from he cap + * @ch_width: channel width + * @he_cap: pointer to tDot11fIEhe_cap + * + * Return: max mcs index from he cap + */ +uint8_t lim_get_he_max_mcs_idx(enum phy_ch_width ch_width, + tDot11fIEhe_cap *he_cap); + +/** + * lim_get_vht_max_mcs_idx() - get max mcs index from vht cap + * @vht_cap: pointer to tDot11fIEVHTCaps + * + * Return: max mcs index from vht cap + */ +uint8_t lim_get_vht_max_mcs_idx(tDot11fIEVHTCaps *vht_cap); + +/** + * lim_get_ht_max_mcs_idx() - get max mcs index from ht cap + * @ht_cap: pointer to tDot11fIEHTCaps + * + * Return: max mcs index from ht cap + */ +uint8_t lim_get_ht_max_mcs_idx(tDot11fIEHTCaps *ht_cap); + +/** + * lim_get_max_rate_idx() - get max rate index from tSirMacRateSet + * @rateset: pointer to tSirMacRateSet + * + * Return: max rate index from tSirMacRateSet + */ +uint8_t lim_get_max_rate_idx(tSirMacRateSet *rateset); #endif /* __LIM_UTILS_H */ diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index c426ce2f11..eda06d4613 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -275,6 +275,7 @@ typedef struct sap_StationAssocReassocCompleteEvent_s { uint8_t max_supp_idx; uint8_t max_ext_idx; uint8_t max_mcs_idx; + uint8_t max_real_mcs_idx; uint8_t rx_mcs_map; uint8_t tx_mcs_map; uint8_t ecsa_capable; diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 703d1b256b..8df67bac6d 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -2287,6 +2287,8 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx, reassoc_complete->max_supp_idx = csr_roaminfo->max_supp_idx; reassoc_complete->max_ext_idx = csr_roaminfo->max_ext_idx; reassoc_complete->max_mcs_idx = csr_roaminfo->max_mcs_idx; + reassoc_complete->max_real_mcs_idx = + csr_roaminfo->max_real_mcs_idx; reassoc_complete->rx_mcs_map = csr_roaminfo->rx_mcs_map; reassoc_complete->tx_mcs_map = csr_roaminfo->tx_mcs_map; reassoc_complete->ecsa_capable = csr_roaminfo->ecsa_capable; diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index f68c8cb29a..6183a054a4 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -574,6 +574,7 @@ struct csr_roam_info { enum sir_sme_phy_mode mode; uint8_t max_supp_idx; uint8_t max_ext_idx; + uint8_t max_real_mcs_idx; uint8_t max_mcs_idx; uint8_t rx_mcs_map; uint8_t tx_mcs_map; @@ -620,6 +621,7 @@ typedef struct sSirSmeAssocIndToUpperLayerCnf { uint8_t max_supp_idx; uint8_t max_ext_idx; uint8_t max_mcs_idx; + uint8_t max_real_mcs_idx; uint8_t rx_mcs_map; uint8_t tx_mcs_map; /* Extended capabilities of STA */ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 000f80fe3b..f9286eaa76 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -3253,6 +3253,8 @@ void csr_roam_joined_state_msg_processor(struct mac_context *mac, void *msg_buf) roam_info->max_supp_idx = pUpperLayerAssocCnf->max_supp_idx; roam_info->max_ext_idx = pUpperLayerAssocCnf->max_ext_idx; roam_info->max_mcs_idx = pUpperLayerAssocCnf->max_mcs_idx; + roam_info->max_real_mcs_idx = + pUpperLayerAssocCnf->max_real_mcs_idx; roam_info->rx_mcs_map = pUpperLayerAssocCnf->rx_mcs_map; roam_info->tx_mcs_map = pUpperLayerAssocCnf->tx_mcs_map; roam_info->ecsa_capable = pUpperLayerAssocCnf->ecsa_capable; @@ -3776,6 +3778,7 @@ csr_send_assoc_ind_to_upper_layer_cnf_msg(struct mac_context *mac, cnf->max_supp_idx = ind->max_supp_idx; cnf->max_ext_idx = ind->max_ext_idx; cnf->max_mcs_idx = ind->max_mcs_idx; + cnf->max_real_mcs_idx = ind->max_real_mcs_idx; cnf->rx_mcs_map = ind->rx_mcs_map; cnf->tx_mcs_map = ind->tx_mcs_map; cnf->ecsa_capable = ind->ecsa_capable; diff --git a/os_if/son/src/os_if_son.c b/os_if/son/src/os_if_son.c index d5ba11cc87..0d2513ffce 100644 --- a/os_if/son/src/os_if_son.c +++ b/os_if/son/src/os_if_son.c @@ -1763,7 +1763,11 @@ QDF_STATUS os_if_son_get_node_datarate_info(struct wlan_objmgr_vdev *vdev, ucfg_son_get_min_and_max_power(psoc, &max_tx_power, &min_tx_power); node_info->max_txpower = max_tx_power; - node_info->max_MCS = MAX_HE_MCS_IDX; + node_info->max_MCS = ucfg_mlme_get_vdev_max_mcs_idx(vdev); + if (node_info->max_MCS == INVALID_MCS_NSS_INDEX) { + osif_err("invalid mcs index"); + return QDF_STATUS_E_INVAL; + } osif_debug("node info: max_chwidth: %u, phymode: %u, num_streams: %d, max_mcs: %d, max_txpower: %d", node_info->max_chwidth, node_info->phymode, node_info->num_streams, node_info->max_MCS,