]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: mvm: fix add stream vs. restart race
authorJohannes Berg <johannes.berg@intel.com>
Sat, 28 Dec 2024 20:34:18 +0000 (22:34 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 13 Jan 2025 14:26:41 +0000 (15:26 +0100)
My recent restart related work has made this race more likely
to happen and we've now noticed it, but it seems that it was
always possible. The race is that the add stream work can be
scheduled just before a restart is scheduled and then execute
before the restart, accessing the device while it's doing the
restart and not accessible.

To fix this, check if the device is restarting and abort the
work in that case. Reschedule it after the restart as well.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20241228223206.9c30af039b4d.I1a32936776f8ba5e83dda0a68ffc2722d9d37950@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c

index 3e0f34dc6e1a87d07256f4a1fdf98fb7c3d65fdf..a5b4f1b843c03a4241699154c184c4ab00d12f0a 100644 (file)
@@ -1341,6 +1341,10 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
 
        IWL_INFO(mvm, "restart completed\n");
        iwl_trans_finish_sw_reset(mvm->trans);
+
+       /* no need to lock, adding in parallel would schedule too */
+       if (!list_empty(&mvm->add_stream_txqs))
+               schedule_work(&mvm->add_stream_wk);
 }
 
 void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
index 9d9d385f67ac881c28e0c23371638452eea12aac..735a66269f88655e804f3d0ba973ab7d071d6844 100644 (file)
@@ -1520,7 +1520,12 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
        struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm,
                                           add_stream_wk);
 
-       mutex_lock(&mvm->mutex);
+       guard(mvm)(mvm);
+
+       /* will reschedule to run after restart */
+       if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) ||
+           test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+               return;
 
        iwl_mvm_inactivity_check(mvm, IWL_INVALID_STA);
 
@@ -1564,8 +1569,6 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
                iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
                local_bh_enable();
        }
-
-       mutex_unlock(&mvm->mutex);
 }
 
 static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,