mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 18:01:23 +00:00
270 lines
9.5 KiB
Diff
270 lines
9.5 KiB
Diff
From ddf4f23a95dd44931d695eb615c6b4e3869a0a56 Mon Sep 17 00:00:00 2001
|
|
From: Venkateswara Naralasetty <vnaralas@codeaurora.org>
|
|
Date: Fri, 9 Oct 2020 15:15:46 +0530
|
|
Subject: [PATCH] ath11k: allow multiple single rates from fixed rate settings
|
|
|
|
Ath11k driver allows user to set either range of rates like
|
|
1:0-9 2:0-9 3:0-9 4:0-9 or single fixed rate like 1:9 from
|
|
set bitrates command.
|
|
This change allows user to set multiple vht/he single rates
|
|
from set bitrates command like 1:9 2:9 3:9 4:9. And rate will
|
|
be applied based on the best nss supported by the peer using
|
|
peer fixed rate command.
|
|
|
|
Signed-off-by: Venkateswara Naralasetty <vnaralas@codeaurora.org>
|
|
---
|
|
drivers/net/wireless/ath/ath11k/mac.c | 130 ++++++++++++++++++++++------------
|
|
1 file changed, 84 insertions(+), 46 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -3581,6 +3581,28 @@ exit:
|
|
}
|
|
|
|
static int
|
|
+ath11k_mac_bitrate_num_vht_single_rates(struct ath11k *ar,
|
|
+ enum nl80211_band band,
|
|
+ const struct cfg80211_bitrate_mask *mask,
|
|
+ struct ieee80211_sta *sta)
|
|
+{
|
|
+ int num_single_rates = 0;
|
|
+ int i;
|
|
+ int rates;
|
|
+ int nss;
|
|
+
|
|
+ nss = sta ? sta->rx_nss : ARRAY_SIZE(mask->control[band].vht_mcs);
|
|
+
|
|
+ for (i = 0; i < nss; i++) {
|
|
+ rates = hweight16(mask->control[band].vht_mcs[i]);
|
|
+ if (rates == 1)
|
|
+ num_single_rates++;
|
|
+ }
|
|
+
|
|
+ return num_single_rates;
|
|
+}
|
|
+
|
|
+static int
|
|
ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar,
|
|
enum nl80211_band band,
|
|
const struct cfg80211_bitrate_mask *mask)
|
|
@@ -3595,6 +3617,28 @@ ath11k_mac_bitrate_mask_num_vht_rates(st
|
|
}
|
|
|
|
static int
|
|
+ath11k_mac_bitrate_num_he_single_rates(struct ath11k *ar,
|
|
+ enum nl80211_band band,
|
|
+ const struct cfg80211_bitrate_mask *mask,
|
|
+ struct ieee80211_sta *sta)
|
|
+{
|
|
+ int num_single_rates = 0;
|
|
+ int i;
|
|
+ int rates;
|
|
+ int nss;
|
|
+
|
|
+ nss = sta ? sta->rx_nss : ARRAY_SIZE(mask->control[band].he_mcs);
|
|
+
|
|
+ for (i = 0; i < nss; i++) {
|
|
+ rates = hweight16(mask->control[band].he_mcs[i]);
|
|
+ if (rates == 1)
|
|
+ num_single_rates++;
|
|
+ }
|
|
+
|
|
+ return num_single_rates;
|
|
+}
|
|
+
|
|
+static int
|
|
ath11k_mac_bitrate_mask_num_he_rates(struct ath11k *ar,
|
|
enum nl80211_band band,
|
|
const struct cfg80211_bitrate_mask *mask)
|
|
@@ -3623,7 +3667,7 @@ ath11k_mac_set_peer_vht_fixed_rate(struc
|
|
|
|
nss = 0;
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
|
|
+ for (i = 0; i < sta->rx_nss; i++) {
|
|
if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
|
|
nss = i + 1;
|
|
vht_rate = ffs(mask->control[band].vht_mcs[i]) - 1;
|
|
@@ -3636,10 +3680,6 @@ ath11k_mac_set_peer_vht_fixed_rate(struc
|
|
return -EINVAL;
|
|
}
|
|
|
|
- /* Avoid updating invalid nss as fixed rate*/
|
|
- if (nss > sta->rx_nss)
|
|
- return -EINVAL;
|
|
-
|
|
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
|
"Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates",
|
|
sta->addr);
|
|
@@ -3673,7 +3713,7 @@ ath11k_mac_set_peer_he_fixed_rate(struct
|
|
|
|
nss = 0;
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(mask->control[band].he_mcs); i++) {
|
|
+ for (i = 0; i < sta->rx_nss; i++) {
|
|
if (hweight16(mask->control[band].he_mcs[i]) == 1) {
|
|
nss = i + 1;
|
|
he_rate = ffs(mask->control[band].he_mcs[i]) - 1;
|
|
@@ -3686,11 +3726,6 @@ ath11k_mac_set_peer_he_fixed_rate(struct
|
|
return -EINVAL;
|
|
}
|
|
|
|
- /* Avoid updating invalid nss as fixed rate*/
|
|
- if (nss > sta->rx_nss)
|
|
- return -EINVAL;
|
|
-
|
|
-
|
|
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
|
"Setting Fixed HE Rate for peer %pM. Device will not switch to any other selected rates",
|
|
sta->addr);
|
|
@@ -3720,7 +3755,7 @@ static int ath11k_station_assoc(struct a
|
|
struct cfg80211_chan_def def;
|
|
enum nl80211_band band;
|
|
struct cfg80211_bitrate_mask *mask;
|
|
- u8 num_vht_rates, num_he_rates;
|
|
+ u8 num_vht_single_rates, num_he_single_rates;
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
@@ -3745,22 +3780,23 @@ static int ath11k_station_assoc(struct a
|
|
return -ETIMEDOUT;
|
|
}
|
|
|
|
- num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
|
|
- num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask);
|
|
+ num_vht_single_rates = ath11k_mac_bitrate_num_vht_single_rates(ar, band,
|
|
+ mask, sta);
|
|
+ num_he_single_rates = ath11k_mac_bitrate_num_he_single_rates(ar, band,
|
|
+ mask, sta);
|
|
|
|
/* If single VHT/HE rate is configured (by set_bitrate_mask()),
|
|
* peer_assoc will disable VHT/HE. This is now enabled by a peer specific
|
|
- * fixed param.
|
|
+ * fixed param. If multiple single VHT/HE rates like(1:9 2:9 3:9 4:9)
|
|
+ * are configured, apply rate with the best nss supported by the peer.
|
|
* Note that all other rates and NSS will be disabled for this peer.
|
|
*/
|
|
- if (sta->vht_cap.vht_supported && num_vht_rates == 1) {
|
|
- ret = ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
|
|
- band);
|
|
+ if (sta->vht_cap.vht_supported && num_vht_single_rates >= 1) {
|
|
+ ret = ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask, band);
|
|
if (ret)
|
|
return ret;
|
|
- } else if (sta->he_cap.has_he && num_he_rates == 1) {
|
|
- ret = ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
|
|
- band);
|
|
+ } else if (sta->he_cap.has_he && num_he_single_rates >= 1) {
|
|
+ ret = ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask, band);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
@@ -3835,7 +3871,7 @@ static void ath11k_sta_rc_update_wk(stru
|
|
const u16 *vht_mcs_mask;
|
|
const u16 *he_mcs_mask;
|
|
u32 changed, bw, nss, smps;
|
|
- int err, num_vht_rates, num_he_rates;
|
|
+ int err, num_vht_single_rates, num_he_single_rates;
|
|
const struct cfg80211_bitrate_mask *mask;
|
|
struct peer_assoc_params peer_arg;
|
|
|
|
@@ -3902,26 +3938,27 @@ static void ath11k_sta_rc_update_wk(stru
|
|
|
|
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
|
|
mask = &arvif->bitrate_mask;
|
|
- num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
|
|
- mask);
|
|
- num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
|
|
- mask);
|
|
+ num_vht_single_rates = ath11k_mac_bitrate_num_vht_single_rates(ar, band,
|
|
+ mask, sta);
|
|
+ num_he_single_rates = ath11k_mac_bitrate_num_he_single_rates(ar, band,
|
|
+ mask, sta);
|
|
|
|
/* Peer_assoc_prepare will reject vht rates in
|
|
* bitrate_mask if its not available in range format and
|
|
- * sets vht tx_rateset as unsupported. So multiple VHT MCS
|
|
- * setting(eg. MCS 4,5,6) per peer is not supported here.
|
|
- * But, Single rate in VHT mask can be set as per-peer
|
|
- * fixed rate. But even if any HT rates are configured in
|
|
- * the bitrate mask, device will not switch to those rates
|
|
- * when per-peer Fixed rate is set.
|
|
+ * sets vht tx_rateset as unsupported. If multiple VHT MCS
|
|
+ * and NSS (or) single fixed rate are configured from set_bitrate()
|
|
+ * setting(eg. 1:9 2:9 3:9 4:9) select the best rate based on NSS
|
|
+ * supported by the peer and apply it as peer fixed rate. Also,
|
|
+ * if rate is configured as 1:9 2:0-9 will select 1:9 here.
|
|
+ * But even if any HT rates are configured in the bitrate mask,
|
|
+ * device will not switch to those rates when per-peer Fixed rate is set.
|
|
* TODO: Check RATEMASK_CMDID to support auto rates selection
|
|
* across HT/VHT and for multiple VHT MCS support.
|
|
*/
|
|
- if (sta->vht_cap.vht_supported && num_vht_rates == 1) {
|
|
+ if (sta->vht_cap.vht_supported && num_vht_single_rates >= 1) {
|
|
ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
|
|
band);
|
|
- } else if (sta->he_cap.has_he && num_he_rates == 1) {
|
|
+ } else if (sta->he_cap.has_he && num_he_single_rates >= 1) {
|
|
ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
|
|
band);
|
|
} else {
|
|
@@ -7138,7 +7175,7 @@ ath11k_mac_op_set_bitrate_mask(struct ie
|
|
u8 he_gi = 0, he_ltf = 0;
|
|
int single_nss;
|
|
int ret;
|
|
- int num_rates;
|
|
+ int num_single_rates;
|
|
bool he_fixed_rate = false;
|
|
|
|
if (ath11k_mac_vif_chan(vif, &def))
|
|
@@ -7215,37 +7252,38 @@ ath11k_mac_op_set_bitrate_mask(struct ie
|
|
* the VHT rate as fixed rate for vht peers.
|
|
* - Multiple VHT Rates : When Multiple VHT rates are given,this
|
|
* can be set using RATEMASK CMD which uses FW rate-ctl alg.
|
|
+ * - Multiple VHT single Rates: like 1:9 2:9 3:9 4:9 provided in
|
|
+ * set_bitrates(), apply rate based on the best NSS supported by
|
|
+ * the peer through peer fixed rate command.
|
|
* TODO: Setting multiple VHT MCS and replacing peer_assoc with
|
|
* RATEMASK_CMDID can cover all use cases of setting rates
|
|
* across multiple preambles and rates within same type.
|
|
* But requires more validation of the command at this point.
|
|
*/
|
|
|
|
- num_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
|
|
- mask);
|
|
+ num_single_rates = ath11k_mac_bitrate_num_vht_single_rates(ar, band,
|
|
+ mask, NULL);
|
|
|
|
if (!ath11k_mac_vht_mcs_range_present(ar, band, mask) &&
|
|
- num_rates > 1) {
|
|
- /* TODO: Handle multiple VHT MCS values setting using
|
|
- * RATEMASK CMD
|
|
- */
|
|
+ num_single_rates == 0) {
|
|
ath11k_warn(ar->ab,
|
|
"Setting VHT MCS range other than 0-7, 0-8 and 0-9 in bitrate mask not supported\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
- num_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
|
|
- mask);
|
|
- if (num_rates == 1)
|
|
- he_fixed_rate = true;
|
|
+ num_single_rates = ath11k_mac_bitrate_num_he_single_rates(ar, band,
|
|
+ mask, NULL);
|
|
|
|
if (!ath11k_mac_he_mcs_range_present(ar, band, mask) &&
|
|
- num_rates > 1) {
|
|
+ num_single_rates == 0) {
|
|
ath11k_warn(ar->ab,
|
|
"Setting HE MCS range other than 0-7, 0-9 and 0-11 in bitrate mask not supported\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ if (num_single_rates >= 1)
|
|
+ he_fixed_rate = true;
|
|
+
|
|
mutex_lock(&ar->conf_mutex);
|
|
ieee80211_iterate_stations_atomic(ar->hw,
|
|
ath11k_mac_disable_peer_fixed_rate,
|