summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorMiaoqing Pan <miaoqing@codeaurora.org>2019-05-29 04:13:28 -0400
committerKalle Valo <kvalo@codeaurora.org>2019-06-25 09:01:38 -0400
commit8b97b055dc9db09b48d5a9a37d847900dd00d3cc (patch)
tree0964fa3c094e8631861d74983b246ecbeb9f358f /drivers/net/wireless
parent265df32eae5845212ad9f55f5ae6b6dcb68b187b (diff)
ath10k: fix failure to set multiple fixed rate
Currently, below fixed rate commands are broken, iw wlanx set bitrates legacy-<2.4|5> ht-mcs-<2.4|5> vht-mcs-<2.4|5> \ <NSS:MCSx> iw wlanx set bitrates legacy-<2.4|5> <legacy rate> ht-mcs-<2.4|5> \ vht-mcs-<2.4|5> <NSS:MCSx> There are two methods to set fixed rate, both failed, - Use vdev fixed rate command This command only support one single rate, but it's broken due to mac80211 change commit e8e4f5280ddd ("mac80211: reject/clear user rate mask if not usable"), which requires user to specify at least one legacy rate. So we can't use this command to set ht/vht single rate any more. - Use peer_assoc command This command can update rx capability for multiple rates, it will work fine for ht mcs rates, as each supported mcs can be advertised in ht_mcs index mask. But this will not work with vht rates because, as per the vht mcs capability advertisement, there are only two bits to indicate the supported mcs. E.g. only support 0-7, 0-8, 0-9. So introduced new WMI command: WMI_PEER_PARAM_FIXED_RATE. After peer assoc, the peer fixed rate cmd will work for that specific peer. Remaining peers will use auto rate. If both vdev fixed rate and peer fixed rates are given, peer fixed rate will take effect to peers for which this cmd is given. Remaining peers in that vdev, will use vdev fixed rate. Tested HW: QCA9984 Tested FW: 10.4-3.9.0.2-00035 Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h7
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c111
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h1
4 files changed, 108 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 43ed6164a132..d5cb22e04a1e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -629,6 +629,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
629 [ATH10K_FW_FEATURE_MGMT_TX_BY_REF] = "mgmt-tx-by-reference", 629 [ATH10K_FW_FEATURE_MGMT_TX_BY_REF] = "mgmt-tx-by-reference",
630 [ATH10K_FW_FEATURE_NON_BMI] = "non-bmi", 630 [ATH10K_FW_FEATURE_NON_BMI] = "non-bmi",
631 [ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL] = "single-chan-info-per-channel", 631 [ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL] = "single-chan-info-per-channel",
632 [ATH10K_FW_FEATURE_PEER_FIXED_RATE] = "peer-fixed-rate",
632}; 633};
633 634
634static unsigned int ath10k_core_get_fw_feature_str(char *buf, 635static unsigned int ath10k_core_get_fw_feature_str(char *buf,
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 2d109c030ec4..fe6e88d2bdf9 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -579,6 +579,10 @@ struct ath10k_vif {
579 struct work_struct ap_csa_work; 579 struct work_struct ap_csa_work;
580 struct delayed_work connection_loss_work; 580 struct delayed_work connection_loss_work;
581 struct cfg80211_bitrate_mask bitrate_mask; 581 struct cfg80211_bitrate_mask bitrate_mask;
582
583 /* For setting VHT peer fixed rate, protected by conf_mutex */
584 int vht_num_rates;
585 u8 vht_pfr;
582}; 586};
583 587
584struct ath10k_vif_iter { 588struct ath10k_vif_iter {
@@ -770,6 +774,9 @@ enum ath10k_fw_features {
770 /* Firmware sends only one chan_info event per channel */ 774 /* Firmware sends only one chan_info event per channel */
771 ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL = 20, 775 ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL = 20,
772 776
777 /* Firmware allows setting peer fixed rate */
778 ATH10K_FW_FEATURE_PEER_FIXED_RATE = 21,
779
773 /* keep last */ 780 /* keep last */
774 ATH10K_FW_FEATURE_COUNT, 781 ATH10K_FW_FEATURE_COUNT,
775}; 782};
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 40e7cea02f94..c4e7adf3ae45 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -7107,18 +7107,23 @@ exit:
7107static bool 7107static bool
7108ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar, 7108ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
7109 enum nl80211_band band, 7109 enum nl80211_band band,
7110 const struct cfg80211_bitrate_mask *mask) 7110 const struct cfg80211_bitrate_mask *mask,
7111 int *vht_num_rates)
7111{ 7112{
7112 int num_rates = 0; 7113 int num_rates = 0;
7113 int i; 7114 int i, tmp;
7114 7115
7115 num_rates += hweight32(mask->control[band].legacy); 7116 num_rates += hweight32(mask->control[band].legacy);
7116 7117
7117 for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) 7118 for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
7118 num_rates += hweight8(mask->control[band].ht_mcs[i]); 7119 num_rates += hweight8(mask->control[band].ht_mcs[i]);
7119 7120
7120 for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) 7121 *vht_num_rates = 0;
7121 num_rates += hweight16(mask->control[band].vht_mcs[i]); 7122 for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
7123 tmp = hweight16(mask->control[band].vht_mcs[i]);
7124 num_rates += tmp;
7125 *vht_num_rates += tmp;
7126 }
7122 7127
7123 return num_rates == 1; 7128 return num_rates == 1;
7124} 7129}
@@ -7176,7 +7181,7 @@ static int
7176ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar, 7181ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
7177 enum nl80211_band band, 7182 enum nl80211_band band,
7178 const struct cfg80211_bitrate_mask *mask, 7183 const struct cfg80211_bitrate_mask *mask,
7179 u8 *rate, u8 *nss) 7184 u8 *rate, u8 *nss, bool vht_only)
7180{ 7185{
7181 int rate_idx; 7186 int rate_idx;
7182 int i; 7187 int i;
@@ -7184,6 +7189,9 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
7184 u8 preamble; 7189 u8 preamble;
7185 u8 hw_rate; 7190 u8 hw_rate;
7186 7191
7192 if (vht_only)
7193 goto next;
7194
7187 if (hweight32(mask->control[band].legacy) == 1) { 7195 if (hweight32(mask->control[band].legacy) == 1) {
7188 rate_idx = ffs(mask->control[band].legacy) - 1; 7196 rate_idx = ffs(mask->control[band].legacy) - 1;
7189 7197
@@ -7217,6 +7225,7 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
7217 } 7225 }
7218 } 7226 }
7219 7227
7228next:
7220 for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) { 7229 for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
7221 if (hweight16(mask->control[band].vht_mcs[i]) == 1) { 7230 if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
7222 *nss = i + 1; 7231 *nss = i + 1;
@@ -7278,7 +7287,8 @@ static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif,
7278static bool 7287static bool
7279ath10k_mac_can_set_bitrate_mask(struct ath10k *ar, 7288ath10k_mac_can_set_bitrate_mask(struct ath10k *ar,
7280 enum nl80211_band band, 7289 enum nl80211_band band,
7281 const struct cfg80211_bitrate_mask *mask) 7290 const struct cfg80211_bitrate_mask *mask,
7291 bool allow_pfr)
7282{ 7292{
7283 int i; 7293 int i;
7284 u16 vht_mcs; 7294 u16 vht_mcs;
@@ -7297,7 +7307,8 @@ ath10k_mac_can_set_bitrate_mask(struct ath10k *ar,
7297 case BIT(10) - 1: 7307 case BIT(10) - 1:
7298 break; 7308 break;
7299 default: 7309 default:
7300 ath10k_warn(ar, "refusing bitrate mask with missing 0-7 VHT MCS rates\n"); 7310 if (!allow_pfr)
7311 ath10k_warn(ar, "refusing bitrate mask with missing 0-7 VHT MCS rates\n");
7301 return false; 7312 return false;
7302 } 7313 }
7303 } 7314 }
@@ -7305,6 +7316,26 @@ ath10k_mac_can_set_bitrate_mask(struct ath10k *ar,
7305 return true; 7316 return true;
7306} 7317}
7307 7318
7319static bool ath10k_mac_set_vht_bitrate_mask_fixup(struct ath10k *ar,
7320 struct ath10k_vif *arvif,
7321 struct ieee80211_sta *sta)
7322{
7323 int err;
7324 u8 rate = arvif->vht_pfr;
7325
7326 /* skip non vht and multiple rate peers */
7327 if (!sta->vht_cap.vht_supported || arvif->vht_num_rates != 1)
7328 return false;
7329
7330 err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
7331 WMI_PEER_PARAM_FIXED_RATE, rate);
7332 if (err)
7333 ath10k_warn(ar, "failed to eanble STA %pM peer fixed rate: %d\n",
7334 sta->addr, err);
7335
7336 return true;
7337}
7338
7308static void ath10k_mac_set_bitrate_mask_iter(void *data, 7339static void ath10k_mac_set_bitrate_mask_iter(void *data,
7309 struct ieee80211_sta *sta) 7340 struct ieee80211_sta *sta)
7310{ 7341{
@@ -7315,6 +7346,9 @@ static void ath10k_mac_set_bitrate_mask_iter(void *data,
7315 if (arsta->arvif != arvif) 7346 if (arsta->arvif != arvif)
7316 return; 7347 return;
7317 7348
7349 if (ath10k_mac_set_vht_bitrate_mask_fixup(ar, arvif, sta))
7350 return;
7351
7318 spin_lock_bh(&ar->data_lock); 7352 spin_lock_bh(&ar->data_lock);
7319 arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED; 7353 arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
7320 spin_unlock_bh(&ar->data_lock); 7354 spin_unlock_bh(&ar->data_lock);
@@ -7322,6 +7356,26 @@ static void ath10k_mac_set_bitrate_mask_iter(void *data,
7322 ieee80211_queue_work(ar->hw, &arsta->update_wk); 7356 ieee80211_queue_work(ar->hw, &arsta->update_wk);
7323} 7357}
7324 7358
7359static void ath10k_mac_clr_bitrate_mask_iter(void *data,
7360 struct ieee80211_sta *sta)
7361{
7362 struct ath10k_vif *arvif = data;
7363 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
7364 struct ath10k *ar = arvif->ar;
7365 int err;
7366
7367 /* clear vht peers only */
7368 if (arsta->arvif != arvif || !sta->vht_cap.vht_supported)
7369 return;
7370
7371 err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
7372 WMI_PEER_PARAM_FIXED_RATE,
7373 WMI_FIXED_RATE_NONE);
7374 if (err)
7375 ath10k_warn(ar, "failed to clear STA %pM peer fixed rate: %d\n",
7376 sta->addr, err);
7377}
7378
7325static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, 7379static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
7326 struct ieee80211_vif *vif, 7380 struct ieee80211_vif *vif,
7327 const struct cfg80211_bitrate_mask *mask) 7381 const struct cfg80211_bitrate_mask *mask)
@@ -7338,6 +7392,9 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
7338 u8 ldpc; 7392 u8 ldpc;
7339 int single_nss; 7393 int single_nss;
7340 int ret; 7394 int ret;
7395 int vht_num_rates, allow_pfr;
7396 u8 vht_pfr;
7397 bool update_bitrate_mask = true;
7341 7398
7342 if (ath10k_mac_vif_chan(vif, &def)) 7399 if (ath10k_mac_vif_chan(vif, &def))
7343 return -EPERM; 7400 return -EPERM;
@@ -7351,9 +7408,21 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
7351 if (sgi == NL80211_TXRATE_FORCE_LGI) 7408 if (sgi == NL80211_TXRATE_FORCE_LGI)
7352 return -EINVAL; 7409 return -EINVAL;
7353 7410
7354 if (ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask)) { 7411 allow_pfr = test_bit(ATH10K_FW_FEATURE_PEER_FIXED_RATE,
7412 ar->normal_mode_fw.fw_file.fw_features);
7413 if (allow_pfr) {
7414 mutex_lock(&ar->conf_mutex);
7415 ieee80211_iterate_stations_atomic(ar->hw,
7416 ath10k_mac_clr_bitrate_mask_iter,
7417 arvif);
7418 mutex_unlock(&ar->conf_mutex);
7419 }
7420
7421 if (ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask,
7422 &vht_num_rates)) {
7355 ret = ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask, 7423 ret = ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask,
7356 &rate, &nss); 7424 &rate, &nss,
7425 false);
7357 if (ret) { 7426 if (ret) {
7358 ath10k_warn(ar, "failed to get single rate for vdev %i: %d\n", 7427 ath10k_warn(ar, "failed to get single rate for vdev %i: %d\n",
7359 arvif->vdev_id, ret); 7428 arvif->vdev_id, ret);
@@ -7369,12 +7438,30 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
7369 max(ath10k_mac_max_ht_nss(ht_mcs_mask), 7438 max(ath10k_mac_max_ht_nss(ht_mcs_mask),
7370 ath10k_mac_max_vht_nss(vht_mcs_mask))); 7439 ath10k_mac_max_vht_nss(vht_mcs_mask)));
7371 7440
7372 if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask)) 7441 if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask,
7373 return -EINVAL; 7442 allow_pfr)) {
7443 u8 vht_nss;
7444
7445 if (!allow_pfr || vht_num_rates != 1)
7446 return -EINVAL;
7447
7448 /* Reach here, firmware supports peer fixed rate and has
7449 * single vht rate, and don't update vif birate_mask, as
7450 * the rate only for specific peer.
7451 */
7452 ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask,
7453 &vht_pfr,
7454 &vht_nss,
7455 true);
7456 update_bitrate_mask = false;
7457 }
7374 7458
7375 mutex_lock(&ar->conf_mutex); 7459 mutex_lock(&ar->conf_mutex);
7376 7460
7377 arvif->bitrate_mask = *mask; 7461 if (update_bitrate_mask)
7462 arvif->bitrate_mask = *mask;
7463 arvif->vht_num_rates = vht_num_rates;
7464 arvif->vht_pfr = vht_pfr;
7378 ieee80211_iterate_stations_atomic(ar->hw, 7465 ieee80211_iterate_stations_atomic(ar->hw,
7379 ath10k_mac_set_bitrate_mask_iter, 7466 ath10k_mac_set_bitrate_mask_iter,
7380 arvif); 7467 arvif);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 12f57f9adbba..bd54da64cd02 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6260,6 +6260,7 @@ enum wmi_peer_param {
6260 WMI_PEER_CHAN_WIDTH = 0x4, 6260 WMI_PEER_CHAN_WIDTH = 0x4,
6261 WMI_PEER_NSS = 0x5, 6261 WMI_PEER_NSS = 0x5,
6262 WMI_PEER_USE_4ADDR = 0x6, 6262 WMI_PEER_USE_4ADDR = 0x6,
6263 WMI_PEER_PARAM_FIXED_RATE = 0x9,
6263 WMI_PEER_DEBUG = 0xa, 6264 WMI_PEER_DEBUG = 0xa,
6264 WMI_PEER_PHYMODE = 0xd, 6265 WMI_PEER_PHYMODE = 0xd,
6265 WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */ 6266 WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */