3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-12-22 21:12:48 +01:00

band: Add HT RX rate estimation

Similarly to commit
27d302a0 ("band: Add a utility to estimate VHT rx data rate"), this
commit adds an RX data rate estimation utility for HT connections.
This commit is contained in:
Denis Kenzior 2021-06-03 15:35:23 -05:00
parent 2686baae69
commit 575f603f89
2 changed files with 107 additions and 0 deletions

View File

@ -119,6 +119,110 @@ bool band_ofdm_rate(uint8_t index, enum ofdm_channel_width width,
return true; return true;
} }
static bool find_best_mcs_ht(const struct band *band,
const uint8_t *tx_mcs_set,
uint8_t max_mcs, enum ofdm_channel_width width,
int32_t rssi, bool sgi,
uint64_t *out_data_rate)
{
int i;
/*
* TODO: Support MCS values 32 - 76
*
* The MCS values > 31 use an unequal modulation, and the number of
* supported MCS indexes per NSS differs. We do not consider them
* here for now to keep things simple(r).
*/
for (i = max_mcs; i >= 0; i--) {
if (!test_bit(band->ht_mcs_set, i))
continue;
if (!test_bit(tx_mcs_set, i))
continue;
if (band_ofdm_rate(i % 8, width, rssi,
(i / 8) + 1, sgi, out_data_rate))
return true;
}
return false;
}
int band_estimate_ht_rx_rate(const struct band *band,
const uint8_t *htc, const uint8_t *hto,
int32_t rssi, uint64_t *out_data_rate)
{
uint8_t channel_offset;
int max_mcs = 31;
bool sgi;
uint8_t unequal_tx_mcs_set[16];
const uint8_t *tx_mcs_set;
if (!band->ht_supported)
return -ENOTSUP;
if (!htc || !hto)
return -ENOTSUP;
memset(unequal_tx_mcs_set, 0, sizeof(unequal_tx_mcs_set));
tx_mcs_set = htc + 5;
/*
* Check 'Tx MCS Set Defined' at bit 96 and 'Tx MCS Set Unequal' at
* bit 97 of the Supported MCS Set field. Also extract 'Tx Maximum
* Number of Spatial Streams Supported' field at bits 98 and 99.
*
* Note 44 on page 1662 of 802.11-2016 states:
* "How a non-AP STA determines an APs HT MCS transmission support,
* if the Tx MCS Set subfield in the HT Capabilities element
* advertised by the AP is equal to 0 or if he Tx Rx MCS Set Not Equal
* subfield in that element is equal to 1, is implementation dependent.
* The non-AP STA might conservatively use the basic HT-MCS set, or it
* might use knowledge of past transmissions by the AP, or it might
* use other means.
*/
if (test_bit(tx_mcs_set, 96)) {
if (test_bit(tx_mcs_set, 97)) {
uint8_t max_nss = bit_field(tx_mcs_set[12], 2, 2);
max_mcs = max_nss * 4 + 7;
/*
* For purposes of finding the best MCS below, assume
* the AP can send any MCS up to max_nss (i.e 0-7 for
* 1 nss, 0-15 for 2 nss, 0-23 for 3 nss, 0-31 for 4
*/
memset(unequal_tx_mcs_set, 0xff, max_nss + 1);
tx_mcs_set = unequal_tx_mcs_set;
}
} else
max_mcs = 7;
/* Test for 40 Mhz operation */
channel_offset = bit_field(hto[3], 0, 2);
if (test_bit(hto + 3, 2) &&
(channel_offset == 1 || channel_offset == 3)) {
sgi = test_bit(band->ht_capabilities, 6) &&
test_bit(htc + 2, 6);
if (find_best_mcs_ht(band, tx_mcs_set, max_mcs,
OFDM_CHANNEL_WIDTH_40MHZ,
rssi, sgi, out_data_rate))
return 0;
}
sgi = test_bit(band->ht_capabilities, 5) && test_bit(htc + 2, 5);
if (find_best_mcs_ht(band, tx_mcs_set, max_mcs,
OFDM_CHANNEL_WIDTH_20MHZ,
rssi, sgi, out_data_rate))
return 0;
return -EINVAL;
}
static bool find_best_mcs_vht(uint8_t max_index, enum ofdm_channel_width width, static bool find_best_mcs_vht(uint8_t max_index, enum ofdm_channel_width width,
int32_t rssi, uint8_t nss, bool sgi, int32_t rssi, uint8_t nss, bool sgi,
uint64_t *out_data_rate) uint64_t *out_data_rate)

View File

@ -48,3 +48,6 @@ int band_estimate_vht_rx_rate(const struct band *band,
const uint8_t *vhtc, const uint8_t *vhto, const uint8_t *vhtc, const uint8_t *vhto,
const uint8_t *htc, const uint8_t *hto, const uint8_t *htc, const uint8_t *hto,
int32_t rssi, uint64_t *out_data_rate); int32_t rssi, uint64_t *out_data_rate);
int band_estimate_ht_rx_rate(const struct band *band,
const uint8_t *htc, const uint8_t *hto,
int32_t rssi, uint64_t *out_data_rate);