]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
iwlwifi: mvm: clear IN_D3 after wowlan status cmd
authorShaul Triebitz <shaul.triebitz@intel.com>
Fri, 22 Jan 2021 12:52:39 +0000 (14:52 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 25 Jan 2021 13:59:19 +0000 (15:59 +0200)
In D3 resume flow, avoid the following race where sending
packets before updating the sequence number (sequence
number received from the wowlan status command response):
Thread 1:
__iwl_mvm_resume clears IWL_MVM_STATUS_IN_D3 and is cut
by thread 2 before reaching iwl_mvm_query_wakeup_reasons.
Thread 2:
iwl_mvm_mac_itxq_xmit calls iwl_mvm_tx_skb since
IWL_MVM_STATUS_IN_D3 is not set using a wrong sequence number.
Thread 1:
__iwl_mvm_resume continues and calls iwl_mvm_query_wakeup_reasons
updating the sequence number received from the firmware.

The next packet that will be sent now will cause sysassert 0x1096.

Fix the bug by moving 'clear IWL_MVM_STATUS_IN_D3' to after
sending the wowlan status command and updating the sequence
number.

Signed-off-by: Shaul Triebitz <shaul.triebitz@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/iwlwifi.20210122144849.fe927ec939c6.I103d3321fb55da7e6c6c51582cfadf94eb8b6c58@changeid
drivers/net/wireless/intel/iwlwifi/mvm/d3.c

index c025188fa9bc5017688f5fe7a097f37cda27dd5d..df018972a46bfa914a8478433130ba7b5c25acf9 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -2032,8 +2032,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
 
        mutex_lock(&mvm->mutex);
 
-       clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
-
        /* get the BSS vif pointer again */
        vif = iwl_mvm_get_bss_vif(mvm);
        if (IS_ERR_OR_NULL(vif))
@@ -2148,6 +2146,8 @@ out_iterate:
                        iwl_mvm_d3_disconnect_iter, keep ? vif : NULL);
 
 out:
+       clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);
+
        /* no need to reset the device in unified images, if successful */
        if (unified_image && !ret) {
                /* nothing else to do if we already sent D0I3_END_CMD */