1 |
From 521f2d87160344647a245ea77dca8e782cbc92da Mon Sep 17 00:00:00 2001 |
2 |
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com> |
3 |
Date: Wed, 13 Jun 2018 11:49:20 +0300 |
4 |
Subject: [PATCH 028/145] iwlwifi: mvm: clear HW_RESTART_REQUESTED when |
5 |
stopping the interface |
6 |
|
7 |
[ Upstream commit 155f7e0441cd121b1e673d465a35e99f4b9b2f0b ] |
8 |
|
9 |
Fix a bug that happens in the following scenario: |
10 |
1) suspend without WoWLAN |
11 |
2) mac80211 calls drv_stop because of the suspend |
12 |
3) __iwl_mvm_mac_stop deallocates the aux station |
13 |
4) during drv_stop the firmware crashes |
14 |
5) iwlmvm: |
15 |
* sets IWL_MVM_STATUS_HW_RESTART_REQUESTED |
16 |
* asks mac80211 to kick the restart flow |
17 |
6) mac80211 puts the restart worker into a freezable |
18 |
queue which means that the worker will not run for now |
19 |
since the workqueue is already frozen |
20 |
7) ... |
21 |
8) resume |
22 |
9) mac80211 runs ieee80211_reconfig as part of the resume |
23 |
10) mac80211 detects that a restart flow has been requested |
24 |
and that we are now resuming from suspend and cancels |
25 |
the restart worker |
26 |
11) mac80211 calls drv_start() |
27 |
12) __iwl_mvm_mac_start checks that IWL_MVM_STATUS_HW_RESTART_REQUESTED |
28 |
clears it, sets IWL_MVM_STATUS_IN_HW_RESTART and calls |
29 |
iwl_mvm_restart_cleanup() |
30 |
13) iwl_fw_error_dump gets called and accesses the device |
31 |
to get debug data |
32 |
14) iwl_mvm_up adds the aux station |
33 |
15) iwl_mvm_add_aux_sta() allocates an internal station for |
34 |
the aux station |
35 |
16) iwl_mvm_allocate_int_sta() tests IWL_MVM_STATUS_IN_HW_RESTART |
36 |
and doesn't really allocate a station ID for the aux |
37 |
station |
38 |
17) a new queue is added for the aux station |
39 |
|
40 |
Note that steps from 5 to 9 aren't really part of the |
41 |
problem but were described for the sake of completeness. |
42 |
|
43 |
Once the iwl_mvm_mac_stop() is called, the device is not |
44 |
accessible, meaning that step 12) can't succeed and we'll |
45 |
see the following: |
46 |
|
47 |
drivers/net/wireless/intel/iwlwifi/pcie/trans.c:2122 iwl_trans_pcie_grab_nic_access+0xc0/0x1d6 [iwlwifi]() |
48 |
Timeout waiting for hardware access (CSR_GP_CNTRL 0x080403d8) |
49 |
Call Trace: |
50 |
[<ffffffffc03e6ad3>] iwl_trans_pcie_grab_nic_access+0xc0/0x1d6 [iwlwifi] |
51 |
[<ffffffffc03e6a13>] iwl_trans_pcie_dump_regs+0x3fd/0x3fd [iwlwifi] |
52 |
[<ffffffffc03dad42>] iwl_fw_error_dump+0x4f5/0xe8b [iwlwifi] |
53 |
[<ffffffffc04bd43e>] __iwl_mvm_mac_start+0x5a/0x21a [iwlmvm] |
54 |
[<ffffffffc04bd6d2>] iwl_mvm_mac_start+0xd4/0x103 [iwlmvm] |
55 |
[<ffffffffc042d378>] drv_start+0xa1/0xc5 [iwl7000_mac80211] |
56 |
[<ffffffffc045a339>] ieee80211_reconfig+0x145/0xf50 [mac80211] |
57 |
[<ffffffffc044788b>] ieee80211_resume+0x62/0x66 [mac80211] |
58 |
[<ffffffffc0366c5b>] wiphy_resume+0xa9/0xc6 [cfg80211] |
59 |
|
60 |
The station id of the aux station is set to 0xff in step 3 |
61 |
and because we don't really allocate a new station id for |
62 |
the auxliary station (as explained in 16), we end up sending |
63 |
a command to the firmware asking to connect the queue |
64 |
to station id 0xff. This makes the firmware crash with the |
65 |
following information: |
66 |
|
67 |
0x00002093 | ADVANCED_SYSASSERT |
68 |
0x000002F0 | trm_hw_status0 |
69 |
0x00000000 | trm_hw_status1 |
70 |
0x00000B38 | branchlink2 |
71 |
0x0001978C | interruptlink1 |
72 |
0x00000000 | interruptlink2 |
73 |
0xFF080501 | data1 |
74 |
0xDEADBEEF | data2 |
75 |
0xDEADBEEF | data3 |
76 |
Firmware error during reconfiguration - reprobe! |
77 |
FW error in SYNC CMD SCD_QUEUE_CFG |
78 |
|
79 |
Fix this by clearing IWL_MVM_STATUS_HW_RESTART_REQUESTED |
80 |
in iwl_mvm_mac_stop(). We won't be able to collect debug |
81 |
data anyway and when we will brought up again, we will |
82 |
have a clean state from the firmware perspective. |
83 |
Since we won't have IWL_MVM_STATUS_IN_HW_RESTART set in |
84 |
step 12) we won't get to the 2093 ASSERT either. |
85 |
|
86 |
Fixes: bf8b286f86fc ("iwlwifi: mvm: defer setting IWL_MVM_STATUS_IN_HW_RESTART") |
87 |
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> |
88 |
Signed-off-by: Luca Coelho <luciano.coelho@intel.com> |
89 |
Signed-off-by: Sasha Levin <sashal@kernel.org> |
90 |
--- |
91 |
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 9 ++++++--- |
92 |
1 file changed, 6 insertions(+), 3 deletions(-) |
93 |
|
94 |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c |
95 |
index b15b0d84bb7e..155cc2ac0120 100644 |
96 |
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c |
97 |
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c |
98 |
@@ -1233,12 +1233,15 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) |
99 |
iwl_mvm_del_aux_sta(mvm); |
100 |
|
101 |
/* |
102 |
- * Clear IN_HW_RESTART flag when stopping the hw (as restart_complete() |
103 |
- * won't be called in this case). |
104 |
+ * Clear IN_HW_RESTART and HW_RESTART_REQUESTED flag when stopping the |
105 |
+ * hw (as restart_complete() won't be called in this case) and mac80211 |
106 |
+ * won't execute the restart. |
107 |
* But make sure to cleanup interfaces that have gone down before/during |
108 |
* HW restart was requested. |
109 |
*/ |
110 |
- if (test_and_clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) |
111 |
+ if (test_and_clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) || |
112 |
+ test_and_clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, |
113 |
+ &mvm->status)) |
114 |
ieee80211_iterate_interfaces(mvm->hw, 0, |
115 |
iwl_mvm_cleanup_iterator, mvm); |
116 |
|
117 |
-- |
118 |
2.19.1 |
119 |
|