Browse Source

qcacld-3.0: Add EHT bitrate support

Add EHT MCS to rate mapping for NSS 1 and NSS 2.

Update TX/RX bitrate for EHT connection depending on current MCS/NSS
configuration.

Change-Id: I0c55beab2c6b9a9609d5a2e454a0c0e8c1312d09
CRs-Fixed: 3181127
Arun Kumar Khandavalli 2 years ago
parent
commit
5e29697d88

+ 10 - 0
components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h

@@ -91,6 +91,11 @@ enum stats_req_type {
  * @TX_RATE_HE80: HE 80 rates
  * @TX_RATE_HE160: HE 160 rates
  * @TX_RATE_VHT160: VHT 160 rates
+ * @TX_RATE_EHT20: EHT 20 rates
+ * @TX_RATE_EHT40: EHT 40 rates
+ * @TX_RATE_EHT80: EHT 80 rates
+ * @TX_RATE_EHT160: EHT 160 rates
+ * @TX_RATE_EHT320: EHT 320 rates
  */
 enum tx_rate_info {
 	TX_RATE_LEGACY = 0x1,
@@ -106,6 +111,11 @@ enum tx_rate_info {
 	TX_RATE_HE80 = 0x400,
 	TX_RATE_HE160 = 0x800,
 	TX_RATE_VHT160 = 0x1000,
+	TX_RATE_EHT20 = 0x2000,
+	TX_RATE_EHT40 = 0x4000,
+	TX_RATE_EHT80 = 0x8000,
+	TX_RATE_EHT160 = 0x10000,
+	TX_RATE_EHT320 = 0x20000,
 };
 
 /**

+ 22 - 0
core/hdd/inc/wlan_hdd_eht.h

@@ -116,6 +116,20 @@ void hdd_sysfs_11be_rate_create(struct hdd_adapter *adapter);
  * Return: None
  */
 void hdd_sysfs_11be_rate_destroy(struct hdd_adapter *adapter);
+
+/**
+ * wlan_hdd_fill_os_eht_rateflags() - Fill EHT 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
+ */
+void wlan_hdd_fill_os_eht_rateflags(struct rate_info *os_rate,
+				    enum tx_rate_info rate_flags,
+				    uint8_t dcm,
+				    enum txrate_gi guard_interval);
 #else
 static inline
 void hdd_update_tgt_eht_cap(struct hdd_context *hdd_ctx,
@@ -151,5 +165,13 @@ static inline void wlan_hdd_get_mlo_link_id(struct hdd_beacon_data *beacon,
 					    uint8_t *link_id, uint8_t *num_link)
 {
 }
+
+static inline
+void wlan_hdd_fill_os_eht_rateflags(struct rate_info *os_rate,
+				    enum tx_rate_info rate_flags,
+				    uint8_t dcm,
+				    enum txrate_gi guard_interval)
+{
+}
 #endif
 #endif /* if !defined(WLAN_HDD_EHT_H)*/

+ 8 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -23713,6 +23713,12 @@ void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
 		qdf_mem_free(chan);
 }
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) || defined(CFG80211_11BE_BASIC)
+#define SET_RATE_INFO_BW_320 RATE_INFO_BW_320
+#else
+#define SET_RATE_INFO_BW_320 RATE_INFO_BW_160
+#endif
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
 static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
 {
@@ -23729,6 +23735,8 @@ static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
 		return RATE_INFO_BW_80;
 	case HDD_RATE_BW_160:
 		return RATE_INFO_BW_160;
+	case HDD_RATE_BW_320:
+		return SET_RATE_INFO_BW_320;
 	}
 
 	hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);

+ 2 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -597,6 +597,7 @@ int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
  * @HDD_RATE_BW_40: 40MHz
  * @HDD_RATE_BW_80: 80MHz
  * @HDD_RATE_BW_160: 160 MHz
+ * @HDD_RATE_BW_320: 320 MHz
  */
 enum hdd_rate_info_bw {
 	HDD_RATE_BW_5,
@@ -605,6 +606,7 @@ enum hdd_rate_info_bw {
 	HDD_RATE_BW_40,
 	HDD_RATE_BW_80,
 	HDD_RATE_BW_160,
+	HDD_RATE_BW_320,
 };
 
 /**

+ 51 - 0
core/hdd/src/wlan_hdd_eht.c

@@ -346,4 +346,55 @@ void hdd_sysfs_11be_rate_destroy(struct hdd_adapter *adapter)
 	device_remove_file(&adapter->dev->dev, &dev_attr_11be_rate);
 }
 
+/**
+ * hdd_map_eht_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_eht_gi_to_os(enum txrate_gi guard_interval)
+{
+	switch (guard_interval) {
+	case TXRATE_GI_0_8_US:
+		return NL80211_RATE_INFO_EHT_GI_0_8;
+	case TXRATE_GI_1_6_US:
+		return NL80211_RATE_INFO_EHT_GI_1_6;
+	case TXRATE_GI_3_2_US:
+		return NL80211_RATE_INFO_EHT_GI_3_2;
+	default:
+		return NL80211_RATE_INFO_EHT_GI_0_8;
+	}
+}
+
+/**
+ * wlan_hdd_fill_os_eht_rateflags() - Fill EHT 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
+ */
+void wlan_hdd_fill_os_eht_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 don't
+	 * fill RATE_INFO_BW_EHT_RU.
+	 */
+	if (rate_flags & (TX_RATE_EHT80 | TX_RATE_EHT40 |
+	    TX_RATE_EHT20 | TX_RATE_EHT160 | TX_RATE_EHT320)) {
+		if (rate_flags & TX_RATE_EHT320)
+			hdd_set_rate_bw(os_rate, HDD_RATE_BW_320);
+		else if (rate_flags & TX_RATE_EHT160)
+			hdd_set_rate_bw(os_rate, HDD_RATE_BW_160);
+		else if (rate_flags & TX_RATE_EHT80)
+			hdd_set_rate_bw(os_rate, HDD_RATE_BW_80);
+		else if (rate_flags & TX_RATE_EHT40)
+			hdd_set_rate_bw(os_rate, HDD_RATE_BW_40);
+
+		os_rate->flags |= RATE_INFO_FLAGS_EHT_MCS;
+	}
+}
 #endif

+ 2 - 0
core/hdd/src/wlan_hdd_stats.c

