]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: iwlwifi: mvm: fix driver-set TX rates on old devices
authorJohannes Berg <johannes.berg@intel.com>
Fri, 15 May 2026 12:14:57 +0000 (15:14 +0300)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Sat, 16 May 2026 20:31:25 +0000 (23:31 +0300)
On old devices such as 7265D, rates are still encoded in version 1
format, which doesn't use the CCK/OFDM rate index (0-3/0-7) but
rather their PLCP value (e.g. 10 for 1 Mbps CCK rate.)

While introducing v3 rates, I changed the driver from internally
handling v1 rates and converting to v2, to internally handling v3
and converting to v1 or v2 according to the firmware. I accordingly
changed the code in iwl_mvm_mac80211_idx_to_hwrate() to no longer
have different values for different APIs. This was correct.

However, I later reverted this part of the change, because it was
reported that I had broken beacon rates, causing a FW assert/crash.
This caused TX_CMD rates to be set incorrectly, potentially causing
a warning when reported back from the device as having been used.

Fix this (hopefully correctly now) by handling beacon rates in the
TX_CMD that's embedded in the beacon template command separately.
Restore iwl_mvm_mac80211_idx_to_hwrate() to return only the rate
index, not PLCP value, fixing the real TX_CMD.

Cc: stable@vger.kernel.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260515151351.7407e293dff7.I4ea1a17f8fe99c933d3f3e30d077cf4246125c3e@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/intel/iwlwifi/mvm/utils.c

index c523c5e82d4ae55f443ee4ed94527753cb2cd5a8..8ffa72aca3cf7b10c5cea06f4c6ed842ad226e00 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
@@ -927,13 +927,18 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
 
 u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
 {
-       u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
        bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10;
+       u16 flags = 0;
 
        if (rate_idx <= IWL_LAST_CCK_RATE)
                flags |= is_new_rate ? IWL_MAC_BEACON_CCK
                          : IWL_MAC_BEACON_CCK_V1;
 
+       if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
+               flags |= iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
+       else
+               flags |= iwl_fw_rate_idx_to_plcp(rate_idx);
+
        return flags;
 }
 
@@ -962,6 +967,7 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct ieee80211_tx_info *info;
+       u32 rate_n_flags = 0;
        u8 rate;
        u32 tx_flags;
 
@@ -981,18 +987,21 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
                         IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) {
                iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
 
-               tx_params->rate_n_flags =
-                       cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
-                                   RATE_MCS_ANT_POS);
+               rate_n_flags |= BIT(mvm->mgmt_last_antenna_idx) <<
+                                       RATE_MCS_ANT_POS;
        }
 
        rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
 
-       tx_params->rate_n_flags |=
-               cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
-       if (rate == IWL_FIRST_CCK_RATE)
-               tx_params->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
+       if (rate < IWL_FIRST_OFDM_RATE)
+               rate_n_flags |= RATE_MCS_MOD_TYPE_CCK;
+       else
+               rate_n_flags |= RATE_MCS_MOD_TYPE_LEGACY_OFDM;
+
+       rate_n_flags |= iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate);
 
+       tx_params->rate_n_flags = iwl_mvm_v3_rate_to_fw(rate_n_flags,
+                                                       mvm->fw_rates_ver);
 }
 
 int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
index 4a33a032c2a77d308f9e2cc51e3ae536f46a2c61..f052537e9567e933fd0a6ed7e16ce6154abf137d 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
@@ -159,15 +159,9 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
 
 u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx)
 {
-       if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
-               /* In the new rate legacy rates are indexed:
-                * 0 - 3 for CCK and 0 - 7 for OFDM.
-                */
-               return (rate_idx >= IWL_FIRST_OFDM_RATE ?
-                       rate_idx - IWL_FIRST_OFDM_RATE :
-                       rate_idx);
-
-       return iwl_fw_rate_idx_to_plcp(rate_idx);
+       return rate_idx >= IWL_FIRST_OFDM_RATE ?
+               rate_idx - IWL_FIRST_OFDM_RATE :
+               rate_idx;
 }
 
 u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac)