Эх сурвалжийг харах

qcacld-3.0: Fix the incorrect mcs rate index conversion

qcacld-2.0 to qcacld-3.0 propagation

Driver would get the tx rate info from firmware and converts it
to mcs index or legacy rate for userspace.

The problem here is when firmware creates a valid ratesets,
it includes all the subset of lower grade rates.
e.g

 - VHT80 would include VHT80/VHT40/VHT20, VHT40 include VHT40/HT20
 - HT40 would include HT40/HT20
 - NSS2 would include NSS2 and NSS1

So that firmware would not only use one rateset, but would use all
other valid rates, the fix is to go through all other possibilities
to make sure the rate look up can find the correct mcs index.

Change-Id: I5df9059b73954951c4adec56002a3eba80915752
CRs-fixed: 936078
Ryan Hsu 9 жил өмнө
parent
commit
6139d2de9d

+ 13 - 7
core/hdd/src/wlan_hdd_stats.c

@@ -1779,13 +1779,12 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
 			pAdapter->hdd_stats.ClassA_stat.mcs_index = 0;
 		}
 	}
-#ifdef LINKSPEED_DEBUG_ENABLED
-	pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d\n",
-		sinfo->signal, pCfg->reportMaxLinkSpeed, myRate,
-		(int)pCfg->linkSpeedRssiHigh, (int)pCfg->linkSpeedRssiMid,
-		(int)pCfg->linkSpeedRssiLow, (int)rate_flags,
-		(int)pAdapter->hdd_stats.ClassA_stat.mcs_index);
-#endif /* LINKSPEED_DEBUG_ENABLED */
+
+	hdd_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d",
+		 sinfo->signal, pCfg->reportMaxLinkSpeed, myRate,
+		 (int)pCfg->linkSpeedRssiHigh, (int)pCfg->linkSpeedRssiMid,
+		 (int)pCfg->linkSpeedRssiLow, (int)rate_flags,
+		 (int)pAdapter->hdd_stats.ClassA_stat.mcs_index);
 
 	if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed) {
 		/* we do not want to necessarily report the current speed */
@@ -2118,6 +2117,13 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
 #endif /* LINKSPEED_DEBUG_ENABLED */
 		}
 	}
+
+	if (rate_flags & eHAL_TX_RATE_LEGACY)
+		hdd_info("Reporting legacy rate %d", sinfo->txrate.legacy);
+	else
+		hdd_info("Reporting MCS rate %d flags 0x%x",
+			 sinfo->txrate.mcs, sinfo->txrate.flags);
+
 	sinfo->filled |= STATION_INFO_TX_BITRATE;
 
 	sinfo->tx_bytes = pAdapter->stats.tx_bytes;

+ 14 - 12
core/wma/inc/wma_internal.h

@@ -111,27 +111,29 @@
 
 /**
  * struct index_data_rate_type - non vht data rate type
- * @beacon_rate_index: Beacon rate index
- * @supported_rate: Supported rate table
+ * @mcs_index: mcs rate index
+ * @ht20_rate: HT20 supported rate table
+ * @ht40_rate: HT40 supported rate table
  */
 struct index_data_rate_type {
-	uint8_t beacon_rate_index;
-	uint16_t supported_rate[4];
+	uint8_t  mcs_index;
+	uint16_t ht20_rate[2];
+	uint16_t ht40_rate[2];
 };
 
 #ifdef WLAN_FEATURE_11AC
 /**
  * struct index_vht_data_rate_type - vht data rate type
- * @beacon_rate_index: Beacon rate index
- * @supported_VHT80_rate: VHT80 rate
- * @supported_VHT40_rate: VHT40 rate
- * @supported_VHT20_rate: VHT20 rate
+ * @mcs_index: mcs rate index
+ * @ht20_rate: VHT20 supported rate table
+ * @ht40_rate: VHT40 supported rate table
+ * @ht80_rate: VHT80 supported rate table
  */
 struct index_vht_data_rate_type {
-	uint8_t beacon_rate_index;
-	uint16_t supported_VHT80_rate[2];
-	uint16_t supported_VHT40_rate[2];
-	uint16_t supported_VHT20_rate[2];
+	uint8_t mcs_index;
+	uint16_t ht20_rate[2];
+	uint16_t ht40_rate[2];
+	uint16_t ht80_rate[2];
 };
 #endif
 

+ 148 - 146
core/wma/src/wma_utils.c

@@ -74,61 +74,61 @@
 
 /* MCS Based rate table */
 /* HT MCS parameters with Nss = 1 */