@@ -5484,6 +5484,8 @@ static void wlan_hdd_fill_os_rate_info(enum tx_rate_info rate_flags,
 	hdd_set_rate_bw(os_rate, HDD_RATE_BW_20);
 	os_rate->mcs = mcs_index;
 
+	wlan_hdd_fill_os_eht_rateflags(os_rate, rate_flags, dcm,
+				       guard_interval);
 	wlan_hdd_fill_os_he_rateflags(os_rate, rate_flags, dcm, guard_interval);
 
 	if (rate_flags & (TX_RATE_VHT160 | TX_RATE_VHT80 | TX_RATE_VHT40 |

+ 18 - 0
core/wma/inc/wma_internal.h

@@ -1756,4 +1756,22 @@ int wma_latency_level_event_handler(void *wma_ctx, uint8_t *event_buff,
  */
 int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf,
 				  uint32_t len);
+/**
+ * wma_mcs_rate_match() - find the match mcs 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
+ * and return nss/guard interval.
+ *
+ * Return: the found rate or 0 otherwise
+ */
+uint16_t wma_mcs_rate_match(uint16_t raw_rate, bool is_he,
+			    const uint16_t *nss1_rate,
+			    const uint16_t *nss2_rate,
+			    uint8_t *nss, enum txrate_gi *guard_interval);
 #endif

+ 11 - 27
core/wma/src/wma_data.c

@@ -82,6 +82,7 @@
 #include <wlan_mlme_main.h>
 #include <wlan_cm_api.h>
 #include "wlan_pkt_capture_ucfg_api.h"
+#include "wma_eht.h"
 
 struct wma_search_rate {
 	int32_t rate;
@@ -759,24 +760,6 @@ 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_11BE
-/**
- * wma_get_bss_eht_capable() - whether bss is eht capable or not
- * @add_bss: add_bss params
- *
- * Return: true if eht capable is present
- */
-static bool wma_get_bss_eht_capable(struct bss_params *add_bss)
-{
-	return add_bss->eht_capable;
-}
-#else
-static bool wma_get_bss_eht_capable(struct bss_params *add_bss)
-{
-	return false;
-}
-#endif
-
 #ifdef WLAN_FEATURE_11AX
 /**
  * wma_set_bss_rate_flags_he() - set rate flags based on BSS capability
@@ -870,7 +853,7 @@ void wma_set_bss_rate_flags(tp_wma_handle wma, uint8_t vdev_id,
 	struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
 	struct vdev_mlme_obj *vdev_mlme;
 	enum tx_rate_info *rate_flags;
-
+	QDF_STATUS qdf_status;
 
 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(iface->vdev);
 	if (!vdev_mlme) {
@@ -880,14 +863,15 @@ 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 (QDF_STATUS_SUCCESS !=
-		wma_set_bss_rate_flags_he(rate_flags, add_bss)) {
-		if (add_bss->vhtCapable) {
-			*rate_flags = wma_get_vht_rate_flags(add_bss->ch_width);
-		}
-		/* avoid to conflict with htCapable flag */
-		else if (add_bss->htCapable) {
-			*rate_flags |= wma_get_ht_rate_flags(add_bss->ch_width);
+	qdf_status = wma_set_bss_rate_flags_eht(rate_flags, add_bss);
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		if (QDF_STATUS_SUCCESS !=
+			wma_set_bss_rate_flags_he(rate_flags, add_bss)) {
+			if (add_bss->vhtCapable)
+				*rate_flags = wma_get_vht_rate_flags(add_bss->ch_width);
+			/* avoid to conflict with htCapable flag */
+			else if (add_bss->htCapable)
+				*rate_flags |= wma_get_ht_rate_flags(add_bss->ch_width);
 		}
 	}
 

+ 3 - 1
core/wma/src/wma_dev_if.c

@@ -1022,7 +1022,9 @@ void wma_update_rate_flags_after_vdev_restart(tp_wma_handle wma,
 	des_chan = wlan_vdev_mlme_get_des_chan(iface->vdev);
 	bss_phymode = des_chan->ch_phymode;
 
-	if (IS_WLAN_PHYMODE_HE(bss_phymode)) {
+	if (wma_is_eht_phymode_supported(bss_phymode)) {
+		rate_flags = wma_get_eht_rate_flags(des_chan->ch_width);
+	} else if (IS_WLAN_PHYMODE_HE(bss_phymode)) {
 		rate_flags = wma_get_he_rate_flags(des_chan->ch_width);
 	} else if (IS_WLAN_PHYMODE_VHT(bss_phymode)) {
 		rate_flags = wma_get_vht_rate_flags(des_chan->ch_width);

+ 293 - 0
core/wma/src/wma_eht.c

@@ -28,6 +28,157 @@
 #include "wma_internal.h"
 
 #if defined(WLAN_FEATURE_11BE)
+/* MCS Based EHT rate table */
+/* MCS parameters with Nss = 1*/
+static const struct index_eht_data_rate_type eht_mcs_nss1[] = {
+/* MCS,  {dcm0:0.8/1.6/3.2}, {dcm1:0.8/1.6/3.2} */
+	{0,  {{86,   81,   73}, {0} }, /* EHT20 */
+	     {{172,  163,  146}, {0} }, /* EHT40 */
+	     {{360,  340,  306}, {0} }, /* EHT80 */
+	     {{721,  681,  613}, {0} }, /* EHT160 */
+	     {{1441,  1361,  1225}, {0}}} , /* EHT320 */
+	{1,  {{172,  163,  146 }, {0} },
+	     {{344,  325,  293 }, {0} },
+	     {{721,  681,  613 }, {0} },
+	     {{1441, 1361, 1225}, {0} },
+	     {{2882, 2722, 2450}, {0} } } ,
+	{2,  {{258,  244,  219 }, {0} },
+	     {{516,  488,  439 }, {0} },
+	     {{1081, 1021, 919 }, {0} },
+	     {{2162, 2042, 1838}, {0} },
+	     {{4324, 4083, 3675}, {0} } } ,
+	{3,  {{344,  325,  293 }, {0} },
+	     {{688,  650,  585 }, {0} },
+	     {{1441, 1361, 1225}, {0} },
+	     {{2882, 2722, 2450}, {0} },
+	     {{5765, 5444, 4900}, {0} } } ,
+	{4,  {{516,  488,  439 }, {0} },
+	     {{1032, 975,  878 }, {0} },
+	     {{2162, 2042, 1838}, {0} },
+	     {{4324, 4083, 3675}, {0} },
+	     {{8647, 8167, 7350}, {0} } } ,
+	{5,  {{688,  650,  585 }, {0} },
+	     {{1376, 1300, 1170}, {0} },
+	     {{2882, 2722, 2450}, {0} },
+	     {{5765, 5444, 4900}, {0} },
+	     {{11529, 10889, 9800}, {0}}} ,
+	{6,  {{774,  731,  658 }, {0} },
+	     {{1549, 1463, 1316}, {0} },
+	     {{3243, 3063, 2756}, {0} },
+	     {{6485, 6125, 5513}, {0} },
+	     {{12971, 12250, 11025}, {0} } } ,
+	{7,  {{860,  813,  731 }, {0} },
+	     {{1721, 1625, 1463}, {0} },
+	     {{3603, 3403, 3063}, {0} },
+	     {{7206, 6806, 6125}, {0} },
+	     {{14412, 13611, 12250}, {0} } } ,
+	{8,  {{1032, 975,  878 }, {0} },
+	     {{2065, 1950, 1755}, {0} },
+	     {{4324, 4083, 3675}, {0} },
+	     {{8647, 8167, 7350}, {0} },
+	     {{17294, 16333, 14700}, {0} }} ,
+	{9,  {{1147, 1083, 975 }, {0} },
+	     {{2294, 2167, 1950}, {0} },
+	     {{4804, 4537, 4083}, {0} },
+	     {{9608, 9074, 8167}, {0} },
+	     {{19216, 18148, 16333}, {0} } } ,
+	{10, {{1290, 1219, 1097}, {0} },
+	     {{2581, 2438, 2194}, {0} },
+	     {{5404, 5104, 4594}, {0} },
+	     {{10809, 10208, 9188}, {0} },
+	     {{21618, 20417, 18375}, {0} } } ,
+	{11, {{1434, 1354, 1219}, {0} },
+	     {{2868, 2708, 2438}, {0} },
+	     {{6004, 5671, 5104}, {0} },
+	     {{12010, 11342, 10208}, {0} },
+	     {{24020, 22685, 20417}, {0} }} ,
+	{12, {{1549, 1463, 1316}, {0} },
+	     {{3097, 2925, 2633}, {0} },
+	     {{6485, 6125, 5513}, {0} },
+	     {{12971, 12250, 11025}, {0} },
+	     {{25941, 24500, 22050}, {0} }} ,
+	{13, {{1721, 1625, 1463}, {0} },
+	     {{3441, 3250, 2925}, {0} },
+	     {{7206, 6806, 6125}, {0} },
+	     {{14412, 13611, 12250}, {0}},
+	     {{28824, 27222, 24500}, {0}}} ,
+};
+
+/*MCS parameters with Nss = 2*/
+static const struct index_eht_data_rate_type eht_mcs_nss2[] = {
+/* MCS,  {dcm0:0.8/1.6/3.2}, {dcm1:0.8/1.6/3.2} */
+	{0,  {{172,   163,   146 }, {0} }, /* EHT20 */
+	     {{344,   325,   293 }, {0} }, /* EHT40 */
+	     {{721,   681,   613 }, {0} }, /* EHT80 */
+	     {{1442, 1362, 1225},   {0} }, /* EHT160 */
+	     {{2882, 2722, 2450},   {0} } } , /* EHT320 */
+	{1,  {{344,   325,   293 }, {0} },
+	     {{688,   650,   585 }, {0} },
+	     {{1441,  1361,  1225}, {0} },
+	     {{2882, 2722, 2450},   {0}},
+	     {{5764, 5444, 4900},   {0} }} ,
+	{2,  {{516,   488,   439 }, {0} },
+	     {{1032,  975,   878 }, {0} },
+	     {{2162,  2042,  1838}, {0} },
+	     {{4324, 4084, 3676}, {0} },
+	     {{8648, 8166, 7350}, {0} } } ,
+	{3,  {{688,   650,   585 }, {0} },
+	     {{1376,  1300,  1170}, {0} },
+	     {{2882,  2722,  2450}, {0} },
+	     {{5764, 5444, 4900}, {0} },
+	     {{11530, 10888, 9800}, {0}} } ,
+	{4,  {{1032,  975,   878 }, {0} },
+	     {{2065,  1950,  1755}, {0} },
+	     {{4324,  4083,  3675}, {0} },
+	     {{8648, 8166, 7350}, {0} },
+	     {{17294, 16334, 14700}, {0}}},
+	{5,  {{1376,  1300,  1170}, {0} },
+	     {{2753,  2600,  2340}, {0} },
+	     {{5765,  5444,  4900}, {0} },
+	     {{11530, 10888, 9800}, {0} },
+	     {{23058, 21778, 19600}, {0} }} ,
+	{6,  {{1549,  1463,  1316}, {0} },
+	     {{3097,  2925,  2633}, {0} },
+	     {{6485,  6125,  5513}, {0} },
+	     {{12977, 12250, 11026}, {0} },
+	     {{25942, 24500, 22050}, {0} }} ,
+	{7,  {{1721,  1625,  1463}, {0} },
+	     {{3441,  3250,  2925}, {0} },
+	     {{7206,  6806,  6125}, {0} },
+	     {{14412, 13612, 12250}, {0} },
+	     {{28824, 27222, 24500}, {0} }} ,
+	{8,  {{2065,  1950,  1755}, {0} },
+	     {{4129,  3900,  3510}, {0} },
+	     {{8647,  8167,  7350}, {0} },
+	     {{17294, 16334, 14700}, {0} },
+	     {{34588, 32666, 29400}, {0} }} ,
+	{9,  {{2294,  2167,  1950}, {0} },
+	     {{4588,  4333,  3900}, {0} },
+	     {{9607,  9074,  8166}, {0} },
+	     {{19216, 18148, 16334}, {0} },
+	     {{38432, 36296, 32666}, {0} }} ,
+	{10, {{2581,  2438,  2194}, {0} },
+	     {{5162,  4875,  4388}, {0} },
+	     {{10809, 10208, 9188}, {0} },
+	     {{21618, 20416, 18376}, {0} },
+	     {{43236, 40834, 36750}, {0} }} ,
+	{11, {{2868,  2708,  2438}, {0} },
+	     {{5735,  5417,  4875}, {0} },
+	     {{12010, 11343, 10208}, {0} },
+	     {{24020, 22686, 20416}, {0} },
+	     {{48040, 45370, 40834}, {0} }} ,
+	{12, {{3097,  2925,  2633}, {0} },
+	     {{6194,  5850,  5265}, {0} },
+	     {{12971, 12250, 11025}, {0} },
+	     {{25942, 24500, 22050}, {0} },
+	     {{51882, 49000, 44100}, {0} }} ,
+	{13, {{3441,  3250,  2925}, {0} },
+	     {{6882,  6500,  5850}, {0} },
+	     {{14412, 13611, 12250}, {0} },
+	     {{28824, 27222, 24500}, {0} },
+	     {{57648, 54444, 49000}, {0} }}
+};
+
 /**
  * wma_convert_eht_cap() - convert EHT capabilities into dot11f structure
  * @eht_cap: pointer to dot11f structure
@@ -835,4 +986,146 @@ void wma_set_eht_txbf_params(uint8_t vdev_id, bool su_bfer,
 	if (QDF_IS_STATUS_ERROR(status))
 		wma_err("failed to set EHTMU_MODE(status = %d)", status);
 }
+
+QDF_STATUS wma_set_bss_rate_flags_eht(enum tx_rate_info *rate_flags,
+				      struct bss_params *add_bss)
+{
+	if (!add_bss->eht_capable)
+		return QDF_STATUS_E_NOSUPPORT;
+
+	*rate_flags |= wma_get_eht_rate_flags(add_bss->ch_width);
+
+	wma_debug("ehe_capable %d rate_flags 0x%x", add_bss->eht_capable,
+		  *rate_flags);
+	return QDF_STATUS_SUCCESS;
+}
+
+bool wma_get_bss_eht_capable(struct bss_params *add_bss)
+{
+	return add_bss->eht_capable;
+}
+
+enum tx_rate_info wma_get_eht_rate_flags(enum phy_ch_width ch_width)
+{
+	enum tx_rate_info rate_flags = 0;
+
+	if (ch_width == CH_WIDTH_320MHZ)
+		rate_flags |= TX_RATE_EHT320 | TX_RATE_EHT160 |
+				TX_RATE_EHT80 | TX_RATE_EHT40 | TX_RATE_EHT20;
+	else if (ch_width == CH_WIDTH_160MHZ || ch_width == CH_WIDTH_80P80MHZ)
+		rate_flags |= TX_RATE_EHT160 | TX_RATE_EHT80 | TX_RATE_EHT40 |
+				TX_RATE_EHT20;
+	else if (ch_width == CH_WIDTH_80MHZ)
+		rate_flags |= TX_RATE_EHT80 | TX_RATE_EHT40 | TX_RATE_EHT20;
+	else if (ch_width)
+		rate_flags |= TX_RATE_EHT40 | TX_RATE_EHT20;
+	else
+		rate_flags |= TX_RATE_EHT20;
+
+	return rate_flags;
+}
+
+uint16_t wma_match_eht_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;
+	uint8_t dcm_index_max = 1;
+	uint8_t dcm_index;
+	uint16_t match_rate = 0;
+	const uint16_t *nss1_rate;
+	const uint16_t *nss2_rate;
+
+	*p_index = 0;
+	if (!(rate_flags & (TX_RATE_EHT320 | TX_RATE_EHT160 | TX_RATE_EHT80 |
+	      TX_RATE_EHT40 | TX_RATE_EHT20)))
+		return 0;
+
+	for (index = 0; index < MAX_EHT_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_EHT320) {
+				nss1_rate = &eht_mcs_nss1[index].supported_eht320_rate[dcm_index][0];
+				nss2_rate = &eht_mcs_nss2[index].supported_eht320_rate[dcm_index][0];
+				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_EHT160) {
+				nss1_rate = &eht_mcs_nss1[index].supported_eht160_rate[dcm_index][0];
+				nss2_rate = &eht_mcs_nss2[index].supported_eht160_rate[dcm_index][0];
+				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_EHT80 | TX_RATE_EHT160)) {
+				nss1_rate = &eht_mcs_nss1[index].supported_eht80_rate[dcm_index][0];
+				nss2_rate = &eht_mcs_nss2[index].supported_eht80_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) {
+					*mcs_rate_flag &= ~TX_RATE_EHT160;
+					goto rate_found;
+				}
+			}
+
+			if (rate_flags & (TX_RATE_EHT40 | TX_RATE_EHT80 |
+					  TX_RATE_EHT160)) {
+				nss1_rate = &eht_mcs_nss1[index].supported_eht40_rate[dcm_index][0];
+				nss2_rate = &eht_mcs_nss2[index].supported_eht40_rate[dcm_index][0];
+				match_rate = wma_mcs_rate_match(raw_rate, 1,
+								nss1_rate,
+								nss2_rate,
+								nss,
+								guard_interval);
+
+				if (match_rate) {
+					*mcs_rate_flag &= ~(TX_RATE_EHT80 |
+							    TX_RATE_EHT160);
+					goto rate_found;
+				}
+			}
+
+			if (rate_flags & (TX_RATE_EHT80 | TX_RATE_EHT40 |
+				TX_RATE_HE20 | TX_RATE_HE160)) {
+				nss1_rate = &eht_mcs_nss1[index].supported_eht20_rate[dcm_index][0];
+				nss2_rate = &eht_mcs_nss2[index].supported_eht20_rate[dcm_index][0];
+				match_rate = wma_mcs_rate_match(raw_rate, 1,
+								nss1_rate,
+								nss2_rate,
+								nss,
+								guard_interval);
+
+				if (match_rate) {
+					*mcs_rate_flag &= TX_RATE_EHT20;
+					goto rate_found;
+				}
+			}
+		}
+	}
+
+rate_found:
+	if (match_rate) {
+		if (dcm_index == 1)
+			*dcm = 1;
+		*p_index = index;
+	}
+	return match_rate;
+}
 #endif

+ 107 - 0
core/wma/src/wma_eht.h

@@ -28,6 +28,27 @@ enum EHT_TXRX_MCS_NSS_IDX {
 };
 
 #if defined(WLAN_FEATURE_11BE)
+#define MAX_EHT_DCM_INDEX 2
+#define MAX_EHT_MCS_IDX 14
+/* valid only for mcs-15 */
+#define IS_EHT_ MCS_HAS_DCM_RATE(val)  ((val) == 15)
+/**
+ * struct index_eht_data_rate_type - eht data rate type
+ * @beacon_rate_index: Beacon rate index
+ * @supported_eht20_rate: eht20 rate
+ * @supported_eht40_rate: eht40 rate
+ * @supported_eht80_rate: eht80 rate
+ * @supported_eht160_rate: eht160 rate
+ */
+struct index_eht_data_rate_type {
+	uint8_t beacon_rate_index;
+	uint16_t supported_eht20_rate[MAX_EHT_DCM_INDEX][3];
+	uint16_t supported_eht40_rate[MAX_EHT_DCM_INDEX][3];
+	uint16_t supported_eht80_rate[MAX_EHT_DCM_INDEX][3];
+	uint16_t supported_eht160_rate[MAX_EHT_DCM_INDEX][3];
+	uint16_t supported_eht320_rate[MAX_EHT_DCM_INDEX][3];
+};
+
 /*
  * wma_eht_update_tgt_services() - update tgt cfg to indicate 11be support
  * @wmi_handle: pointer to WMI handle
@@ -176,6 +197,57 @@ void wma_set_eht_txbf_cfg(struct mac_context *mac, uint8_t vdev_id);
  */
 void wma_set_eht_txbf_params(uint8_t vdev_id, bool su_bfer,
 			     bool su_bfee, bool mu_bfer);
+
+/**
+ * wma_get_eht_rate_flags() - Return the EHT rate flags corresponding to the BW
+ * @ch_width: BW for which rate flags is required
+ *
+ * Return: Rate flags corresponding to ch_width
+ */
+enum tx_rate_info wma_get_eht_rate_flags(enum phy_ch_width ch_width);
+
+/**
+ * wma_match_eht_rate() - get eht rate matching with nss
+ * @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
+ */
+uint16_t wma_match_eht_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);
+
+/**
+ * wma_set_bss_rate_flags_eht() - set rate flags based on BSS capability
+ * @rate_flags: rate_flags pointer
+ * @add_bss: add_bss params
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wma_set_bss_rate_flags_eht(enum tx_rate_info *rate_flags,
+				      struct bss_params *add_bss);
+
+/**
+ * wma_get_bss_eht_capable() - whether bss is eht capable or not
+ * @add_bss: add_bss params
+ *
+ * Return: true if eht capable is present
+ */
+bool wma_get_bss_eht_capable(struct bss_params *add_bss);
+
+static
+inline bool wma_is_eht_phymode_supported(enum wlan_phymode bss_phymode)
+{
+	return IS_WLAN_PHYMODE_EHT(bss_phymode);
+}
 #else
 static inline void wma_eht_update_tgt_services(struct wmi_unified *wmi_handle,
 					       struct wma_tgt_services *cfg)
@@ -242,5 +314,40 @@ void wma_set_eht_txbf_params(uint8_t vdev_id, bool su_bfer,
 			     bool su_bfee, bool mu_bfer)
 {
 }
+
+static inline
+QDF_STATUS wma_set_bss_rate_flags_eht(enum tx_rate_info *rate_flags,
+				      struct bss_params *add_bss)
+{
+	return QDF_STATUS_E_INVAL;
+}
+
+static inline
+enum tx_rate_info wma_get_eht_rate_flags(enum phy_ch_width ch_width)
+{
+	return TX_RATE_EHT20;
+}
+
+static inline
+uint16_t wma_match_eht_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;
+}
+
+static inline
+bool wma_get_bss_eht_capable(struct bss_params *add_bss)
+{
+	return false;
+}
+
+static inline bool wma_is_eht_phymode_supported(enum wlan_phymode bss_phymode)
+{
+	return false;
+}
 #endif
 #endif

+ 21 - 30
core/wma/src/wma_utils.c

@@ -69,10 +69,11 @@
 #include <cdp_txrx_host_stats.h>
 #include "wlan_mlme_ucfg_api.h"
 #include <wlan_cp_stats_mc_tgt_api.h>
+#include "wma_eht.h"
 
 /* MCS Based rate table */
 /* HT MCS parameters with Nss = 1 */
-static struct index_data_rate_type mcs_nss1[] = {
+static const struct index_data_rate_type mcs_nss1[] = {
 	/* MCS L20  S20   L40   S40 */
 	{0,  {65,  72},  {135,  150 } },
 	{1,  {130, 144}, {270,  300 } },
@@ -85,7 +86,7 @@ static struct index_data_rate_type mcs_nss1[] = {
 };
 
 /* HT MCS parameters with Nss = 2 */
-static struct index_data_rate_type mcs_nss2[] = {
+static const struct index_data_rate_type mcs_nss2[] = {
 	/* MCS L20  S20    L40   S40 */
 	{0,  {130,  144},  {270,  300 } },
 	{1,  {260,  289},  {540,  600 } },
@@ -99,7 +100,7 @@ static struct index_data_rate_type mcs_nss2[] = {
 
 /* MCS Based VHT rate table */
 /* MCS parameters with Nss = 1*/
-static struct index_vht_data_rate_type vht_mcs_nss1[] = {
+static const struct index_vht_data_rate_type vht_mcs_nss1[] = {
 	/* MCS L20  S20    L40   S40    L80   S80    L160  S160*/
 	{0,  {65,   72 }, {135,  150},  {293,  325}, {585, 650} },
 	{1,  {130,  144}, {270,  300},  {585,  650}, {1170, 1300} },
@@ -114,7 +115,7 @@ static struct index_vht_data_rate_type vht_mcs_nss1[] = {
 };
 
 /*MCS parameters with Nss = 2*/
-static struct index_vht_data_rate_type vht_mcs_nss2[] = {
+static const struct index_vht_data_rate_type vht_mcs_nss2[] = {
 	/* MCS L20  S20    L40    S40    L80    S80    L160   S160*/
 	{0,  {130,  144},  {270,  300},  { 585,  650}, {1170, 1300} },
 	{1,  {260,  289},  {540,  600},  {1170, 1300}, {2340, 2600} },
@@ -131,7 +132,7 @@ static struct index_vht_data_rate_type vht_mcs_nss2[] = {
 #ifdef WLAN_FEATURE_11AX
 /* MCS Based HE rate table */
 /* MCS parameters with Nss = 1*/
-static struct index_he_data_rate_type he_mcs_nss1[] = {
+static const 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 */
@@ -192,7 +193,7 @@ static struct index_he_data_rate_type he_mcs_nss1[] = {
 };
 
 /*MCS parameters with Nss = 2*/
-static struct index_he_data_rate_type he_mcs_nss2[] = {
+static const 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 */
@@ -279,26 +280,10 @@ void wma_swap_bytes(void *pv, uint32_t n)
 #define SWAPME(x, len) wma_swap_bytes(&x, len)
 #endif /* BIG_ENDIAN_HOST */
 
-/**
- * wma_mcs_rate_match() - find the match mcs 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
- * and return nss/guard interval.
- *
- * Return: the found rate or 0 otherwise
- */
-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)
+uint16_t wma_mcs_rate_match(uint16_t raw_rate, bool is_he,
+			    const uint16_t *nss1_rate,
+			    const uint16_t *nss2_rate,
+			    uint8_t *nss, enum txrate_gi *guard_interval)
 {
 	uint8_t gi_index;
 	uint8_t gi_index_max = 2;
@@ -358,8 +343,8 @@ static uint16_t wma_match_he_rate(uint16_t raw_rate,
 	uint8_t dcm_index_max = 1;
 	uint8_t dcm_index = 0;
 	uint16_t match_rate = 0;
-	uint16_t *nss1_rate;
-	uint16_t *nss2_rate;
+	const uint16_t *nss1_rate;
+	const uint16_t *nss2_rate;
 
 	*p_index = 0;
 	if (!(rate_flags & (TX_RATE_HE160 | TX_RATE_HE80 | TX_RATE_HE40 |
@@ -478,14 +463,20 @@ uint8_t wma_get_mcs_idx(uint16_t raw_rate, enum tx_rate_info rate_flags,
 {
 	uint8_t  index = 0;
 	uint16_t match_rate = 0;
-	uint16_t *nss1_rate;
-	uint16_t *nss2_rate;
+	const uint16_t *nss1_rate;
+	const uint16_t *nss2_rate;
 
 	wma_debug("Rates from FW:  raw_rate:%d rate_flgs: 0x%x is_he_mcs_12_13_supported: %d nss: %d",
 		  raw_rate, rate_flags, is_he_mcs_12_13_supported, *nss);
 
 	*mcs_rate_flag = rate_flags;
 
+	match_rate = wma_match_eht_rate(raw_rate, rate_flags,
+					nss, dcm, guard_interval,
+					mcs_rate_flag, &index);
+	if (match_rate)
+		goto rate_found;
+
 	match_rate = wma_match_he_rate(raw_rate, rate_flags,
 				       is_he_mcs_12_13_supported,
 				       nss, dcm, guard_interval,