]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: iwlwifi: mvm: ensure offloading TID queue exists
authorBenjamin Berg <benjamin.berg@intel.com>
Sun, 18 Feb 2024 17:51:47 +0000 (19:51 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 28 Mar 2025 20:59:57 +0000 (21:59 +0100)
commit 78f65fbf421a61894c14a1b91fe2fb4437b3fe5f upstream.

The resume code path assumes that the TX queue for the offloading TID
has been configured. At resume time it then tries to sync the write
pointer as it may have been updated by the firmware.

In the unusual event that no packets have been send on TID 0, the queue
will not have been allocated and this causes a crash. Fix this by
ensuring the queue exist at suspend time.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240218194912.6632e6dc7b35.Ie6e6a7488c9c7d4529f13d48f752b5439d8ac3c4@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Jianqi Ren <jianqi.ren.cn@windriver.com>
Signed-off-by: He Zhe <zhe.he@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h

index 592b9157d50c6718ab00d858b4487bbbb41421c5..a82cdd897173f5b1fdbade37fa36f1acb249f61d 100644 (file)
@@ -1293,7 +1293,9 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
 
                mvm->net_detect = true;
        } else {
-               struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
+               struct iwl_wowlan_config_cmd wowlan_config_cmd = {
+                       .offloading_tid = 0,
+               };
 
                wowlan_config_cmd.sta_id = mvmvif->deflink.ap_sta_id;
 
@@ -1305,6 +1307,11 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
                        goto out_noreset;
                }
 
+               ret = iwl_mvm_sta_ensure_queue(
+                       mvm, ap_sta->txq[wowlan_config_cmd.offloading_tid]);
+               if (ret)
+                       goto out_noreset;
+
                ret = iwl_mvm_get_wowlan_config(mvm, wowlan, &wowlan_config_cmd,
                                                vif, mvmvif, ap_sta);
                if (ret)
index 84f4a9576cbda1be13bc8237b57d00740d82452c..662efded3125d1d33cb2966be3bfb99ddc38d1c2 100644 (file)
@@ -1501,6 +1501,34 @@ out_err:
        return ret;
 }
 
+int iwl_mvm_sta_ensure_queue(struct iwl_mvm *mvm,
+                            struct ieee80211_txq *txq)
+{
+       struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
+       int ret = -EINVAL;
+
+       lockdep_assert_held(&mvm->mutex);
+
+       if (likely(test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) ||
+           !txq->sta) {
+               return 0;
+       }
+
+       if (!iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, txq->tid)) {
+               set_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+               ret = 0;
+       }
+
+       local_bh_disable();
+       spin_lock(&mvm->add_stream_lock);
+       if (!list_empty(&mvmtxq->list))
+               list_del_init(&mvmtxq->list);
+       spin_unlock(&mvm->add_stream_lock);
+       local_bh_enable();
+
+       return ret;
+}
+
 void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
 {
        struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm,
index 95ef60daa62f04c85e396c9ab68bdb216374c0df..799ea7675e0137e24aefe8de2b319384634a2e61 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2016 Intel Deutschland GmbH
  */
@@ -577,6 +577,7 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
                                       bool disable);
 
 void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_sta_ensure_queue(struct iwl_mvm *mvm, struct ieee80211_txq *txq);
 void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk);
 int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                         struct iwl_mvm_int_sta *sta, u8 *addr, u32 cipher,