wifi: iwlwifi: mvm: Fix getting the lowest rate
authorIlan Peer <ilan.peer@intel.com>
Wed, 2 Nov 2022 14:59:54 +0000 (16:59 +0200)
committerGregory Greenman <gregory.greenman@intel.com>
Thu, 10 Nov 2022 11:26:56 +0000 (13:26 +0200)
When setting the rate for Tx, the code tried to get the lowest
allowed rate but without considering the BSS basic rates. Fix this
by considering the basic rates.

In addition, declare support for configuring beacon Tx rate and when
configured use the configured Tx beacon rate to set beacon tx command rate.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20221102165239.be8403f0d5c0.I7d141646746b96310efd75fc77ca9aebc61aefcc@changeid
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

index 1e8123140973efa0f258cb05f16f81388c88ecba..1ce9450e5add2372451f7b31917e8fa524cc067e 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -1248,7 +1248,7 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
 
        mvmvif = iwl_mvm_vif_from_mac80211(vif);
        info = IEEE80211_SKB_CB(beacon);
-       rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
+       rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
 
        beacon_cmd.flags =
                cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate));
index de0c545d50fd5935eb0a0e6faca315791b67e2d3..83abfe996138e77710bddba3341150af39c4063a 100644 (file)
@@ -788,14 +788,40 @@ static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
        return ie - beacon;
 }
 
-u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
-                                   struct ieee80211_vif *vif)
+static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
+                                          struct ieee80211_tx_info *info,
+                                          struct ieee80211_vif *vif)
 {
+       struct ieee80211_supported_band *sband;
+       unsigned long basic = vif->bss_conf.basic_rates;
+       u16 lowest_cck = IWL_RATE_COUNT, lowest_ofdm = IWL_RATE_COUNT;
        u8 rate;
-       if (info->band == NL80211_BAND_2GHZ && !vif->p2p)
-               rate = IWL_FIRST_CCK_RATE;
-       else
-               rate = IWL_FIRST_OFDM_RATE;
+       u32 i;
+
+       sband = mvm->hw->wiphy->bands[info->band];
+       for_each_set_bit(i, &basic, BITS_PER_LONG) {
+               u16 hw = sband->bitrates[i].hw_value;
+
+               if (hw >= IWL_FIRST_OFDM_RATE) {
+                       if (lowest_ofdm > hw)
+                               lowest_ofdm = hw;
+               } else if (lowest_cck > hw) {
+                       lowest_cck = hw;
+               }
+       }
+
+       if (info->band == NL80211_BAND_2GHZ && !vif->p2p) {
+               if (lowest_cck != IWL_RATE_COUNT)
+                       rate = lowest_cck;
+               else if (lowest_ofdm != IWL_RATE_COUNT)
+                       rate = lowest_ofdm;
+               else
+                       rate = IWL_RATE_1M_INDEX;
+       } else if (lowest_ofdm != IWL_RATE_COUNT) {
+               rate = lowest_ofdm;
+       } else {
+               rate = IWL_RATE_6M_INDEX;
+       }
 
        return rate;
 }
@@ -812,6 +838,24 @@ u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
        return flags;
 }
 
+u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm,
+                                   struct ieee80211_tx_info *info,
+                                   struct ieee80211_vif *vif)
+{
+       struct ieee80211_supported_band *sband =
+               mvm->hw->wiphy->bands[info->band];
+       u32 legacy = vif->bss_conf.beacon_tx_rate.control[info->band].legacy;
+
+       /* if beacon rate was configured try using it */
+       if (hweight32(legacy) == 1) {
+               u32 rate = ffs(legacy) - 1;
+
+               return sband->bitrates[rate].hw_value;
+       }
+
+       return iwl_mvm_mac_ctxt_get_lowest_rate(mvm, info, vif);
+}
+
 static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
                                    struct ieee80211_vif *vif,
                                    struct sk_buff *beacon,
@@ -842,7 +886,7 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
                cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
                            RATE_MCS_ANT_POS);
 
-       rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
+       rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
 
        tx->rate_n_flags |=
                cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
@@ -926,7 +970,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(beacon);
        struct iwl_mac_beacon_cmd beacon_cmd = {};
-       u8 rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
+       u8 rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
        u16 flags;
        struct ieee80211_chanctx_conf *ctx;
        int channel;
index e923e9a75c927c8771a95edf80bd3b8190a08e2d..a81dd488caa84755a99083add29970993e7aee2a 100644 (file)
@@ -374,6 +374,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                hw->wiphy->n_cipher_suites++;
        }
 
+       wiphy_ext_feature_set(hw->wiphy,
+                             NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
+
        if (fw_has_capa(&mvm->fw->ucode_capa,
                        IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) {
                wiphy_ext_feature_set(hw->wiphy,
index 19d7a4f4ccdcd615b1284a66cf719972927c1be7..962e304fc2b1622ae51b0741befec14ed4d09361 100644 (file)
@@ -1644,7 +1644,8 @@ int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
 int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
                                     struct sk_buff *beacon,
                                     void *data, int len);
-u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
+u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm,
+                                   struct ieee80211_tx_info *info,
                                    struct ieee80211_vif *vif);
 u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw,
                                      u8 rate_idx);