From f1d815920862621824ab77d861f39aa0d43f1a22 Mon Sep 17 00:00:00 2001 From: Jingxiang Ge Date: Sun, 20 Oct 2019 12:03:22 +0800 Subject: [PATCH] qcacld-3.0: config 11ax linkspeed rate This change is to support 11ax linkspeed rate on UI. It supports different config for gReportMaxLinkSpeed. Current 11ax rate support to max 80 nss2 mcs11. Change-Id: Iff8cbafe1354ab50c4b3a90ef8ab698a3350a21d CRs-Fixed: 2529291 --- core/hdd/inc/wlan_hdd_main.h | 2 +- core/hdd/src/wlan_hdd_station_info.c | 3 +- core/hdd/src/wlan_hdd_stats.c | 338 +++++++++++++---------- core/hdd/src/wlan_hdd_stats.h | 2 +- core/mac/src/pe/lim/lim_assoc_utils.c | 4 +- core/mac/src/pe/lim/lim_utils.c | 8 + core/mac/src/pe/lim/lim_utils.h | 15 + core/sme/inc/csr_api.h | 10 +- core/sme/inc/sme_api.h | 10 +- core/sme/src/common/sme_api.c | 9 +- core/wma/inc/wma.h | 1 + core/wma/inc/wma_api.h | 10 +- core/wma/inc/wma_if.h | 2 + core/wma/inc/wma_internal.h | 24 ++ core/wma/src/wma_data.c | 82 ++++-- core/wma/src/wma_utils.c | 380 +++++++++++++++++++++----- 16 files changed, 641 insertions(+), 259 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 43c9467ad353..371d7f9a4d9a 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -815,7 +815,7 @@ struct hdd_rate_info { uint8_t mode; uint8_t nss; uint8_t mcs; - uint8_t rate_flags; + enum tx_rate_info rate_flags; }; /** diff --git a/core/hdd/src/wlan_hdd_station_info.c b/core/hdd/src/wlan_hdd_station_info.c index f73c7d3dd86f..f485fa8bce74 100644 --- a/core/hdd/src/wlan_hdd_station_info.c +++ b/core/hdd/src/wlan_hdd_station_info.c @@ -372,7 +372,8 @@ static void hdd_get_max_tx_bitrate(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter) { struct station_info sinfo; - uint8_t tx_rate_flags, tx_mcs_index, tx_nss = 1; + enum tx_rate_info tx_rate_flags; + uint8_t tx_mcs_index, tx_nss = 1; uint16_t my_tx_rate; struct hdd_station_ctx *hdd_sta_ctx; diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 4ae0476b5db9..621fc9002e49 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -162,15 +162,14 @@ static struct index_vht_data_rate_type supported_vht_mcs_rate_nss2[] = { {9, {7800, 8667}, {3600, 4000}, {1730, 1920} } }; -/*array index ponints to MCS and array value points respective rssi*/ -static int rssi_mcs_tbl[][10] = { -/*MCS 0 1 2 3 4 5 6 7 8 9*/ - {-82, -79, -77, -74, -70, -66, -65, -64, -59, -57}, /* 20 */ - {-79, -76, -74, -71, -67, -63, -62, -61, -56, -54}, /* 40 */ - {-76, -73, -71, -68, -64, -60, -59, -58, -53, -51} /* 80 */ +/*array index points to MCS and array value points respective rssi*/ +static int rssi_mcs_tbl[][12] = { +/* MCS 0 1 2 3 4 5 6 7 8 9 10 11*/ + {-82, -79, -77, -74, -70, -66, -65, -64, -59, -57, -52, -48}, /* 20 */ + {-79, -76, -74, -71, -67, -63, -62, -61, -56, -54, -49, -45}, /* 40 */ + {-76, -73, -71, -68, -64, -60, -59, -58, -53, -51, -46, -42} /* 80 */ }; - #ifdef WLAN_FEATURE_LINK_LAYER_STATS /** @@ -3346,7 +3345,7 @@ static void hdd_get_max_rate_vht(struct hdd_station_info *stainfo, * Return: None */ static void hdd_fill_bw_mcs(struct station_info *sinfo, - uint8_t rate_flags, + enum tx_rate_info rate_flags, uint8_t mcsidx, uint8_t nss, bool vht) @@ -3383,7 +3382,7 @@ static void hdd_fill_bw_mcs(struct station_info *sinfo, * Return: None */ static void hdd_fill_bw_mcs(struct station_info *sinfo, - uint8_t rate_flags, + enum tx_rate_info rate_flags, uint8_t mcsidx, uint8_t nss, bool vht) @@ -3420,7 +3419,7 @@ static void hdd_fill_bw_mcs(struct station_info *sinfo, * Return: None */ static void hdd_fill_bw_mcs_vht(struct station_info *sinfo, - uint8_t rate_flags, + enum tx_rate_info rate_flags, uint8_t mcsidx, uint8_t nss) { @@ -3513,7 +3512,7 @@ static void hdd_fill_rate_info(struct wlan_objmgr_psoc *psoc, struct hdd_station_info *stainfo, struct hdd_fw_txrx_stats *stats) { - uint8_t rate_flags; + enum tx_rate_info rate_flags; uint8_t mcsidx = 0xff; uint32_t myrate, maxrate, tmprate; int rssidx; @@ -3943,10 +3942,121 @@ static int wlan_hdd_get_station_remote(struct wiphy *wiphy, return status; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) && \ + defined(WLAN_FEATURE_11AX) +/** + * hdd_map_he_gi_to_os() - map txrate_gi to os guard interval + * @guard_interval: guard interval get from fw rate + * + * Return: os guard interval value + */ +static inline uint8_t hdd_map_he_gi_to_os(enum txrate_gi guard_interval) +{ + switch (guard_interval) { + case TXRATE_GI_0_8_US: + return NL80211_RATE_INFO_HE_GI_0_8; + case TXRATE_GI_1_6_US: + return NL80211_RATE_INFO_HE_GI_1_6; + case TXRATE_GI_3_2_US: + return NL80211_RATE_INFO_HE_GI_3_2; + default: + return NL80211_RATE_INFO_HE_GI_0_8; + } +} + +/** + * wlan_hdd_fill_os_he_rateflags() - Fill HE related rate_info + * @os_rate: rate info for os + * @rate_flags: rate flags + * @dcm: dcm from rate + * @guard_interval: guard interval from rate + * + * Return: none + */ +static void wlan_hdd_fill_os_he_rateflags(struct rate_info *os_rate, + enum tx_rate_info rate_flags, + uint8_t dcm, + enum txrate_gi guard_interval) +{ + /* as fw not yet report ofdma to host, so we doesn't + * fill RATE_INFO_BW_HE_RU. + */ + if (rate_flags & (TX_RATE_HE80 | TX_RATE_HE40 | + TX_RATE_HE20)) { + if (rate_flags & TX_RATE_HE80) + hdd_set_rate_bw(os_rate, HDD_RATE_BW_80); + else if (rate_flags & TX_RATE_HE40) + hdd_set_rate_bw(os_rate, HDD_RATE_BW_40); + + os_rate->flags |= RATE_INFO_FLAGS_HE_MCS; + + os_rate->he_gi = hdd_map_he_gi_to_os(guard_interval); + os_rate->he_dcm = dcm; + } +} +#else +static void wlan_hdd_fill_os_he_rateflags(struct rate_info *os_rate, + enum tx_rate_info rate_flags, + uint8_t dcm, + enum txrate_gi guard_interval) +{} +#endif + +/** + * wlan_hdd_fill_os_rate_info() - Fill os related rate_info + * @rate_flags: rate flags + * @legacy_rate: 802.11abg rate + * @os_rate: rate info for os + * @mcs_index: mcs + * @dcm: dcm from rate + * @guard_interval: guard interval from rate + * + * Return: none + */ +static void wlan_hdd_fill_os_rate_info(enum tx_rate_info rate_flags, + uint16_t legacy_rate, + struct rate_info *os_rate, + uint8_t mcs_index, uint8_t nss, + uint8_t dcm, + enum txrate_gi guard_interval) +{ + if (rate_flags & TX_RATE_LEGACY) { + os_rate->legacy = legacy_rate; + hdd_debug("Reporting legacy rate %d", os_rate->legacy); + return; + } + + /* assume basic BW. anything else will override this later */ + hdd_set_rate_bw(os_rate, HDD_RATE_BW_20); + os_rate->mcs = mcs_index; + os_rate->nss = nss; + + wlan_hdd_fill_os_he_rateflags(os_rate, rate_flags, dcm, guard_interval); + + if (rate_flags & (TX_RATE_VHT80 | TX_RATE_VHT40 | + TX_RATE_VHT20)) { + if (rate_flags & TX_RATE_VHT80) + hdd_set_rate_bw(os_rate, HDD_RATE_BW_80); + else if (rate_flags & TX_RATE_VHT40) + hdd_set_rate_bw(os_rate, HDD_RATE_BW_40); + os_rate->flags |= RATE_INFO_FLAGS_VHT_MCS; + } + + if (rate_flags & (TX_RATE_HT20 | TX_RATE_HT40)) { + if (rate_flags & TX_RATE_HT40) + hdd_set_rate_bw(os_rate, + HDD_RATE_BW_40); + os_rate->flags |= RATE_INFO_FLAGS_MCS; + } + + if (rate_flags & TX_RATE_SGI) + os_rate->flags |= RATE_INFO_FLAGS_SHORT_GI; +} + bool hdd_report_max_rate(mac_handle_t mac_handle, struct rate_info *rate, int8_t signal, - uint8_t rate_flags, + enum tx_rate_info rate_flags, uint8_t mcs_index, uint16_t fw_rate, uint8_t nss) { @@ -3961,10 +4071,8 @@ bool hdd_report_max_rate(mac_handle_t mac_handle, qdf_size_t er_leng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX; uint8_t mcs_rates[SIZE_OF_BASIC_MCS_SET]; qdf_size_t mcs_leng = SIZE_OF_BASIC_MCS_SET; - struct index_vht_data_rate_type *supported_vht_mcs_rate; struct index_data_rate_type *supported_mcs_rate; enum data_rate_11ac_max_mcs vht_max_mcs; - uint8_t max_speed_mcs = 0; uint8_t max_mcs_idx = 0; uint8_t rate_flag = 1; int mode = 0, max_ht_idx; @@ -4065,7 +4173,6 @@ bool hdd_report_max_rate(mac_handle_t mac_handle, * Only if we are connected in non legacy mode and not reporting * actual speed */ - if ((3 != rssidx) && !(rate_flags & TX_RATE_LEGACY)) { if (0 != ucfg_mlme_get_current_mcs_set(hdd_ctx->psoc, mcs_rates, @@ -4075,22 +4182,18 @@ bool hdd_report_max_rate(mac_handle_t mac_handle, return false; } rate_flag = 0; - supported_vht_mcs_rate = (struct index_vht_data_rate_type *) - ((nss == 1) ? - &supported_vht_mcs_rate_nss1 : - &supported_vht_mcs_rate_nss2); - if (rate_flags & TX_RATE_VHT80) + if (rate_flags & (TX_RATE_VHT80 | TX_RATE_HE80)) mode = 2; - else if ((rate_flags & TX_RATE_VHT40) || - (rate_flags & TX_RATE_HT40)) + else if (rate_flags & (TX_RATE_HT40 | + TX_RATE_VHT40 | TX_RATE_HE40)) mode = 1; else mode = 0; - /* VHT80 rate has separate rate table */ if (rate_flags & (TX_RATE_VHT20 | TX_RATE_VHT40 | - TX_RATE_VHT80)) { + TX_RATE_VHT80 | TX_RATE_HE20 | TX_RATE_HE40 | + TX_RATE_HE80)) { stat = ucfg_mlme_cfg_get_vht_tx_mcs_map(hdd_ctx->psoc, &vht_mcs_map); if (QDF_IS_STATUS_ERROR(stat)) @@ -4123,6 +4226,10 @@ bool hdd_report_max_rate(mac_handle_t mac_handle, max_mcs_idx = 9; } + if (rate_flags & (TX_RATE_HE20 | TX_RATE_HE40 | + TX_RATE_HE80)) + max_mcs_idx = 11; + if (rssidx != 0) { for (i = 0; i <= max_mcs_idx; i++) { if (signal <= rssi_mcs_tbl[mode][i]) { @@ -4132,33 +4239,8 @@ bool hdd_report_max_rate(mac_handle_t mac_handle, } } - if (rate_flags & TX_RATE_VHT80) { - current_rate = - supported_vht_mcs_rate[mcs_index]. - supported_VHT80_rate[rate_flag]; - max_rate = - supported_vht_mcs_rate[max_mcs_idx]. - supported_VHT80_rate[rate_flag]; - } else if (rate_flags & TX_RATE_VHT40) { - current_rate = - supported_vht_mcs_rate[mcs_index]. - supported_VHT40_rate[rate_flag]; - max_rate = - supported_vht_mcs_rate[max_mcs_idx]. - supported_VHT40_rate[rate_flag]; - } else if (rate_flags & TX_RATE_VHT20) { - current_rate = - supported_vht_mcs_rate[mcs_index]. - supported_VHT20_rate[rate_flag]; - max_rate = - supported_vht_mcs_rate[max_mcs_idx]. - supported_VHT20_rate[rate_flag]; - } - - max_speed_mcs = 1; - if (current_rate > max_rate) - max_rate = current_rate; - + max_mcs_idx = (max_mcs_idx > mcs_index) ? + max_mcs_idx : mcs_index; } else { if (rate_flags & TX_RATE_HT40) rate_flag |= 1; @@ -4197,67 +4279,28 @@ bool hdd_report_max_rate(mac_handle_t mac_handle, } if ((j < MAX_HT_MCS_IDX) && - (current_rate > max_rate)) { + (current_rate > max_rate)) max_rate = current_rate; - } - max_speed_mcs = 1; } + if (nss == 2) max_mcs_idx += MAX_HT_MCS_IDX; + max_mcs_idx = (max_mcs_idx > mcs_index) ? + max_mcs_idx : mcs_index; } } else if (!(rate_flags & TX_RATE_LEGACY)) { max_rate = fw_rate; - max_speed_mcs = 1; max_mcs_idx = mcs_index; } /* report a value at least as big as current rate */ if ((max_rate < fw_rate) || (0 == max_rate)) { max_rate = fw_rate; - if (rate_flags & TX_RATE_LEGACY) { - max_speed_mcs = 0; - } else { - max_speed_mcs = 1; - max_mcs_idx = mcs_index; - } } - if (rate_flags & TX_RATE_LEGACY) { - rate->legacy = max_rate; - - hdd_info("Reporting legacy rate %d", rate->legacy); - } else { - rate->mcs = max_mcs_idx; - rate->nss = nss; - if (rate_flags & TX_RATE_VHT80) - hdd_set_rate_bw(rate, HDD_RATE_BW_80); - else if (rate_flags & TX_RATE_VHT40) - hdd_set_rate_bw(rate, HDD_RATE_BW_40); - else if (rate_flags & TX_RATE_VHT20) - hdd_set_rate_bw(rate, HDD_RATE_BW_20); - - if (rate_flags & - (TX_RATE_HT20 | TX_RATE_HT40)) { - rate->flags |= RATE_INFO_FLAGS_MCS; - if (rate_flags & TX_RATE_HT40) - hdd_set_rate_bw(rate, - HDD_RATE_BW_40); - else if (rate_flags & TX_RATE_HT20) - hdd_set_rate_bw(rate, - HDD_RATE_BW_20); - } else { - rate->flags |= RATE_INFO_FLAGS_VHT_MCS; - } - - if (rate_flags & TX_RATE_SGI) { - if (!(rate->flags & RATE_INFO_FLAGS_VHT_MCS)) - rate->flags |= RATE_INFO_FLAGS_MCS; - rate->flags |= RATE_INFO_FLAGS_SHORT_GI; - } - linkspeed_dbg("Reporting MCS rate %d flags %x\n", - rate->mcs, rate->flags); - } + wlan_hdd_fill_os_rate_info(rate_flags, max_rate, rate, + max_mcs_idx, nss, 0, 0); return true; } @@ -4268,48 +4311,22 @@ bool hdd_report_max_rate(mac_handle_t mac_handle, * @rate_flags: The rate flags computed from rate * @my_rate: The rate from fw stats * @rate: The station_info struct member strust rate_info to be filled - * @mcs_index; The mcs index computed from rate + * @mcs_index: The mcs index computed from rate * @nss: The NSS from fw stats + * @dcm: the dcm computed from rate + * @guard_interval: the guard interval computed from rate * * Return: None */ -static void hdd_report_actual_rate(uint8_t rate_flags, uint16_t my_rate, +static void hdd_report_actual_rate(enum tx_rate_info rate_flags, + uint16_t my_rate, struct rate_info *rate, uint8_t mcs_index, - uint8_t nss) + uint8_t nss, uint8_t dcm, + enum txrate_gi guard_interval) { /* report current rate instead of max rate */ - - if (rate_flags & TX_RATE_LEGACY) { - /* provide to the UI in units of 100kbps */ - rate->legacy = my_rate; - linkspeed_dbg("Reporting actual legacy rate %d", - rate->legacy); - } else { - /* must be MCS */ - rate->mcs = mcs_index; - rate->nss = nss; - - if (rate_flags & TX_RATE_VHT80) - hdd_set_rate_bw(rate, HDD_RATE_BW_80); - else if (rate_flags & TX_RATE_VHT40) - hdd_set_rate_bw(rate, HDD_RATE_BW_40); - - if (rate_flags & - (TX_RATE_HT20 | TX_RATE_HT40)) { - rate->flags |= RATE_INFO_FLAGS_MCS; - if (rate_flags & TX_RATE_HT40) - hdd_set_rate_bw(rate, HDD_RATE_BW_40); - } else { - rate->flags |= RATE_INFO_FLAGS_VHT_MCS; - } - - if (rate_flags & TX_RATE_SGI) { - rate->flags |= RATE_INFO_FLAGS_SHORT_GI; - } - - linkspeed_dbg("Reporting actual MCS rate %d flags %x\n", - rate->mcs, rate->flags); - } + wlan_hdd_fill_os_rate_info(rate_flags, my_rate, rate, + mcs_index, nss, dcm, guard_interval); } /** @@ -4395,13 +4412,14 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, struct station_info *sinfo) { struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - uint8_t rate_flags, tx_rate_flags, rx_rate_flags; + enum tx_rate_info rate_flags, tx_rate_flags, rx_rate_flags; uint8_t tx_mcs_index, rx_mcs_index; struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy); mac_handle_t mac_handle; int8_t snr = 0; uint16_t my_tx_rate, my_rx_rate; - uint8_t tx_nss = 1, rx_nss = 1; + uint8_t tx_nss = 1, rx_nss = 1, tx_dcm, rx_dcm; + enum txrate_gi tx_gi, rx_gi; int32_t rcpi_value; int link_speed_rssi_high = 0; int link_speed_rssi_mid = 0; @@ -4482,6 +4500,11 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, my_tx_rate = adapter->hdd_stats.class_a_stat.tx_rate; my_rx_rate = adapter->hdd_stats.class_a_stat.rx_rate; + tx_dcm = adapter->hdd_stats.class_a_stat.tx_dcm; + rx_dcm = adapter->hdd_stats.class_a_stat.rx_dcm; + tx_gi = adapter->hdd_stats.class_a_stat.tx_gi; + rx_gi = adapter->hdd_stats.class_a_stat.rx_gi; + if (!(rate_flags & TX_RATE_LEGACY)) { tx_nss = adapter->hdd_stats.class_a_stat.tx_nss; rx_nss = adapter->hdd_stats.class_a_stat.rx_nss; @@ -4535,9 +4558,8 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, hdd_debug("MCS Index: TX: %d, RX: %d", (int)tx_mcs_index, (int)rx_mcs_index); hdd_debug("NSS: TX: %d, RX: %d", (int)tx_nss, (int)rx_nss); - - /* assume basic BW. anything else will override this later */ - hdd_set_rate_bw(&sinfo->txrate, HDD_RATE_BW_20); + hdd_debug("dcm: TX: %d, RX: %d", (int)tx_dcm, (int)rx_dcm); + hdd_debug("guard interval: TX: %d, RX: %d", (int)tx_gi, (int)rx_gi); if (!ucfg_mlme_stats_is_link_speed_report_actual(hdd_ctx->psoc)) { bool tx_rate_calc; @@ -4566,11 +4588,14 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, /* Fill TX stats */ hdd_report_actual_rate(tx_rate_flags, my_tx_rate, - &sinfo->txrate, tx_mcs_index, tx_nss); + &sinfo->txrate, tx_mcs_index, + tx_nss, tx_dcm, tx_gi); + /* Fill RX stats */ hdd_report_actual_rate(rx_rate_flags, my_rx_rate, - &sinfo->rxrate, rx_mcs_index, rx_nss); + &sinfo->rxrate, rx_mcs_index, + rx_nss, rx_dcm, rx_gi); } wlan_hdd_fill_summary_stats(&adapter->hdd_stats.summary_stat, sinfo); @@ -4594,14 +4619,21 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, HDD_INFO_RX_BYTES | HDD_INFO_RX_PACKETS; - if (tx_rate_flags & TX_RATE_LEGACY) - hdd_debug("Reporting legacy rate %d pkt cnt tx %d rx %d", - sinfo->txrate.legacy, sinfo->tx_packets, - sinfo->rx_packets); - else - hdd_debug("Reporting MCS rate %d flags 0x%x pkt cnt tx %d rx %d", - sinfo->txrate.mcs, sinfo->txrate.flags, - sinfo->tx_packets, sinfo->rx_packets); + if (tx_rate_flags & TX_RATE_LEGACY) { + hdd_debug("TX: Reporting legacy rate %d pkt cnt %d", + sinfo->txrate.legacy, sinfo->tx_packets); + hdd_debug("RX: Reporting legacy rate %d pkt cnt %d", + sinfo->rxrate.legacy, sinfo->rx_packets); + } else { + hdd_debug("TX: Reporting MCS rate %d, flags 0x%x pkt cnt %d, nss %d, bw %d", + sinfo->txrate.mcs, sinfo->txrate.flags, + sinfo->tx_packets, sinfo->txrate.nss, + sinfo->rxrate.bw); + hdd_debug("RX: Reporting MCS rate %d, flags 0x%x pkt cnt %d, nss %d, bw %d", + sinfo->rxrate.mcs, sinfo->rxrate.flags, + sinfo->rx_packets, sinfo->rxrate.nss, + sinfo->rxrate.bw); + } hdd_wlan_fill_per_chain_rssi_stats(sinfo, adapter); @@ -5631,7 +5663,6 @@ int wlan_hdd_get_peer_info(struct hdd_adapter *adapter, int wlan_hdd_get_station_stats(struct hdd_adapter *adapter) { int ret = 0; - uint8_t mcs_rate_flags; struct stats_event *stats; stats = wlan_cfg80211_mc_cp_stats_get_station_stats(adapter->vdev, @@ -5690,13 +5721,18 @@ int wlan_hdd_get_station_stats(struct hdd_adapter *adapter) adapter->hdd_stats.class_a_stat.tx_mcs_index = sme_get_mcs_idx(stats->tx_rate, stats->tx_rate_flags, &adapter->hdd_stats.class_a_stat.tx_nss, - &mcs_rate_flags); - adapter->hdd_stats.class_a_stat.tx_mcs_rate_flags = mcs_rate_flags; + &adapter->hdd_stats.class_a_stat.tx_dcm, + &adapter->hdd_stats.class_a_stat.tx_gi, + &adapter->hdd_stats.class_a_stat. + tx_mcs_rate_flags); + adapter->hdd_stats.class_a_stat.rx_mcs_index = sme_get_mcs_idx(stats->rx_rate, stats->tx_rate_flags, &adapter->hdd_stats.class_a_stat.rx_nss, - &mcs_rate_flags); - adapter->hdd_stats.class_a_stat.rx_mcs_rate_flags = mcs_rate_flags; + &adapter->hdd_stats.class_a_stat.rx_dcm, + &adapter->hdd_stats.class_a_stat.rx_gi, + &adapter->hdd_stats.class_a_stat. + rx_mcs_rate_flags); /* save per chain rssi to legacy location */ qdf_mem_copy(adapter->hdd_stats.per_chain_rssi_stats.rssi, diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h index 275461c66462..a6272db124c7 100644 --- a/core/hdd/src/wlan_hdd_stats.h +++ b/core/hdd/src/wlan_hdd_stats.h @@ -457,7 +457,7 @@ void wlan_hdd_display_txrx_stats(struct hdd_context *hdd_ctx); bool hdd_report_max_rate(mac_handle_t mac_handle, struct rate_info *rate, int8_t signal, - uint8_t rate_flags, + enum tx_rate_info rate_flags, uint8_t mcs_index, uint16_t fw_rate, uint8_t nss); diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index bf3ec5fec8f4..5f37b96c9df5 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -4092,8 +4092,10 @@ QDF_STATUS lim_sta_send_add_bss_pre_assoc(struct mac_context *mac, } if (lim_is_session_he_capable(pe_session) && - pBeaconStruct->he_cap.present) + pBeaconStruct->he_cap.present) { + lim_update_bss_he_capable(mac, pAddBssParams); lim_add_bss_he_cfg(pAddBssParams, pe_session); + } pe_debug("vhtCapable %d ch_width %d", pAddBssParams->vhtCapable, pAddBssParams->ch_width); /* diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 5891ac2feea3..441b34e90aa9 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -6717,6 +6717,7 @@ void lim_add_bss_he_cap(struct bss_params *add_bss, tpSirAssocRsp assoc_rsp) he_cap = &assoc_rsp->he_cap; he_op = &assoc_rsp->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)); @@ -7124,6 +7125,13 @@ void lim_update_sta_he_capable(struct mac_context *mac, pe_debug("he_capable: %d", add_sta_params->he_capable); } +void lim_update_bss_he_capable(struct mac_context *mac, + struct bss_params *add_bss) +{ + add_bss->he_capable = true; + pe_debug("he_capable: %d", add_bss->he_capable); +} + void lim_update_stads_he_capable(tpDphHashNode sta_ds, tpSirAssocReq assoc_req) { sta_ds->mlmStaContext.he_capable = assoc_req->he_cap.present; diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index 38978a890f1f..358084c1d441 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -1137,6 +1137,16 @@ static inline bool lim_is_sta_he_capable(tpDphHashNode sta_ds) return sta_ds->mlmStaContext.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(struct mac_context *mac, + struct bss_params *add_bss); + /** * lim_update_stads_he_capable() - Update he_capable in sta ds context * @sta_ds: pointer to sta ds @@ -1290,6 +1300,11 @@ static inline bool lim_is_sta_he_capable(tpDphHashNode sta_ds) return false; } +static inline void lim_update_bss_he_capable(struct mac_context *mac, + struct bss_params *add_bss) +{ +} + static inline void lim_update_stads_he_capable(tpDphHashNode sta_ds, tpSirAssocReq assoc_req) { diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index b1e83f7df29f..0be154d2407d 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1197,10 +1197,14 @@ typedef struct tagCsrGlobalClassAStatsInfo { /* mcs index for HT20 and HT40 rates */ uint32_t tx_mcs_index; uint32_t rx_mcs_index; - uint32_t tx_mcs_rate_flags; - uint32_t rx_mcs_rate_flags; + enum tx_rate_info tx_mcs_rate_flags; + enum tx_rate_info rx_mcs_rate_flags; + uint8_t tx_dcm; + uint8_t rx_dcm; + enum txrate_gi tx_gi; + enum txrate_gi rx_gi; /* to diff between HT20 & HT40 rates;short & long guard interval */ - uint32_t tx_rx_rate_flags; + enum tx_rate_info tx_rx_rate_flags; } tCsrGlobalClassAStatsInfo; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 8dee1e0ac7bd..cc81e539cff0 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -3377,15 +3377,19 @@ static inline void sme_reset_he_caps(mac_handle_t mac_handle, uint8_t vdev_id) /** * sme_get_mcs_idx() - gets mcs index - * @max_rate: max rate + * @raw_rate: raw rate from fw * @rate_flags: rate flags * @nss: number of nss + * @dcm: dcm will be calculated from rate + * @guard_interval: guard interval info from rate * @mcs_rate_flags: mcs rate flag * * Return: return mcs index */ -uint8_t sme_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags, - uint8_t *nss, uint8_t *mcs_rate_flags); +uint8_t sme_get_mcs_idx(uint16_t raw_rate, enum tx_rate_info rate_flags, + uint8_t *nss, uint8_t *dcm, + enum txrate_gi *guard_interval, + enum tx_rate_info *mcs_rate_flags); #ifdef WLAN_SUPPORT_TWT /** diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index edbadde39bad..551f411764a7 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -15318,10 +15318,13 @@ void sme_reset_he_caps(mac_handle_t mac_handle, uint8_t vdev_id) } #endif -uint8_t sme_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags, - uint8_t *nss, uint8_t *mcs_rate_flags) +uint8_t sme_get_mcs_idx(uint16_t raw_rate, enum tx_rate_info rate_flags, + uint8_t *nss, uint8_t *dcm, + enum txrate_gi *guard_interval, + enum tx_rate_info *mcs_rate_flags) { - return wma_get_mcs_idx(max_rate, rate_flags, nss, mcs_rate_flags); + return wma_get_mcs_idx(raw_rate, rate_flags, + nss, dcm, guard_interval, mcs_rate_flags); } bool sme_find_session_by_bssid(mac_handle_t mac_handle, uint8_t *bssid) diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index d5fe2afb7414..320b28694ff6 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -768,6 +768,7 @@ struct wma_txrx_node { void *del_staself_req; bool is_del_sta_defered; qdf_atomic_t bss_status; + enum tx_rate_info rate_flags; uint8_t nss; uint16_t pause_bitmap; int8_t tx_power; diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index b6fd5fa55dee..66ccbe07994c 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -450,15 +450,19 @@ void wma_wmi_stop(void); /** * wma_get_mcs_idx() - get mcs index - * @max_rate: max rate + * @raw_rate: raw rate from fw * @rate_flags: rate flags * @nss: nss + * @dcm: dcm + * @guard_interval: guard interval * @mcs_rate_flag: mcs rate flags * * Return: mcs index */ -uint8_t wma_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags, - uint8_t *nss, uint8_t *mcs_rate_flag); +uint8_t wma_get_mcs_idx(uint16_t raw_rate, enum tx_rate_info rate_flags, + uint8_t *nss, uint8_t *dcm, + enum txrate_gi *guard_interval, + enum tx_rate_info *mcs_rate_flag); /** * wma_get_hidden_ssid_restart_in_progress() - check if hidden ssid restart is diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 6813dd0caa50..364faf9b047c 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -342,6 +342,7 @@ typedef struct sLimMlmSetKeysReq { * @bSpectrumMgtEnabled: Spectrum Management Capability, 1:Enabled, 0:Disabled. * @vhtCapable: VHT capablity * @ch_width: VHT tx channel width + * @he_capable: HE Capability * @no_ptk_4_way: Do not need 4-way handshake */ struct bss_params { @@ -368,6 +369,7 @@ struct bss_params { enum phy_ch_width ch_width; uint8_t nonRoamReassoc; #ifdef WLAN_FEATURE_11AX + bool he_capable; uint32_t he_sta_obsspd; #endif bool no_ptk_4_way; diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index d19b5bfcb2f8..0277a23ce0f0 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -57,8 +57,15 @@ #define MAX_HT_MCS_IDX 8 #define MAX_VHT_MCS_IDX 10 +#ifdef WLAN_FEATURE_11AX +#define MAX_HE_MCS_IDX 12 +#endif #define INVALID_MCS_IDX 255 +#define IS_MCS_HAS_DCM_RATE(val) \ + ((val) == 0 || (val) == 1 || \ + (val) == 3 || (val) == 4) + #define LINK_STATUS_LEGACY 0 #define LINK_STATUS_VHT 0x1 #define LINK_STATUS_MIMO 0x2 @@ -96,6 +103,23 @@ struct index_vht_data_rate_type { uint16_t ht80_rate[2]; }; +#ifdef WLAN_FEATURE_11AX +#define MAX_HE_DCM_INDEX 2 +/** + * struct index_he_data_rate_type - he data rate type + * @beacon_rate_index: Beacon rate index + * @supported_he80_rate: he80 rate + * @supported_he40_rate: he40 rate + * @supported_he20_rate: he20 rate + */ +struct index_he_data_rate_type { + uint8_t beacon_rate_index; + uint16_t supported_he20_rate[MAX_HE_DCM_INDEX][3]; + uint16_t supported_he40_rate[MAX_HE_DCM_INDEX][3]; + uint16_t supported_he80_rate[MAX_HE_DCM_INDEX][3]; +}; +#endif + struct wifi_scan_cmd_req_params; /* * wma_main.c functions declarations diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index f6471e74323c..0c728a34b8ee 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -761,12 +761,48 @@ static void wma_cp_stats_set_rate_flag(tp_wma_handle wma, uint8_t vdev_id) wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); } +#ifdef WLAN_FEATURE_11AX +/** + * wma_set_bss_rate_flags_he() - set rate flags based on BSS capability + * @rate_flags: rate_flags pointer + * @add_bss: add_bss params + * + * Return: QDF_STATUS + */ +static QDF_STATUS wma_set_bss_rate_flags_he(enum tx_rate_info *rate_flags, + struct bss_params *add_bss) +{ + if (!add_bss->he_capable) + return QDF_STATUS_E_NOSUPPORT; + + /*extend TX_RATE_HE160 in future*/ + if (add_bss->ch_width == CH_WIDTH_160MHZ || + add_bss->ch_width == CH_WIDTH_80P80MHZ || + add_bss->ch_width == CH_WIDTH_80MHZ) + *rate_flags |= TX_RATE_HE80; + + else if (add_bss->ch_width) + *rate_flags |= TX_RATE_HE40; + else + *rate_flags |= TX_RATE_HE20; + + wma_debug("he_capable %d", add_bss->he_capable); + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS wma_set_bss_rate_flags_he(enum tx_rate_info *rate_flags, + struct bss_params *add_bss) +{ + return QDF_STATUS_E_NOSUPPORT; +} +#endif + void wma_set_bss_rate_flags(tp_wma_handle wma, uint8_t vdev_id, struct bss_params *add_bss) { struct wma_txrx_node *iface = &wma->interfaces[vdev_id]; struct vdev_mlme_obj *vdev_mlme; - uint32_t *rate_flags; + enum tx_rate_info *rate_flags; vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(iface->vdev); @@ -777,24 +813,28 @@ void wma_set_bss_rate_flags(tp_wma_handle wma, uint8_t vdev_id, } rate_flags = &vdev_mlme->mgmt.rate_info.rate_flags; *rate_flags = 0; - if (add_bss->vhtCapable) { - if (add_bss->ch_width == CH_WIDTH_80P80MHZ) - *rate_flags |= TX_RATE_VHT80; - if (add_bss->ch_width == CH_WIDTH_160MHZ) - *rate_flags |= TX_RATE_VHT80; - if (add_bss->ch_width == CH_WIDTH_80MHZ) - *rate_flags |= TX_RATE_VHT80; - else if (add_bss->ch_width) - *rate_flags |= TX_RATE_VHT40; - else - *rate_flags |= TX_RATE_VHT20; - } - /* avoid to conflict with htCapable flag */ - else if (add_bss->htCapable) { - if (add_bss->ch_width) - *rate_flags |= TX_RATE_HT40; - else - *rate_flags |= TX_RATE_HT20; + + if (QDF_STATUS_SUCCESS != + wma_set_bss_rate_flags_he(rate_flags, add_bss)) { + if (add_bss->vhtCapable) { + if (add_bss->ch_width == CH_WIDTH_80P80MHZ) + *rate_flags |= TX_RATE_VHT80; + if (add_bss->ch_width == CH_WIDTH_160MHZ) + *rate_flags |= TX_RATE_VHT80; + if (add_bss->ch_width == CH_WIDTH_80MHZ) + *rate_flags |= TX_RATE_VHT80; + else if (add_bss->ch_width) + *rate_flags |= TX_RATE_VHT40; + else + *rate_flags |= TX_RATE_VHT20; + } + /* avoid to conflict with htCapable flag */ + else if (add_bss->htCapable) { + if (add_bss->ch_width) + *rate_flags |= TX_RATE_HT40; + else + *rate_flags |= TX_RATE_HT20; + } } if (add_bss->staContext.fShortGI20Mhz || @@ -804,6 +844,10 @@ void wma_set_bss_rate_flags(tp_wma_handle wma, uint8_t vdev_id, if (!add_bss->htCapable && !add_bss->vhtCapable) *rate_flags = TX_RATE_LEGACY; + wma_debug("capable: vht %u, ht %u, rate_flags %x, ch_width %d", + add_bss->vhtCapable, add_bss->htCapable, + *rate_flags, add_bss->ch_width); + wma_cp_stats_set_rate_flag(wma, vdev_id); } diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 6136a3b09543..d26c98e63c7d 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -123,6 +123,91 @@ static struct index_vht_data_rate_type vht_mcs_nss2[] = { {9, {1730, 1920}, {3600, 4000}, {7800, 8667} } }; +#ifdef WLAN_FEATURE_11AX +/* MCS Based HE rate table */ +/* MCS parameters with Nss = 1*/ +static struct index_he_data_rate_type he_mcs_nss1[] = { +/* MCS, {dcm0:0.8/1.6/3.2}, {dcm1:0.8/1.6/3.2} */ + {0, {{86, 81, 73 }, {43, 40, 36 } }, /* HE20 */ + {{172, 163, 146 }, {86, 81, 73 } }, /* HE40 */ + {{360, 340, 306 }, {180, 170, 153} } }, /* HE80 */ + {1, {{172, 163, 146 }, {86, 81, 73 } }, + {{344, 325, 293 }, {172, 163, 146} }, + {{721, 681, 613 }, {360, 340, 306} } }, + {2, {{258, 244, 219 }, {0} }, + {{516, 488, 439 }, {0} }, + {{1081, 1021, 919 }, {0} } }, + {3, {{344, 325, 293 }, {172, 163, 146} }, + {{688, 650, 585 }, {344, 325, 293} }, + {{1441, 1361, 1225}, {721, 681, 613} } }, + {4, {{516, 488, 439 }, {258, 244, 219} }, + {{1032, 975, 878 }, {516, 488, 439} }, + {{2162, 2042, 1838}, {1081, 1021, 919} } }, + {5, {{688, 650, 585 }, {0} }, + {{1376, 1300, 1170}, {0} }, + {{2882, 2722, 2450}, {0} } }, + {6, {{774, 731, 658 }, {0} }, + {{1549, 1463, 1316}, {0} }, + {{3243, 3063, 2756}, {0} } }, + {7, {{860, 813, 731 }, {0} }, + {{1721, 1625, 1463}, {0} }, + {{3603, 3403, 3063}, {0} } }, + {8, {{1032, 975, 878 }, {0} }, + {{2065, 1950, 1755}, {0} }, + {{4324, 4083, 3675}, {0} } }, + {9, {{1147, 1083, 975 }, {0} }, + {{2294, 2167, 1950}, {0} }, + {{4804, 4537, 4083}, {0} } }, + {10, {{1290, 1219, 1097}, {0} }, + {{2581, 2438, 2194}, {0} }, + {{5404, 5104, 4594}, {0} } }, + {11, {{1434, 1354, 1219}, {0} }, + {{2868, 2708, 2438}, {0} }, + {{6004, 5671, 5104}, {0} } } +}; + +/*MCS parameters with Nss = 2*/ +static struct index_he_data_rate_type he_mcs_nss2[] = { +/* MCS, {dcm0:0.8/1.6/3.2}, {dcm1:0.8/1.6/3.2} */ + {0, {{172, 163, 146 }, {86, 81, 73 } }, /* HE20 */ + {{344, 325, 293 }, {172, 163, 146} }, /* HE40 */ + {{721, 681, 613 }, {360, 340, 306} } }, /* HE80 */ + {1, {{344, 325, 293 }, {172, 163, 146} }, + {{688, 650, 585 }, {344, 325, 293} }, + {{1441, 1361, 1225}, {721, 681, 613} } }, + {2, {{516, 488, 439 }, {0} }, + {{1032, 975, 878 }, {0} }, + {{2162, 2042, 1838}, {0} } }, + {3, {{688, 650, 585 }, {344, 325, 293 } }, + {{1376, 1300, 1170}, {688, 650, 585 } }, + {{2882, 2722, 2450}, {1441, 1361, 1225} } }, + {4, {{1032, 975, 878 }, {516, 488, 439 } }, + {{2065, 1950, 1755}, {1032, 975, 878 } }, + {{4324, 4083, 3675}, {2162, 2042, 1838} } }, + {5, {{1376, 1300, 1170}, {0} }, + {{2753, 2600, 2340}, {0} }, + {{5765, 5444, 4900}, {0} } }, + {6, {{1549, 1463, 1316}, {0} }, + {{3097, 2925, 2633}, {0} }, + {{6485, 6125, 5513}, {0} } }, + {7, {{1721, 1625, 1463}, {0} }, + {{3441, 3250, 2925}, {0} }, + {{7206, 6806, 6125}, {0} } }, + {8, {{2065, 1950, 1755}, {0} }, + {{4129, 3900, 3510}, {0} }, + {{8647, 8167, 7350}, {0} } }, + {9, {{2294, 2167, 1950}, {0} }, + {{4588, 4333, 3900}, {0} }, + {{9607, 9074, 8166}, {0} } }, + {10, {{2581, 2438, 2194}, {0} }, + {{5162, 4875, 4388}, {0} }, + {{10809, 10208, 9188}, {0} } }, + {11, {{2868, 2708, 2438}, {0} }, + {{5735, 5417, 4875}, {0} }, + {{12010, 11343, 10208}, {0} } } +}; +#endif + #ifdef BIG_ENDIAN_HOST /* ############# function definitions ############ */ @@ -151,90 +236,233 @@ void wma_swap_bytes(void *pv, uint32_t n) /** * wma_mcs_rate_match() - find the match mcs rate - * @match_rate: the rate to look up - * @is_sgi: return if the SGI rate is found - * @nss: the nss in use - * @nss1_rate: the nss1 rate - * @nss1_srate: the nss1 SGI rate - * @nss2_rate: the nss2 rate - * @nss2_srate: the nss2 SGI rate + * @raw_rate: the rate to look up + * @is_he: if it is he rate + * @nss1_rate: the nss1 rate + * @nss2_rate: the nss2 rate + * @nss: the nss in use + * @guard_interval: to get guard interval from rate * * This is a helper function to find the match of the tx_rate - * in terms of the nss1/nss2 rate with non-SGI/SGI. + * and return nss/guard interval. * * Return: the found rate or 0 otherwise */ -static inline uint16_t wma_mcs_rate_match(uint16_t match_rate, bool *is_sgi, - uint8_t *nss, uint16_t nss1_rate, - uint16_t nss1_srate, - uint16_t nss2_rate, - uint16_t nss2_srate) +static inline uint16_t wma_mcs_rate_match(uint16_t raw_rate, + bool is_he, + uint16_t *nss1_rate, + uint16_t *nss2_rate, + uint8_t *nss, + enum txrate_gi *guard_interval) { - WMA_LOGD("%s match_rate: %d, %d %d %d %d", - __func__, match_rate, nss1_rate, nss1_srate, nss2_rate, - nss2_srate); + uint8_t gi_index; + uint8_t gi_index_max = 2; + uint16_t ret_rate = 0; - if (match_rate == nss1_rate) { - *nss = 1; - return nss1_rate; - } else if (match_rate == nss1_srate) { - *is_sgi = true; - *nss = 1; - return nss1_srate; - } else if (*nss == 2 && match_rate == nss2_rate) - return nss2_rate; - else if (*nss == 2 && match_rate == nss2_srate) { - *is_sgi = true; - return nss2_srate; - } else - return 0; + WMA_LOGD("%s raw_rate: %u, %u %u %u %u", + __func__, raw_rate, nss1_rate[0], + nss1_rate[1], nss2_rate[0], nss2_rate[1]); + if (is_he) + WMA_LOGD("%s : is_he %u, %u, %u", + __func__, is_he, nss1_rate[2], nss2_rate[2]); + + if (is_he) + gi_index_max = 3; + + for (gi_index = 0; gi_index < gi_index_max; gi_index++) { + if (raw_rate == nss1_rate[gi_index]) { + *nss = 1; + ret_rate = nss1_rate[gi_index]; + break; + } + if (*nss == 2 && raw_rate == nss2_rate[gi_index]) { + ret_rate = nss2_rate[gi_index]; + break; + } + } + + if (ret_rate) { + if (gi_index == 1) + *guard_interval = + is_he ? TXRATE_GI_1_6_US : TXRATE_GI_0_4_US; + else if (is_he && gi_index == 2) + *guard_interval = TXRATE_GI_3_2_US; + else + *guard_interval = TXRATE_GI_0_8_US; + } + + WMA_LOGD("%s ret_rate: %u, guard interval %u nss %u", + __func__, ret_rate, *guard_interval, *nss); + + return ret_rate; } -uint8_t wma_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags, - uint8_t *nss, uint8_t *mcs_rate_flag) +#ifdef WLAN_FEATURE_11AX +/** + * wma_get_mcs_idx() - get mcs index + * @raw_rate: raw rate from fw + * @rate_flags: rate flags + * @nss: nss + * @dcm: dcm + * @guard_interval: guard interval + * @mcs_rate_flag: mcs rate flags + * @p_index: index for matched rate + * + * Return: return match rate if found, else 0 + */ +static uint16_t wma_match_he_rate(uint16_t raw_rate, + enum tx_rate_info rate_flags, + uint8_t *nss, uint8_t *dcm, + enum txrate_gi *guard_interval, + enum tx_rate_info *mcs_rate_flag, + uint8_t *p_index) +{ + uint8_t index = 0; + uint8_t dcm_index_max = 1; + uint8_t dcm_index = 0; + uint16_t match_rate = 0; + uint16_t *nss1_rate; + uint16_t *nss2_rate; + + *p_index = 0; + if (!(rate_flags & (TX_RATE_HE80 | TX_RATE_HE40 | + TX_RATE_HE20))) + return 0; + + for (index = 0; index < MAX_HE_MCS_IDX; index++) { + dcm_index_max = IS_MCS_HAS_DCM_RATE(index) ? 2 : 1; + + for (dcm_index = 0; dcm_index < dcm_index_max; + dcm_index++) { + if (rate_flags & TX_RATE_HE80) { + nss1_rate = &he_mcs_nss1[index]. + supported_he80_rate[dcm_index][0]; + nss2_rate = &he_mcs_nss2[index]. + supported_he80_rate[dcm_index][0]; + /* check for he80 nss1/2 rate set */ + match_rate = wma_mcs_rate_match(raw_rate, 1, + nss1_rate, + nss2_rate, + nss, + guard_interval); + if (match_rate) + goto rate_found; + } + + if (rate_flags & (TX_RATE_HE40 | TX_RATE_HE80)) { + nss1_rate = &he_mcs_nss1[index]. + supported_he40_rate[dcm_index][0]; + nss2_rate = &he_mcs_nss2[index]. + supported_he40_rate[dcm_index][0]; + /* check for he40 nss1/2 rate set */ + match_rate = wma_mcs_rate_match(raw_rate, 1, + nss1_rate, + nss2_rate, + nss, + guard_interval); + + if (match_rate) { + *mcs_rate_flag &= ~TX_RATE_HE80; + goto rate_found; + } + } + + if (rate_flags & (TX_RATE_HE80 | TX_RATE_HE40 | + TX_RATE_HE20)) { + nss1_rate = &he_mcs_nss1[index]. + supported_he20_rate[dcm_index][0]; + nss2_rate = &he_mcs_nss2[index]. + supported_he20_rate[dcm_index][0]; + /* check for he20 nss1/2 rate set */ + match_rate = wma_mcs_rate_match(raw_rate, 1, + nss1_rate, + nss2_rate, + nss, + guard_interval); + + if (match_rate) { + *mcs_rate_flag &= TX_RATE_HE20; + goto rate_found; + } + } + } + } + +rate_found: + if (match_rate) { + if (dcm_index == 1) + *dcm = 1; + *p_index = index; + } + return match_rate; +} +#else +static uint16_t wma_match_he_rate(uint16_t raw_rate, + enum tx_rate_info rate_flags, + uint8_t *nss, uint8_t *dcm, + enum txrate_gi *guard_interval, + enum tx_rate_info *mcs_rate_flag, + uint8_t *p_index) +{ + return 0; +} +#endif + +uint8_t wma_get_mcs_idx(uint16_t raw_rate, enum tx_rate_info rate_flags, + uint8_t *nss, uint8_t *dcm, + enum txrate_gi *guard_interval, + enum tx_rate_info *mcs_rate_flag) { uint8_t index = 0; uint16_t match_rate = 0; - bool is_sgi = false; + uint16_t *nss1_rate; + uint16_t *nss2_rate; - WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d", - __func__, max_rate, rate_flags, *nss); + WMA_LOGD("%s enter: raw_rate:%d rate_flgs: 0x%x, nss: %d", + __func__, raw_rate, rate_flags, *nss); *mcs_rate_flag = rate_flags; - *mcs_rate_flag &= ~TX_RATE_SGI; + + match_rate = wma_match_he_rate(raw_rate, rate_flags, + nss, dcm, guard_interval, + mcs_rate_flag, &index); + if (match_rate) + goto rate_found; + for (index = 0; index < MAX_VHT_MCS_IDX; index++) { if (rate_flags & TX_RATE_VHT80) { + nss1_rate = &vht_mcs_nss1[index].ht80_rate[0]; + nss2_rate = &vht_mcs_nss2[index].ht80_rate[0]; /* check for vht80 nss1/2 rate set */ - match_rate = wma_mcs_rate_match(max_rate, &is_sgi, nss, - vht_mcs_nss1[index].ht80_rate[0], - vht_mcs_nss1[index].ht80_rate[1], - vht_mcs_nss2[index].ht80_rate[0], - vht_mcs_nss2[index].ht80_rate[1]); + match_rate = wma_mcs_rate_match(raw_rate, 0, + nss1_rate, + nss2_rate, + nss, guard_interval); if (match_rate) goto rate_found; } - if ((rate_flags & TX_RATE_VHT40) | - (rate_flags & TX_RATE_VHT80)) { + if (rate_flags & (TX_RATE_VHT40 | TX_RATE_VHT80)) { + nss1_rate = &vht_mcs_nss1[index].ht40_rate[0]; + nss2_rate = &vht_mcs_nss2[index].ht40_rate[0]; /* check for vht40 nss1/2 rate set */ - match_rate = wma_mcs_rate_match(max_rate, &is_sgi, nss, - vht_mcs_nss1[index].ht40_rate[0], - vht_mcs_nss1[index].ht40_rate[1], - vht_mcs_nss2[index].ht40_rate[0], - vht_mcs_nss2[index].ht40_rate[1]); + match_rate = wma_mcs_rate_match(raw_rate, 0, + nss1_rate, + nss2_rate, + nss, guard_interval); if (match_rate) { *mcs_rate_flag &= ~TX_RATE_VHT80; goto rate_found; } } - if ((rate_flags & TX_RATE_VHT20) | - (rate_flags & TX_RATE_VHT40) | - (rate_flags & TX_RATE_VHT80)) { + if (rate_flags & (TX_RATE_VHT20 | TX_RATE_VHT40 | + TX_RATE_VHT80)) { + nss1_rate = &vht_mcs_nss1[index].ht20_rate[0]; + nss2_rate = &vht_mcs_nss2[index].ht20_rate[0]; /* check for vht20 nss1/2 rate set */ - match_rate = wma_mcs_rate_match(max_rate, &is_sgi, nss, - vht_mcs_nss1[index].ht20_rate[0], - vht_mcs_nss1[index].ht20_rate[1], - vht_mcs_nss2[index].ht20_rate[0], - vht_mcs_nss2[index].ht20_rate[1]); + match_rate = wma_mcs_rate_match(raw_rate, 0, + nss1_rate, + nss2_rate, + nss, guard_interval); if (match_rate) { *mcs_rate_flag &= ~(TX_RATE_VHT80 | TX_RATE_VHT40); @@ -244,12 +472,13 @@ uint8_t wma_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags, } for (index = 0; index < MAX_HT_MCS_IDX; index++) { if (rate_flags & TX_RATE_HT40) { + nss1_rate = &mcs_nss1[index].ht40_rate[0]; + nss2_rate = &mcs_nss2[index].ht40_rate[0]; /* check for ht40 nss1/2 rate set */ - match_rate = wma_mcs_rate_match(max_rate, &is_sgi, nss, - mcs_nss1[index].ht40_rate[0], - mcs_nss1[index].ht40_rate[1], - mcs_nss2[index].ht40_rate[0], - mcs_nss2[index].ht40_rate[1]); + match_rate = wma_mcs_rate_match(raw_rate, 0, + nss1_rate, + nss2_rate, + nss, guard_interval); if (match_rate) { *mcs_rate_flag = TX_RATE_HT40; if (*nss == 2) @@ -257,14 +486,14 @@ uint8_t wma_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags, goto rate_found; } } - if ((rate_flags & TX_RATE_HT20) || - (rate_flags & TX_RATE_HT40)) { + if (rate_flags & (TX_RATE_HT20 | TX_RATE_HT40)) { + nss1_rate = &mcs_nss1[index].ht20_rate[0]; + nss2_rate = &mcs_nss2[index].ht20_rate[0]; /* check for ht20 nss1/2 rate set */ - match_rate = wma_mcs_rate_match(max_rate, &is_sgi, nss, - mcs_nss1[index].ht20_rate[0], - mcs_nss1[index].ht20_rate[1], - mcs_nss2[index].ht20_rate[0], - mcs_nss2[index].ht20_rate[1]); + match_rate = wma_mcs_rate_match(raw_rate, 0, + nss1_rate, + nss2_rate, + nss, guard_interval); if (match_rate) { *mcs_rate_flag = TX_RATE_HT20; if (*nss == 2) @@ -275,12 +504,17 @@ uint8_t wma_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags, } rate_found: - /* set SGI flag only if this is SGI rate */ - if (match_rate && is_sgi == true) - *mcs_rate_flag |= TX_RATE_SGI; - WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d", - __func__, match_rate, index, *mcs_rate_flag, is_sgi); + /* set SGI flag only if this is SGI rate */ + if (match_rate && *guard_interval == TXRATE_GI_0_4_US) + *mcs_rate_flag |= TX_RATE_SGI; + else + *mcs_rate_flag &= ~TX_RATE_SGI; + + WMA_LOGD("%s exit: match_rate %d index: %d" + " mcs_rate_flag: 0x%x nss %d guard interval %d", + __func__, match_rate, index, *mcs_rate_flag, + *nss, *guard_interval); return match_rate ? index : INVALID_MCS_IDX; }