wifi: iwlwifi: mld: properly handle async notification in op mode start
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 23 Apr 2025 06:16:37 +0000 (09:16 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 23 Apr 2025 13:37:40 +0000 (15:37 +0200)
From the moment that we have ALIVE, we can receive notification that
are handled asynchronously.

Some notifications (for example iwl_rfi_support_notif) requires an
operational FW. So we need to make sure that they were handled in
iwl_op_mode_mld_start before we stop the FW. Flush the async_handlers_wk
there to achieve that.

Also, if loading the FW in op mode start failed, we need to cancel
these notifications, as they are from a dead FW.

More than that, not doing so can cause us to access freed memory
if async_handlers_wk is executed after ieee80211_free_hw is called.

Fix this by canceling all async notifications if a failure occurred in
init (after ALIVE).

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20250423091408.a8f63d983466.Ifd77d9c1a29fdd278b0a7bfc2709dd5d5e5efdb1@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mld/d3.c
drivers/net/wireless/intel/iwlwifi/mld/fw.c
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
drivers/net/wireless/intel/iwlwifi/mld/mld.c
drivers/net/wireless/intel/iwlwifi/mld/mld.h

index 2c6e8ec..21b20e0 100644 (file)
@@ -1344,6 +1344,8 @@ int iwl_mld_no_wowlan_suspend(struct iwl_mld *mld)
        if (ret) {
                IWL_ERR(mld, "d3 suspend: trans_d3_suspend failed %d\n", ret);
        } else {
+               /* Async notification might send hcmds, which is not allowed in suspend */
+               iwl_mld_cancel_async_notifications(mld);
                mld->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
                mld->fw_status.in_d3 = true;
        }
index 76bf835..14aacfb 100644 (file)
@@ -341,6 +341,11 @@ void iwl_mld_stop_fw(struct iwl_mld *mld)
 
        iwl_trans_stop_device(mld->trans);
 
+       /* HW is stopped, no more coming RX. Cancel all notifications in
+        * case they were sent just before stopping the HW.
+        */
+       iwl_mld_cancel_async_notifications(mld);
+
        mld->fw_status.running = false;
 }
 
index a7bddf7..03ef9b3 100644 (file)
@@ -541,11 +541,6 @@ void iwl_mld_mac80211_stop(struct ieee80211_hw *hw, bool suspend)
            (IS_ENABLED(CONFIG_PM_SLEEP) && iwl_mld_no_wowlan_suspend(mld)))
                iwl_mld_stop_fw(mld);
 
-       /* HW is stopped, no more coming RX. Cancel all notifications in
-        * case they were sent just before stopping the HW.
-        */
-       iwl_mld_cancel_async_notifications(mld);
-
        /* Clear in_hw_restart flag when stopping the hw, as mac80211 won't
         * execute the restart.
         */
index 2f5b6dc..562d320 100644 (file)
@@ -428,6 +428,11 @@ iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
                goto free_hw;
        }
 
+       /* We are about to stop the FW. Notifications may require an
+        * operational FW, so handle them all here before we stop.
+        */
+       wiphy_work_flush(mld->wiphy, &mld->async_handlers_wk);
+
        iwl_mld_stop_fw(mld);
 
        wiphy_unlock(mld->wiphy);
index c436eb4..a4a16da 100644 (file)
@@ -298,11 +298,6 @@ iwl_cleanup_mld(struct iwl_mld *mld)
 #endif
 
        iwl_mld_low_latency_restart_cleanup(mld);
-
-       /* Cancel the async notification handlers so we won't process
-        * notifications from the dead fw after the reconfig flow.
-        */
-       iwl_mld_cancel_async_notifications(mld);
 }
 
 enum iwl_power_scheme {