-static struct index_data_rate_type supported_mcs_rate_nss1[] = {
-	/* MCS  L20   L40   S20  S40 */
-	{0, {65, 135, 72, 150} },
-	{1, {130, 270, 144, 300} },
-	{2, {195, 405, 217, 450} },
-	{3, {260, 540, 289, 600} },
-	{4, {390, 810, 433, 900} },
-	{5, {520, 1080, 578, 1200} },
-	{6, {585, 1215, 650, 1350} },
-	{7, {650, 1350, 722, 1500} }
+static struct index_data_rate_type mcs_nss1[] = {
+	/* MCS L20  S20   L40   S40 */
+	{0,  {65,  72},  {135,  150 } },
+	{1,  {130, 144}, {270,  300 } },
+	{2,  {195, 217}, {405,  450 } },
+	{3,  {260, 289}, {540,  600 } },
+	{4,  {390, 433}, {815,  900 } },
+	{5,  {520, 578}, {1080, 1200} },
+	{6,  {585, 650}, {1215, 1350} },
+	{7,  {650, 722}, {1350, 1500} }
 };
 
 /* HT MCS parameters with Nss = 2 */
-static struct index_data_rate_type supported_mcs_rate_nss2[] = {
-	/* MCS  L20    L40   S20   S40 */
-	{0, {130, 270, 144, 300} },
-	{1, {260, 540, 289, 600} },
-	{2, {390, 810, 433, 900} },
-	{3, {520, 1080, 578, 1200} },
-	{4, {780, 1620, 867, 1800} },
-	{5, {1040, 2160, 1156, 2400} },
-	{6, {1170, 2430, 1300, 2700} },
-	{7, {1300, 2700, 1444, 3000} }
+static struct index_data_rate_type mcs_nss2[] = {
+	/* MCS L20  S20    L40   S40 */
+	{0,  {130,  144},  {270,  300 } },
+	{1,  {260,  289},  {540,  600 } },
+	{2,  {390,  433},  {810,  900 } },
+	{3,  {520,  578},  {1080, 1200} },
+	{4,  {780,  867},  {1620, 1800} },
+	{5,  {1040, 1156}, {2160, 2400} },
+	{6,  {1170, 1300}, {2430, 2700} },
+	{7,  {1300, 1440}, {2700, 3000} }
 };
 
 #ifdef WLAN_FEATURE_11AC
 /* MCS Based VHT rate table */
 /* MCS parameters with Nss = 1*/
-static struct index_vht_data_rate_type supported_vht_mcs_rate_nss1[] = {
-	/* MCS  L80    S80     L40   S40    L20   S40 */
-	{0, {293, 325}, {135, 150}, {65, 72} },
-	{1, {585, 650}, {270, 300}, {130, 144} },
-	{2, {878, 975}, {405, 450}, {195, 217} },
-	{3, {1170, 1300}, {540, 600}, {260, 289} },
-	{4, {1755, 1950}, {810, 900}, {390, 433} },
-	{5, {2340, 2600}, {1080, 1200}, {520, 578} },
-	{6, {2633, 2925}, {1215, 1350}, {585, 650} },
-	{7, {2925, 3250}, {1350, 1500}, {650, 722} },
-	{8, {3510, 3900}, {1620, 1800}, {780, 867} },
-	{9, {3900, 4333}, {1800, 2000}, {780, 867} }
+static struct index_vht_data_rate_type vht_mcs_nss1[] = {
+	/* MCS L20  S20    L40   S40    L80   S80 */
+	{0,  {65,   72 }, {135,  150},  {293,  325} },
+	{1,  {130,  144}, {270,  300},  {585,  650} },
+	{2,  {195,  217}, {405,  450},  {878,  975} },
+	{3,  {260,  289}, {540,  600},  {1170, 1300} },
+	{4,  {390,  433}, {810,  900},  {1755, 1950} },
+	{5,  {520,  578}, {1080, 1200}, {2340, 2600} },
+	{6,  {585,  650}, {1215, 1350}, {2633, 2925} },
+	{7,  {650,  722}, {1350, 1500}, {2925, 3250} },
+	{8,  {780,  867}, {1620, 1800}, {3510, 3900} },
+	{9,  {865,  960}, {1800, 2000}, {3900, 4333} }
 };
 
 /*MCS parameters with Nss = 2*/
-static struct index_vht_data_rate_type supported_vht_mcs_rate_nss2[] = {
-	/* MCS  L80    S80     L40   S40    L20   S40 */
-	{0, {585, 650}, {270, 300}, {130, 144} },
-	{1, {1170, 1300}, {540, 600}, {260, 289} },
-	{2, {1755, 1950}, {810, 900}, {390, 433} },
-	{3, {2340, 2600}, {1080, 1200}, {520, 578} },
-	{4, {3510, 3900}, {1620, 1800}, {780, 867} },
-	{5, {4680, 5200}, {2160, 2400}, {1040, 1156} },
-	{6, {5265, 5850}, {2430, 2700}, {1170, 1300} },
-	{7, {5850, 6500}, {2700, 3000}, {1300, 1444} },
-	{8, {7020, 7800}, {3240, 3600}, {1560, 1733} },
-	{9, {7800, 8667}, {3600, 4000}, {1560, 1733} }
+static struct index_vht_data_rate_type vht_mcs_nss2[] = {
+	/* MCS L20  S20    L40    S40    L80    S80 */
+	{0,  {130,  144},  {270,  300},  { 585,  650} },
+	{1,  {260,  289},  {540,  600},  {1170, 1300} },
+	{2,  {390,  433},  {810,  900},  {1755, 1950} },
+	{3,  {520,  578},  {1080, 1200}, {2340, 2600} },
+	{4,  {780,  867},  {1620, 1800}, {3510, 3900} },
+	{5,  {1040, 1156}, {2160, 2400}, {4680, 5200} },
+	{6,  {1170, 1300}, {2430, 2700}, {5265, 5850} },
+	{7,  {1300, 1444}, {2700, 3000}, {5850, 6500} },
+	{8,  {1560, 1733}, {3240, 3600}, {7020, 7800} },
+	{9,  {1730, 1920}, {3600, 4000}, {7800, 8667} }
 };
 #endif /* WLAN_FEATURE_11AC */
 
@@ -159,6 +159,45 @@ 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
+ * @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
+ *
+ * This is a helper function to find the match of the tx_rate
+ * in terms of the nss1/nss2 rate with non-SGI/SGI.
+ *
+ * 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)
+{
+	WMA_LOGD("%s match_rate: %d, %d %d %d %d",
+		__func__, match_rate, nss1_rate, nss1_srate, nss2_rate,
+		nss2_srate);
+
+	if (match_rate == nss1_rate) {
+		return nss1_rate;
+	} else if (match_rate == nss1_srate) {
+		*is_sgi = true;
+		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_get_mcs_idx() - get mcs index
  * @maxRate: max rate
@@ -171,130 +210,93 @@ void wma_swap_bytes(void *pv, uint32_t n)
 static uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags,
 			       uint8_t nss, uint8_t *mcsRateFlag)
 {
-	uint8_t rateFlag = 0, curIdx = 0;
-	uint16_t curRate;
-	bool found = false;
-#ifdef WLAN_FEATURE_11AC
-	struct index_vht_data_rate_type *supported_vht_mcs_rate;
-#endif /* WLAN_FEATURE_11AC */
-	struct index_data_rate_type *supported_mcs_rate;
+	uint8_t  index = 0;
+	uint16_t match_rate;
+	bool is_sgi = false;
 
-	WMA_LOGD("%s rate:%d rate_flgs:%d", __func__, maxRate, rate_flags);
-#ifdef WLAN_FEATURE_11AC
-	supported_vht_mcs_rate = (struct index_vht_data_rate_type *)
-				 ((nss == 1) ? &supported_vht_mcs_rate_nss1 :
-				  &supported_vht_mcs_rate_nss2);
-#endif /* WLAN_FEATURE_11AC */
-	supported_mcs_rate = (struct index_data_rate_type *)
-			     ((nss == 1) ? &supported_mcs_rate_nss1 : &supported_mcs_rate_nss2);
+	WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d",
+		 __func__, maxRate, rate_flags, nss);
 
 	*mcsRateFlag = rate_flags;
 	*mcsRateFlag &= ~eHAL_TX_RATE_SGI;
 #ifdef WLAN_FEATURE_11AC
-	if (rate_flags &
-	    (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 | eHAL_TX_RATE_VHT80)) {
-
+	for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
 		if (rate_flags & eHAL_TX_RATE_VHT80) {
-			for (curIdx = 0; curIdx < MAX_VHT_MCS_IDX; curIdx++) {
-				rateFlag = 0;
-				if (curIdx >= 7) {
-					if (rate_flags & eHAL_TX_RATE_SGI)
-						rateFlag |= 0x1;
-				}
-
-				curRate = supported_vht_mcs_rate[curIdx].supported_VHT80_rate[rateFlag];
-				if (curRate == maxRate) {
-					found = true;
-					break;
-				}
-			}
+			/* check for vht80 nss1/2 rate set */
+			match_rate = wma_mcs_rate_match(maxRate, &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]);
+			if (match_rate)
+				goto rate_found;
 		}
-
-		if ((found == false) &&
-		    ((rate_flags & eHAL_TX_RATE_VHT80) ||
-		     (rate_flags & eHAL_TX_RATE_VHT40))) {
-			for (curIdx = 0; curIdx < MAX_VHT_MCS_IDX; curIdx++) {
-				rateFlag = 0;
-				if (curIdx >= 7) {
-					if (rate_flags & eHAL_TX_RATE_SGI)
-						rateFlag |= 0x1;
-				}
-
-				curRate = supported_vht_mcs_rate[curIdx].supported_VHT40_rate[rateFlag];
-				if (curRate == maxRate) {
-					found = true;
-					*mcsRateFlag &= ~eHAL_TX_RATE_VHT80;
-					break;
-				}
+		if ((rate_flags & eHAL_TX_RATE_VHT40) |
+		    (rate_flags & eHAL_TX_RATE_VHT80)) {
+			/* check for vht40 nss1/2 rate set */
+			match_rate = wma_mcs_rate_match(maxRate, &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]);
+			if (match_rate) {
+				*mcsRateFlag &= ~eHAL_TX_RATE_VHT80;
+				goto rate_found;
 			}
 		}
-
-		if ((found == false) &&
-		    ((rate_flags & eHAL_TX_RATE_VHT80) ||
-		     (rate_flags & eHAL_TX_RATE_VHT40) ||
-		     (rate_flags & eHAL_TX_RATE_VHT20))) {
-			for (curIdx = 0; curIdx < MAX_VHT_MCS_IDX; curIdx++) {
-				rateFlag = 0;
-				if (curIdx >= 7) {
-					if (rate_flags & eHAL_TX_RATE_SGI)
-						rateFlag |= 0x1;
-				}
-
-				curRate = supported_vht_mcs_rate[curIdx].supported_VHT20_rate[rateFlag];
-				if (curRate == maxRate) {
-					found = true;
-					*mcsRateFlag &=
-						~(eHAL_TX_RATE_VHT80 |
-						  eHAL_TX_RATE_VHT40);
-					break;
-				}
+		if ((rate_flags & eHAL_TX_RATE_VHT20) |
+		    (rate_flags & eHAL_TX_RATE_VHT40) |
+		    (rate_flags & eHAL_TX_RATE_VHT80)) {
+			/* check for vht20 nss1/2 rate set */
+			match_rate = wma_mcs_rate_match(maxRate, &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]);
+			if (match_rate) {
+				*mcsRateFlag &= ~(eHAL_TX_RATE_VHT80 |
+						eHAL_TX_RATE_VHT40);
+				goto rate_found;
 			}
 		}
 	}
 #endif /* WLAN_FEATURE_11AC */
-	if ((found == false) &&
-	    (rate_flags & (eHAL_TX_RATE_HT40 | eHAL_TX_RATE_HT20))) {
+	for (index = 0; index < MAX_HT_MCS_IDX; index++) {
 		if (rate_flags & eHAL_TX_RATE_HT40) {
-			rateFlag = 0x1;
-
-			for (curIdx = 0; curIdx < MAX_HT_MCS_IDX; curIdx++) {
-				if (curIdx == 7) {
-					if (rate_flags & eHAL_TX_RATE_SGI)
-						rateFlag |= 0x2;
-				}
-
-				curRate = supported_mcs_rate[curIdx].supported_rate[rateFlag];
-				if (curRate == maxRate) {
-					found = true;
-					*mcsRateFlag = eHAL_TX_RATE_HT40;
-					break;
-				}
+			/* check for ht40 nss1/2 rate set */
+			match_rate = wma_mcs_rate_match(maxRate, &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]);
+			if (match_rate) {
+				*mcsRateFlag = eHAL_TX_RATE_HT40;
+				goto rate_found;
 			}
 		}
-
-		if (found == false) {
-			rateFlag = 0;
-			for (curIdx = 0; curIdx < MAX_HT_MCS_IDX; curIdx++) {
-				if (curIdx == 7) {
-					if (rate_flags & eHAL_TX_RATE_SGI)
-						rateFlag |= 0x2;
-				}
-
-				curRate = supported_mcs_rate[curIdx].supported_rate[rateFlag];
-				if (curRate == maxRate) {
-					found = true;
-					*mcsRateFlag = eHAL_TX_RATE_HT20;
-					break;
-				}
+		if (rate_flags & eHAL_TX_RATE_HT20) {
+			/* check for ht20 nss1/2 rate set */
+			match_rate = wma_mcs_rate_match(maxRate, &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]);
+			if (match_rate) {
+				*mcsRateFlag = eHAL_TX_RATE_HT20;
+				goto rate_found;
 			}
 		}
 	}
 
-	/*SGI rates are used by firmware only for MCS >= 7 */
-	if (found && (curIdx >= 7))
+rate_found:
+	/* set SGI flag only if this is SGI rate */
+	if (match_rate && is_sgi == true)
 		*mcsRateFlag |= eHAL_TX_RATE_SGI;
 
-	return  found ? curIdx : INVALID_MCS_IDX;
+	WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d",
+		 __func__, match_rate, index, *mcsRateFlag, is_sgi);
+
+	return match_rate ? index : INVALID_MCS_IDX;
 }
 
 /**