diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 1f6030c81859..8f50005d8a96 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/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; diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index d204979b4e0c..0fd93a395ec5 100644 --- a/core/wma/inc/wma_internal.h +++ b/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 diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index cb1cc1ef84c3..bb027532b8d7 100644 --- a/core/wma/src/wma_utils.c +++ b/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 ((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))) { - 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 ((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; } /**