diff options
author | David S. Miller <davem@davemloft.net> | 2015-04-01 14:27:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-04-01 14:27:28 -0400 |
commit | 45eb5168873c93b4f1c3c3867fea65aad4c6abd6 (patch) | |
tree | 4949e1083f214ce51565d41614df912cba017219 /drivers/net/wireless/iwlwifi/mvm | |
parent | b9600d2d0901cd0f91cb372e72bd53d22f49638d (diff) | |
parent | 9374e7d2fdcad3c36dafc8d3effd554bc702c4b6 (diff) |
Merge tag 'wireless-drivers-next-for-davem-2015-04-01' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says:
====================
Major changes:
ath9k:
* add Active Interference Cancellation, a method implemented in the HW
to counter WLAN RX > sensitivity degradation when BT is transmitting
at the same time. This feature is supported by cards like WB222
based on AR9462.
iwlwifi:
* Location Aware Regulatory was added by Arik
* 8000 device family work
* update to the BT Coex firmware API
brmcfmac:
* add new BCM43455 and BCM43457 SDIO device support
* add new BCM43430 SDIO device support
wil6210:
* take care of AP bridging
* fix NAPI behavior
* found approach to achieve 4*n+2 alignment of Rx frames
rt2x00:
* add new rt2800usb device DWA 130
rtlwifi:
* add USB ID for D-Link DWA-131
* add USB ID ASUS N10 WiFi dongle
mwifiex:
* throughput enhancements
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/coex.c | 220 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/coex_legacy.c | 61 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/d3.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/debugfs.c | 26 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | 47 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api.h | 107 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 180 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 63 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/nvm.c | 290 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/ops.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/power.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/quota.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/rs.c | 96 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/sf.c | 67 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/sta.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/time-event.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/utils.c | 2 |
18 files changed, 853 insertions, 382 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index 877f19bbae7e..13a0a03158de 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
@@ -72,158 +72,6 @@ | |||
72 | #include "mvm.h" | 72 | #include "mvm.h" |
73 | #include "iwl-debug.h" | 73 | #include "iwl-debug.h" |
74 | 74 | ||
75 | const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { | ||
76 | [BT_KILL_MSK_DEFAULT] = 0xfffffc00, | ||
77 | [BT_KILL_MSK_NEVER] = 0xffffffff, | ||
78 | [BT_KILL_MSK_ALWAYS] = 0, | ||
79 | }; | ||
80 | |||
81 | const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { | ||
82 | { | ||
83 | BT_KILL_MSK_ALWAYS, | ||
84 | BT_KILL_MSK_ALWAYS, | ||
85 | BT_KILL_MSK_ALWAYS, | ||
86 | }, | ||
87 | { | ||
88 | BT_KILL_MSK_NEVER, | ||
89 | BT_KILL_MSK_NEVER, | ||
90 | BT_KILL_MSK_NEVER, | ||
91 | }, | ||
92 | { | ||
93 | BT_KILL_MSK_NEVER, | ||
94 | BT_KILL_MSK_NEVER, | ||
95 | BT_KILL_MSK_NEVER, | ||
96 | }, | ||
97 | { | ||
98 | BT_KILL_MSK_DEFAULT, | ||
99 | BT_KILL_MSK_NEVER, | ||
100 | BT_KILL_MSK_DEFAULT, | ||
101 | }, | ||
102 | }; | ||
103 | |||
104 | const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { | ||
105 | { | ||
106 | BT_KILL_MSK_ALWAYS, | ||
107 | BT_KILL_MSK_ALWAYS, | ||
108 | BT_KILL_MSK_ALWAYS, | ||
109 | }, | ||
110 | { | ||
111 | BT_KILL_MSK_ALWAYS, | ||
112 | BT_KILL_MSK_ALWAYS, | ||
113 | BT_KILL_MSK_ALWAYS, | ||
114 | }, | ||
115 | { | ||
116 | BT_KILL_MSK_ALWAYS, | ||
117 | BT_KILL_MSK_ALWAYS, | ||
118 | BT_KILL_MSK_ALWAYS, | ||
119 | }, | ||
120 | { | ||
121 | BT_KILL_MSK_DEFAULT, | ||
122 | BT_KILL_MSK_ALWAYS, | ||
123 | BT_KILL_MSK_DEFAULT, | ||
124 | }, | ||
125 | }; | ||
126 | |||
127 | static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { | ||
128 | cpu_to_le32(0xf0f0f0f0), /* 50% */ | ||
129 | cpu_to_le32(0xc0c0c0c0), /* 25% */ | ||
130 | cpu_to_le32(0xfcfcfcfc), /* 75% */ | ||
131 | cpu_to_le32(0xfefefefe), /* 87.5% */ | ||
132 | }; | ||
133 | |||
134 | static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { | ||
135 | { | ||
136 | cpu_to_le32(0x40000000), | ||
137 | cpu_to_le32(0x00000000), | ||
138 | cpu_to_le32(0x44000000), | ||
139 | cpu_to_le32(0x00000000), | ||
140 | cpu_to_le32(0x40000000), | ||
141 | cpu_to_le32(0x00000000), | ||
142 | cpu_to_le32(0x44000000), | ||
143 | cpu_to_le32(0x00000000), | ||
144 | cpu_to_le32(0xc0004000), | ||
145 | cpu_to_le32(0xf0005000), | ||
146 | cpu_to_le32(0xc0004000), | ||
147 | cpu_to_le32(0xf0005000), | ||
148 | }, | ||
149 | { | ||
150 | cpu_to_le32(0x40000000), | ||
151 | cpu_to_le32(0x00000000), | ||
152 | cpu_to_le32(0x44000000), | ||
153 | cpu_to_le32(0x00000000), | ||
154 | cpu_to_le32(0x40000000), | ||
155 | cpu_to_le32(0x00000000), | ||
156 | cpu_to_le32(0x44000000), | ||
157 | cpu_to_le32(0x00000000), | ||
158 | cpu_to_le32(0xc0004000), | ||
159 | cpu_to_le32(0xf0005000), | ||
160 | cpu_to_le32(0xc0004000), | ||
161 | cpu_to_le32(0xf0005000), | ||
162 | }, | ||
163 | { | ||
164 | cpu_to_le32(0x40000000), | ||
165 | cpu_to_le32(0x00000000), | ||
166 | cpu_to_le32(0x44000000), | ||
167 | cpu_to_le32(0x00000000), | ||
168 | cpu_to_le32(0x40000000), | ||
169 | cpu_to_le32(0x00000000), | ||
170 | cpu_to_le32(0x44000000), | ||
171 | cpu_to_le32(0x00000000), | ||
172 | cpu_to_le32(0xc0004000), | ||
173 | cpu_to_le32(0xf0005000), | ||
174 | cpu_to_le32(0xc0004000), | ||
175 | cpu_to_le32(0xf0005000), | ||
176 | }, | ||
177 | }; | ||
178 | |||
179 | static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { | ||
180 | { | ||
181 | /* Tight */ | ||
182 | cpu_to_le32(0xaaaaaaaa), | ||
183 | cpu_to_le32(0xaaaaaaaa), | ||
184 | cpu_to_le32(0xaeaaaaaa), | ||
185 | cpu_to_le32(0xaaaaaaaa), | ||
186 | cpu_to_le32(0xcc00ff28), | ||
187 | cpu_to_le32(0x0000aaaa), | ||
188 | cpu_to_le32(0xcc00aaaa), | ||
189 | cpu_to_le32(0x0000aaaa), | ||
190 | cpu_to_le32(0xc0004000), | ||
191 | cpu_to_le32(0x00004000), | ||
192 | cpu_to_le32(0xf0005000), | ||
193 | cpu_to_le32(0xf0005000), | ||
194 | }, | ||
195 | { | ||
196 | /* Loose */ | ||
197 | cpu_to_le32(0xaaaaaaaa), | ||
198 | cpu_to_le32(0xaaaaaaaa), | ||
199 | cpu_to_le32(0xaaaaaaaa), | ||
200 | cpu_to_le32(0xaaaaaaaa), | ||
201 | cpu_to_le32(0xcc00ff28), | ||
202 | cpu_to_le32(0x0000aaaa), | ||
203 | cpu_to_le32(0xcc00aaaa), | ||
204 | cpu_to_le32(0x0000aaaa), | ||
205 | cpu_to_le32(0x00000000), | ||
206 | cpu_to_le32(0x00000000), | ||
207 | cpu_to_le32(0xf0005000), | ||
208 | cpu_to_le32(0xf0005000), | ||
209 | }, | ||
210 | { | ||
211 | /* Tx Tx disabled */ | ||
212 | cpu_to_le32(0xaaaaaaaa), | ||
213 | cpu_to_le32(0xaaaaaaaa), | ||
214 | cpu_to_le32(0xeeaaaaaa), | ||
215 | cpu_to_le32(0xaaaaaaaa), | ||
216 | cpu_to_le32(0xcc00ff28), | ||
217 | cpu_to_le32(0x0000aaaa), | ||
218 | cpu_to_le32(0xcc00aaaa), | ||
219 | cpu_to_le32(0x0000aaaa), | ||
220 | cpu_to_le32(0xc0004000), | ||
221 | cpu_to_le32(0xc0004000), | ||
222 | cpu_to_le32(0xf0005000), | ||
223 | cpu_to_le32(0xf0005000), | ||
224 | }, | ||
225 | }; | ||
226 | |||
227 | /* 20MHz / 40MHz below / 40Mhz above*/ | 75 | /* 20MHz / 40MHz below / 40Mhz above*/ |
228 | static const __le64 iwl_ci_mask[][3] = { | 76 | static const __le64 iwl_ci_mask[][3] = { |
229 | /* dummy entry for channel 0 */ | 77 | /* dummy entry for channel 0 */ |
@@ -596,14 +444,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
596 | goto send_cmd; | 444 | goto send_cmd; |
597 | } | 445 | } |
598 | 446 | ||
599 | bt_cmd->max_kill = cpu_to_le32(5); | ||
600 | bt_cmd->bt4_antenna_isolation_thr = | ||
601 | cpu_to_le32(IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS); | ||
602 | bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15); | ||
603 | bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15); | ||
604 | bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT); | ||
605 | bt_cmd->override_secondary_lut = cpu_to_le32(BT_COEX_INVALID_LUT); | ||
606 | |||
607 | mode = iwlwifi_mod_params.bt_coex_active ? BT_COEX_NW : BT_COEX_DISABLE; | 447 | mode = iwlwifi_mod_params.bt_coex_active ? BT_COEX_NW : BT_COEX_DISABLE; |
608 | bt_cmd->mode = cpu_to_le32(mode); | 448 | bt_cmd->mode = cpu_to_le32(mode); |
609 | 449 | ||
@@ -622,18 +462,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
622 | 462 | ||
623 | bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET); | 463 | bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET); |
624 | 464 | ||
625 | if (mvm->cfg->bt_shared_single_ant) | ||
626 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant, | ||
627 | sizeof(iwl_single_shared_ant)); | ||
628 | else | ||
629 | memcpy(&bt_cmd->decision_lut, iwl_combined_lookup, | ||
630 | sizeof(iwl_combined_lookup)); | ||
631 | |||
632 | memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost, | ||
633 | sizeof(iwl_bt_prio_boost)); | ||
634 | bt_cmd->multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0); | ||
635 | bt_cmd->multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1); | ||
636 | |||
637 | send_cmd: | 465 | send_cmd: |
638 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | 466 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); |
639 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); | 467 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); |
@@ -644,48 +472,6 @@ send_cmd: | |||
644 | return ret; | 472 | return ret; |
645 | } | 473 | } |
646 | 474 | ||
647 | static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm) | ||
648 | { | ||
649 | struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; | ||
650 | u32 primary_lut = le32_to_cpu(notif->primary_ch_lut); | ||
651 | u32 secondary_lut = le32_to_cpu(notif->secondary_ch_lut); | ||
652 | u32 ag = le32_to_cpu(notif->bt_activity_grading); | ||
653 | struct iwl_bt_coex_sw_boost_update_cmd cmd = {}; | ||
654 | u8 ack_kill_msk[NUM_PHY_CTX] = {}; | ||
655 | u8 cts_kill_msk[NUM_PHY_CTX] = {}; | ||
656 | int i; | ||
657 | |||
658 | lockdep_assert_held(&mvm->mutex); | ||
659 | |||
660 | ack_kill_msk[0] = iwl_bt_ack_kill_msk[ag][primary_lut]; | ||
661 | cts_kill_msk[0] = iwl_bt_cts_kill_msk[ag][primary_lut]; | ||
662 | |||
663 | ack_kill_msk[1] = iwl_bt_ack_kill_msk[ag][secondary_lut]; | ||
664 | cts_kill_msk[1] = iwl_bt_cts_kill_msk[ag][secondary_lut]; | ||
665 | |||
666 | /* Don't send HCMD if there is no update */ | ||
667 | if (!memcmp(ack_kill_msk, mvm->bt_ack_kill_msk, sizeof(ack_kill_msk)) || | ||
668 | !memcmp(cts_kill_msk, mvm->bt_cts_kill_msk, sizeof(cts_kill_msk))) | ||
669 | return 0; | ||
670 | |||
671 | memcpy(mvm->bt_ack_kill_msk, ack_kill_msk, | ||
672 | sizeof(mvm->bt_ack_kill_msk)); | ||
673 | memcpy(mvm->bt_cts_kill_msk, cts_kill_msk, | ||
674 | sizeof(mvm->bt_cts_kill_msk)); | ||
675 | |||
676 | BUILD_BUG_ON(ARRAY_SIZE(ack_kill_msk) < ARRAY_SIZE(cmd.boost_values)); | ||
677 | |||
678 | for (i = 0; i < ARRAY_SIZE(cmd.boost_values); i++) { | ||
679 | cmd.boost_values[i].kill_ack_msk = | ||
680 | cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk[i]]); | ||
681 | cmd.boost_values[i].kill_cts_msk = | ||
682 | cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk[i]]); | ||
683 | } | ||
684 | |||
685 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0, | ||
686 | sizeof(cmd), &cmd); | ||
687 | } | ||
688 | |||
689 | static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | 475 | static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, |
690 | bool enable) | 476 | bool enable) |
691 | { | 477 | { |
@@ -951,9 +737,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
951 | IWL_ERR(mvm, "Failed to send BT_CI cmd\n"); | 737 | IWL_ERR(mvm, "Failed to send BT_CI cmd\n"); |
952 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); | 738 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); |
953 | } | 739 | } |
954 | |||
955 | if (iwl_mvm_bt_udpate_sw_boost(mvm)) | ||
956 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | ||
957 | } | 740 | } |
958 | 741 | ||
959 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | 742 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, |
@@ -1074,9 +857,6 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1074 | ieee80211_iterate_active_interfaces_atomic( | 857 | ieee80211_iterate_active_interfaces_atomic( |
1075 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 858 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
1076 | iwl_mvm_bt_rssi_iterator, &data); | 859 | iwl_mvm_bt_rssi_iterator, &data); |
1077 | |||
1078 | if (iwl_mvm_bt_udpate_sw_boost(mvm)) | ||
1079 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | ||
1080 | } | 860 | } |
1081 | 861 | ||
1082 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) | 862 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c index 5535ec9766cb..d954591e0be5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c | |||
@@ -288,6 +288,65 @@ static const __le64 iwl_ci_mask[][3] = { | |||
288 | }, | 288 | }, |
289 | }; | 289 | }; |
290 | 290 | ||
291 | enum iwl_bt_kill_msk { | ||
292 | BT_KILL_MSK_DEFAULT, | ||
293 | BT_KILL_MSK_NEVER, | ||
294 | BT_KILL_MSK_ALWAYS, | ||
295 | BT_KILL_MSK_MAX, | ||
296 | }; | ||
297 | |||
298 | static const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { | ||
299 | [BT_KILL_MSK_DEFAULT] = 0xfffffc00, | ||
300 | [BT_KILL_MSK_NEVER] = 0xffffffff, | ||
301 | [BT_KILL_MSK_ALWAYS] = 0, | ||
302 | }; | ||
303 | |||
304 | static const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { | ||
305 | { | ||
306 | BT_KILL_MSK_ALWAYS, | ||
307 | BT_KILL_MSK_ALWAYS, | ||
308 | BT_KILL_MSK_ALWAYS, | ||
309 | }, | ||
310 | { | ||
311 | BT_KILL_MSK_NEVER, | ||
312 | BT_KILL_MSK_NEVER, | ||
313 | BT_KILL_MSK_NEVER, | ||
314 | }, | ||
315 | { | ||
316 | BT_KILL_MSK_NEVER, | ||
317 | BT_KILL_MSK_NEVER, | ||
318 | BT_KILL_MSK_NEVER, | ||
319 | }, | ||
320 | { | ||
321 | BT_KILL_MSK_DEFAULT, | ||
322 | BT_KILL_MSK_NEVER, | ||
323 | BT_KILL_MSK_DEFAULT, | ||
324 | }, | ||
325 | }; | ||
326 | |||
327 | static const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { | ||
328 | { | ||
329 | BT_KILL_MSK_ALWAYS, | ||
330 | BT_KILL_MSK_ALWAYS, | ||
331 | BT_KILL_MSK_ALWAYS, | ||
332 | }, | ||
333 | { | ||
334 | BT_KILL_MSK_ALWAYS, | ||
335 | BT_KILL_MSK_ALWAYS, | ||
336 | BT_KILL_MSK_ALWAYS, | ||
337 | }, | ||
338 | { | ||
339 | BT_KILL_MSK_ALWAYS, | ||
340 | BT_KILL_MSK_ALWAYS, | ||
341 | BT_KILL_MSK_ALWAYS, | ||
342 | }, | ||
343 | { | ||
344 | BT_KILL_MSK_DEFAULT, | ||
345 | BT_KILL_MSK_ALWAYS, | ||
346 | BT_KILL_MSK_DEFAULT, | ||
347 | }, | ||
348 | }; | ||
349 | |||
291 | struct corunning_block_luts { | 350 | struct corunning_block_luts { |
292 | u8 range; | 351 | u8 range; |
293 | __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; | 352 | __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; |
@@ -633,7 +692,7 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) | |||
633 | if (IWL_MVM_BT_COEX_TTC) | 692 | if (IWL_MVM_BT_COEX_TTC) |
634 | bt_cmd->flags |= cpu_to_le32(BT_COEX_TTC); | 693 | bt_cmd->flags |= cpu_to_le32(BT_COEX_TTC); |
635 | 694 | ||
636 | if (IWL_MVM_BT_COEX_RRC) | 695 | if (iwl_mvm_bt_is_rrc_supported(mvm)) |
637 | bt_cmd->flags |= cpu_to_le32(BT_COEX_RRC); | 696 | bt_cmd->flags |= cpu_to_le32(BT_COEX_RRC); |
638 | 697 | ||
639 | if (mvm->cfg->bt_shared_single_ant) | 698 | if (mvm->cfg->bt_shared_single_ant) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 9bdfa95d6ce7..5f8afa5f11a3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -694,6 +694,9 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
694 | if (ret) | 694 | if (ret) |
695 | IWL_ERR(mvm, "Failed to send quota: %d\n", ret); | 695 | IWL_ERR(mvm, "Failed to send quota: %d\n", ret); |
696 | 696 | ||
697 | if (iwl_mvm_is_lar_supported(mvm) && iwl_mvm_init_fw_regd(mvm)) | ||
698 | IWL_ERR(mvm, "Failed to initialize D3 LAR information\n"); | ||
699 | |||
697 | return 0; | 700 | return 0; |
698 | } | 701 | } |
699 | 702 | ||
@@ -1596,7 +1599,7 @@ iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1596 | 1599 | ||
1597 | /* RF-kill already asserted again... */ | 1600 | /* RF-kill already asserted again... */ |
1598 | if (!cmd.resp_pkt) { | 1601 | if (!cmd.resp_pkt) { |
1599 | ret = -ERFKILL; | 1602 | fw_status = ERR_PTR(-ERFKILL); |
1600 | goto out_free_resp; | 1603 | goto out_free_resp; |
1601 | } | 1604 | } |
1602 | 1605 | ||
@@ -1605,7 +1608,7 @@ iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1605 | len = iwl_rx_packet_payload_len(cmd.resp_pkt); | 1608 | len = iwl_rx_packet_payload_len(cmd.resp_pkt); |
1606 | if (len < status_size) { | 1609 | if (len < status_size) { |
1607 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1610 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
1608 | ret = -EIO; | 1611 | fw_status = ERR_PTR(-EIO); |
1609 | goto out_free_resp; | 1612 | goto out_free_resp; |
1610 | } | 1613 | } |
1611 | 1614 | ||
@@ -1613,7 +1616,7 @@ iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1613 | if (len != (status_size + | 1616 | if (len != (status_size + |
1614 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4))) { | 1617 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4))) { |
1615 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1618 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
1616 | ret = -EIO; | 1619 | fw_status = ERR_PTR(-EIO); |
1617 | goto out_free_resp; | 1620 | goto out_free_resp; |
1618 | } | 1621 | } |
1619 | 1622 | ||
@@ -1621,7 +1624,7 @@ iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1621 | 1624 | ||
1622 | out_free_resp: | 1625 | out_free_resp: |
1623 | iwl_free_resp(&cmd); | 1626 | iwl_free_resp(&cmd); |
1624 | return ret ? ERR_PTR(ret) : fw_status; | 1627 | return fw_status; |
1625 | } | 1628 | } |
1626 | 1629 | ||
1627 | /* releases the MVM mutex */ | 1630 | /* releases the MVM mutex */ |
@@ -1874,6 +1877,12 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
1874 | /* query SRAM first in case we want event logging */ | 1877 | /* query SRAM first in case we want event logging */ |
1875 | iwl_mvm_read_d3_sram(mvm); | 1878 | iwl_mvm_read_d3_sram(mvm); |
1876 | 1879 | ||
1880 | /* | ||
1881 | * Query the current location and source from the D3 firmware so we | ||
1882 | * can play it back when we re-intiailize the D0 firmware | ||
1883 | */ | ||
1884 | iwl_mvm_update_changed_regdom(mvm); | ||
1885 | |||
1877 | if (mvm->net_detect) { | 1886 | if (mvm->net_detect) { |
1878 | iwl_mvm_query_netdetect_reasons(mvm, vif); | 1887 | iwl_mvm_query_netdetect_reasons(mvm, vif); |
1879 | /* has unlocked the mutex, so skip that */ | 1888 | /* has unlocked the mutex, so skip that */ |
@@ -1883,9 +1892,9 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
1883 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1892 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1884 | if (keep) | 1893 | if (keep) |
1885 | mvm->keep_vif = vif; | 1894 | mvm->keep_vif = vif; |
1895 | #endif | ||
1886 | /* has unlocked the mutex, so skip that */ | 1896 | /* has unlocked the mutex, so skip that */ |
1887 | goto out_iterate; | 1897 | goto out_iterate; |
1888 | #endif | ||
1889 | } | 1898 | } |
1890 | 1899 | ||
1891 | out_unlock: | 1900 | out_unlock: |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 8cbe77dc1dbb..8c5229892e57 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -562,11 +562,12 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, | |||
562 | "\tSecondary Channel Bitmap 0x%016llx\n", | 562 | "\tSecondary Channel Bitmap 0x%016llx\n", |
563 | le64_to_cpu(cmd->bt_secondary_ci)); | 563 | le64_to_cpu(cmd->bt_secondary_ci)); |
564 | 564 | ||
565 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); | 565 | pos += scnprintf(buf+pos, bufsz-pos, |
566 | pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", | 566 | "BT Configuration CMD - 0=default, 1=never, 2=always\n"); |
567 | iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]); | 567 | pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill msk idx %d\n", |
568 | pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", | 568 | mvm->bt_ack_kill_msk[0]); |
569 | iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]); | 569 | pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill msk idx %d\n", |
570 | mvm->bt_cts_kill_msk[0]); | ||
570 | 571 | ||
571 | } else { | 572 | } else { |
572 | struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; | 573 | struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; |
@@ -579,21 +580,6 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, | |||
579 | pos += scnprintf(buf+pos, bufsz-pos, | 580 | pos += scnprintf(buf+pos, bufsz-pos, |
580 | "\tSecondary Channel Bitmap 0x%016llx\n", | 581 | "\tSecondary Channel Bitmap 0x%016llx\n", |
581 | le64_to_cpu(cmd->bt_secondary_ci)); | 582 | le64_to_cpu(cmd->bt_secondary_ci)); |
582 | |||
583 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); | ||
584 | pos += scnprintf(buf+pos, bufsz-pos, | ||
585 | "\tPrimary: ACK Kill Mask 0x%08x\n", | ||
586 | iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]); | ||
587 | pos += scnprintf(buf+pos, bufsz-pos, | ||
588 | "\tPrimary: CTS Kill Mask 0x%08x\n", | ||
589 | iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]); | ||
590 | pos += scnprintf(buf+pos, bufsz-pos, | ||
591 | "\tSecondary: ACK Kill Mask 0x%08x\n", | ||
592 | iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[1]]); | ||
593 | pos += scnprintf(buf+pos, bufsz-pos, | ||
594 | "\tSecondary: CTS Kill Mask 0x%08x\n", | ||
595 | iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[1]]); | ||
596 | |||
597 | } | 583 | } |
598 | 584 | ||
599 | mutex_unlock(&mvm->mutex); | 585 | mutex_unlock(&mvm->mutex); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h index f3b11897991e..d398a6102805 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | |||
@@ -235,36 +235,12 @@ enum iwl_bt_coex_enabled_modules { | |||
235 | * struct iwl_bt_coex_cmd - bt coex configuration command | 235 | * struct iwl_bt_coex_cmd - bt coex configuration command |
236 | * @mode: enum %iwl_bt_coex_mode | 236 | * @mode: enum %iwl_bt_coex_mode |
237 | * @enabled_modules: enum %iwl_bt_coex_enabled_modules | 237 | * @enabled_modules: enum %iwl_bt_coex_enabled_modules |
238 | * @max_kill: max count of Tx retries due to kill from PTA | ||
239 | * @override_primary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT | ||
240 | * should be set by default | ||
241 | * @override_secondary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT | ||
242 | * should be set by default | ||
243 | * @bt4_antenna_isolation_thr: antenna threshold value | ||
244 | * @bt4_tx_tx_delta_freq_thr: TxTx delta frequency | ||
245 | * @bt4_tx_rx_max_freq0: TxRx max frequency | ||
246 | * @multiprio_lut: multi priority LUT configuration | ||
247 | * @mplut_prio_boost: BT priority boost registers | ||
248 | * @decision_lut: PTA decision LUT, per Prio-Ch | ||
249 | * | 238 | * |
250 | * The structure is used for the BT_COEX command. | 239 | * The structure is used for the BT_COEX command. |
251 | */ | 240 | */ |
252 | struct iwl_bt_coex_cmd { | 241 | struct iwl_bt_coex_cmd { |
253 | __le32 mode; | 242 | __le32 mode; |
254 | __le32 enabled_modules; | 243 | __le32 enabled_modules; |
255 | |||
256 | __le32 max_kill; | ||
257 | __le32 override_primary_lut; | ||
258 | __le32 override_secondary_lut; | ||
259 | __le32 bt4_antenna_isolation_thr; | ||
260 | |||
261 | __le32 bt4_tx_tx_delta_freq_thr; | ||
262 | __le32 bt4_tx_rx_max_freq0; | ||
263 | |||
264 | __le32 multiprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE]; | ||
265 | __le32 mplut_prio_boost[BT_COEX_BOOST_SIZE]; | ||
266 | |||
267 | __le32 decision_lut[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE]; | ||
268 | } __packed; /* BT_COEX_CMD_API_S_VER_6 */ | 244 | } __packed; /* BT_COEX_CMD_API_S_VER_6 */ |
269 | 245 | ||
270 | /** | 246 | /** |
@@ -280,29 +256,6 @@ struct iwl_bt_coex_corun_lut_update_cmd { | |||
280 | } __packed; /* BT_COEX_UPDATE_CORUN_LUT_API_S_VER_1 */ | 256 | } __packed; /* BT_COEX_UPDATE_CORUN_LUT_API_S_VER_1 */ |
281 | 257 | ||
282 | /** | 258 | /** |
283 | * struct iwl_bt_coex_sw_boost - SW boost values | ||
284 | * @wifi_tx_prio_boost: SW boost of wifi tx priority | ||
285 | * @wifi_rx_prio_boost: SW boost of wifi rx priority | ||
286 | * @kill_ack_msk: kill ACK mask. 1 - Tx ACK, 0 - kill Tx of ACK. | ||
287 | * @kill_cts_msk: kill CTS mask. 1 - Tx CTS, 0 - kill Tx of CTS. | ||
288 | */ | ||
289 | struct iwl_bt_coex_sw_boost { | ||
290 | __le32 wifi_tx_prio_boost; | ||
291 | __le32 wifi_rx_prio_boost; | ||
292 | __le32 kill_ack_msk; | ||
293 | __le32 kill_cts_msk; | ||
294 | }; | ||
295 | |||
296 | /** | ||
297 | * struct iwl_bt_coex_sw_boost_update_cmd - command to update the SW boost | ||
298 | * @boost_values: check struct %iwl_bt_coex_sw_boost - one for each channel | ||
299 | * primary / secondary / low priority | ||
300 | */ | ||
301 | struct iwl_bt_coex_sw_boost_update_cmd { | ||
302 | struct iwl_bt_coex_sw_boost boost_values[3]; | ||
303 | } __packed; /* BT_COEX_UPDATE_SW_BOOST_S_VER_1 */ | ||
304 | |||
305 | /** | ||
306 | * struct iwl_bt_coex_reduced_txp_update_cmd | 259 | * struct iwl_bt_coex_reduced_txp_update_cmd |
307 | * @reduced_txp: bit BT_REDUCED_TX_POWER_BIT to enable / disable, rest of the | 260 | * @reduced_txp: bit BT_REDUCED_TX_POWER_BIT to enable / disable, rest of the |
308 | * bits are the sta_id (value) | 261 | * bits are the sta_id (value) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index d95b47213731..aab68cbae754 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -212,6 +212,10 @@ enum { | |||
212 | REPLY_RX_MPDU_CMD = 0xc1, | 212 | REPLY_RX_MPDU_CMD = 0xc1, |
213 | BA_NOTIF = 0xc5, | 213 | BA_NOTIF = 0xc5, |
214 | 214 | ||
215 | /* Location Aware Regulatory */ | ||
216 | MCC_UPDATE_CMD = 0xc8, | ||
217 | MCC_CHUB_UPDATE_CMD = 0xc9, | ||
218 | |||
215 | MARKER_CMD = 0xcb, | 219 | MARKER_CMD = 0xcb, |
216 | 220 | ||
217 | /* BT Coex */ | 221 | /* BT Coex */ |
@@ -362,7 +366,8 @@ enum { | |||
362 | NVM_SECTION_TYPE_CALIBRATION = 4, | 366 | NVM_SECTION_TYPE_CALIBRATION = 4, |
363 | NVM_SECTION_TYPE_PRODUCTION = 5, | 367 | NVM_SECTION_TYPE_PRODUCTION = 5, |
364 | NVM_SECTION_TYPE_MAC_OVERRIDE = 11, | 368 | NVM_SECTION_TYPE_MAC_OVERRIDE = 11, |
365 | NVM_MAX_NUM_SECTIONS = 12, | 369 | NVM_SECTION_TYPE_PHY_SKU = 12, |
370 | NVM_MAX_NUM_SECTIONS = 13, | ||
366 | }; | 371 | }; |
367 | 372 | ||
368 | /** | 373 | /** |
@@ -1442,7 +1447,19 @@ enum iwl_sf_scenario { | |||
1442 | #define SF_W_MARK_LEGACY 4096 | 1447 | #define SF_W_MARK_LEGACY 4096 |
1443 | #define SF_W_MARK_SCAN 4096 | 1448 | #define SF_W_MARK_SCAN 4096 |
1444 | 1449 | ||
1445 | /* SF Scenarios timers for FULL_ON state (aligned to 32 uSec) */ | 1450 | /* SF Scenarios timers for default configuration (aligned to 32 uSec) */ |
1451 | #define SF_SINGLE_UNICAST_IDLE_TIMER_DEF 160 /* 150 uSec */ | ||
1452 | #define SF_SINGLE_UNICAST_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1453 | #define SF_AGG_UNICAST_IDLE_TIMER_DEF 160 /* 150 uSec */ | ||
1454 | #define SF_AGG_UNICAST_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1455 | #define SF_MCAST_IDLE_TIMER_DEF 160 /* 150 mSec */ | ||
1456 | #define SF_MCAST_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1457 | #define SF_BA_IDLE_TIMER_DEF 160 /* 150 uSec */ | ||
1458 | #define SF_BA_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1459 | #define SF_TX_RE_IDLE_TIMER_DEF 160 /* 150 uSec */ | ||
1460 | #define SF_TX_RE_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1461 | |||
1462 | /* SF Scenarios timers for BSS MAC configuration (aligned to 32 uSec) */ | ||
1446 | #define SF_SINGLE_UNICAST_IDLE_TIMER 320 /* 300 uSec */ | 1463 | #define SF_SINGLE_UNICAST_IDLE_TIMER 320 /* 300 uSec */ |
1447 | #define SF_SINGLE_UNICAST_AGING_TIMER 2016 /* 2 mSec */ | 1464 | #define SF_SINGLE_UNICAST_AGING_TIMER 2016 /* 2 mSec */ |
1448 | #define SF_AGG_UNICAST_IDLE_TIMER 320 /* 300 uSec */ | 1465 | #define SF_AGG_UNICAST_IDLE_TIMER 320 /* 300 uSec */ |
@@ -1473,6 +1490,92 @@ struct iwl_sf_cfg_cmd { | |||
1473 | __le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; | 1490 | __le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; |
1474 | } __packed; /* SF_CFG_API_S_VER_2 */ | 1491 | } __packed; /* SF_CFG_API_S_VER_2 */ |
1475 | 1492 | ||
1493 | /*********************************** | ||
1494 | * Location Aware Regulatory (LAR) API - MCC updates | ||
1495 | ***********************************/ | ||
1496 | |||
1497 | /** | ||
1498 | * struct iwl_mcc_update_cmd - Request the device to update geographic | ||
1499 | * regulatory profile according to the given MCC (Mobile Country Code). | ||
1500 | * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain. | ||
1501 | * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the | ||
1502 | * MCC in the cmd response will be the relevant MCC in the NVM. | ||
1503 | * @mcc: given mobile country code | ||
1504 | * @source_id: the source from where we got the MCC, see iwl_mcc_source | ||
1505 | * @reserved: reserved for alignment | ||
1506 | */ | ||
1507 | struct iwl_mcc_update_cmd { | ||
1508 | __le16 mcc; | ||
1509 | u8 source_id; | ||
1510 | u8 reserved; | ||
1511 | } __packed; /* LAR_UPDATE_MCC_CMD_API_S */ | ||
1512 | |||
1513 | /** | ||
1514 | * iwl_mcc_update_resp - response to MCC_UPDATE_CMD. | ||
1515 | * Contains the new channel control profile map, if changed, and the new MCC | ||
1516 | * (mobile country code). | ||
1517 | * The new MCC may be different than what was requested in MCC_UPDATE_CMD. | ||
1518 | * @status: see &enum iwl_mcc_update_status | ||
1519 | * @mcc: the new applied MCC | ||
1520 | * @cap: capabilities for all channels which matches the MCC | ||
1521 | * @source_id: the MCC source, see iwl_mcc_source | ||
1522 | * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51 | ||
1523 | * channels, depending on platform) | ||
1524 | * @channels: channel control data map, DWORD for each channel. Only the first | ||
1525 | * 16bits are used. | ||
1526 | */ | ||
1527 | struct iwl_mcc_update_resp { | ||
1528 | __le32 status; | ||
1529 | __le16 mcc; | ||
1530 | u8 cap; | ||
1531 | u8 source_id; | ||
1532 | __le32 n_channels; | ||
1533 | __le32 channels[0]; | ||
1534 | } __packed; /* LAR_UPDATE_MCC_CMD_RESP_S */ | ||
1535 | |||
1536 | /** | ||
1537 | * struct iwl_mcc_chub_notif - chub notifies of mcc change | ||
1538 | * (MCC_CHUB_UPDATE_CMD = 0xc9) | ||
1539 | * The Chub (Communication Hub, CommsHUB) is a HW component that connects to | ||
1540 | * the cellular and connectivity cores that gets updates of the mcc, and | ||
1541 | * notifies the ucode directly of any mcc change. | ||
1542 | * The ucode requests the driver to request the device to update geographic | ||
1543 | * regulatory profile according to the given MCC (Mobile Country Code). | ||
1544 | * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain. | ||
1545 | * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the | ||
1546 | * MCC in the cmd response will be the relevant MCC in the NVM. | ||
1547 | * @mcc: given mobile country code | ||
1548 | * @source_id: identity of the change originator, see iwl_mcc_source | ||
1549 | * @reserved1: reserved for alignment | ||
1550 | */ | ||
1551 | struct iwl_mcc_chub_notif { | ||
1552 | u16 mcc; | ||
1553 | u8 source_id; | ||
1554 | u8 reserved1; | ||
1555 | } __packed; /* LAR_MCC_NOTIFY_S */ | ||
1556 | |||
1557 | enum iwl_mcc_update_status { | ||
1558 | MCC_RESP_NEW_CHAN_PROFILE, | ||
1559 | MCC_RESP_SAME_CHAN_PROFILE, | ||
1560 | MCC_RESP_INVALID, | ||
1561 | MCC_RESP_NVM_DISABLED, | ||
1562 | MCC_RESP_ILLEGAL, | ||
1563 | MCC_RESP_LOW_PRIORITY, | ||
1564 | }; | ||
1565 | |||
1566 | enum iwl_mcc_source { | ||
1567 | MCC_SOURCE_OLD_FW = 0, | ||
1568 | MCC_SOURCE_ME = 1, | ||
1569 | MCC_SOURCE_BIOS = 2, | ||
1570 | MCC_SOURCE_3G_LTE_HOST = 3, | ||
1571 | MCC_SOURCE_3G_LTE_DEVICE = 4, | ||
1572 | MCC_SOURCE_WIFI = 5, | ||
1573 | MCC_SOURCE_RESERVED = 6, | ||
1574 | MCC_SOURCE_DEFAULT = 7, | ||
1575 | MCC_SOURCE_UNINITIALIZED = 8, | ||
1576 | MCC_SOURCE_GET_CURRENT = 0x10 | ||
1577 | }; | ||
1578 | |||
1476 | /* DTS measurements */ | 1579 | /* DTS measurements */ |
1477 | 1580 | ||
1478 | enum iwl_dts_measurement_flags { | 1581 | enum iwl_dts_measurement_flags { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index a81da4cde643..6cf7d9837ca5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -739,6 +739,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
739 | if (ret) | 739 | if (ret) |
740 | goto error; | 740 | goto error; |
741 | 741 | ||
742 | /* | ||
743 | * RTNL is not taken during Ct-kill, but we don't need to scan/Tx | ||
744 | * anyway, so don't init MCC. | ||
745 | */ | ||
746 | if (!test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status)) { | ||
747 | ret = iwl_mvm_init_mcc(mvm); | ||
748 | if (ret) | ||
749 | goto error; | ||
750 | } | ||
751 | |||
742 | if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) { | 752 | if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) { |
743 | ret = iwl_mvm_config_scan(mvm); | 753 | ret = iwl_mvm_config_scan(mvm); |
744 | if (ret) | 754 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 7396b52262b5..302c8cc50f25 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -86,6 +86,7 @@ | |||
86 | #include "iwl-fw-error-dump.h" | 86 | #include "iwl-fw-error-dump.h" |
87 | #include "iwl-prph.h" | 87 | #include "iwl-prph.h" |
88 | #include "iwl-csr.h" | 88 | #include "iwl-csr.h" |
89 | #include "iwl-nvm-parse.h" | ||
89 | 90 | ||
90 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { | 91 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { |
91 | { | 92 | { |
@@ -301,6 +302,109 @@ static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm) | |||
301 | } | 302 | } |
302 | } | 303 | } |
303 | 304 | ||
305 | struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, | ||
306 | const char *alpha2, | ||
307 | enum iwl_mcc_source src_id, | ||
308 | bool *changed) | ||
309 | { | ||
310 | struct ieee80211_regdomain *regd = NULL; | ||
311 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
312 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
313 | struct iwl_mcc_update_resp *resp; | ||
314 | |||
315 | IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2); | ||
316 | |||
317 | lockdep_assert_held(&mvm->mutex); | ||
318 | |||
319 | resp = iwl_mvm_update_mcc(mvm, alpha2, src_id); | ||
320 | if (IS_ERR_OR_NULL(resp)) { | ||
321 | IWL_DEBUG_LAR(mvm, "Could not get update from FW %d\n", | ||
322 | PTR_RET(resp)); | ||
323 | goto out; | ||
324 | } | ||
325 | |||
326 | if (changed) | ||
327 | *changed = (resp->status == MCC_RESP_NEW_CHAN_PROFILE); | ||
328 | |||
329 | regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg, | ||
330 | __le32_to_cpu(resp->n_channels), | ||
331 | resp->channels, | ||
332 | __le16_to_cpu(resp->mcc)); | ||
333 | /* Store the return source id */ | ||
334 | src_id = resp->source_id; | ||
335 | kfree(resp); | ||
336 | if (IS_ERR_OR_NULL(regd)) { | ||
337 | IWL_DEBUG_LAR(mvm, "Could not get parse update from FW %d\n", | ||
338 | PTR_RET(regd)); | ||
339 | goto out; | ||
340 | } | ||
341 | |||
342 | IWL_DEBUG_LAR(mvm, "setting alpha2 from FW to %s (0x%x, 0x%x) src=%d\n", | ||
343 | regd->alpha2, regd->alpha2[0], regd->alpha2[1], src_id); | ||
344 | mvm->lar_regdom_set = true; | ||
345 | mvm->mcc_src = src_id; | ||
346 | |||
347 | out: | ||
348 | return regd; | ||
349 | } | ||
350 | |||
351 | void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm) | ||
352 | { | ||
353 | bool changed; | ||
354 | struct ieee80211_regdomain *regd; | ||
355 | |||
356 | if (!iwl_mvm_is_lar_supported(mvm)) | ||
357 | return; | ||
358 | |||
359 | regd = iwl_mvm_get_current_regdomain(mvm, &changed); | ||
360 | if (!IS_ERR_OR_NULL(regd)) { | ||
361 | /* only update the regulatory core if changed */ | ||
362 | if (changed) | ||
363 | regulatory_set_wiphy_regd(mvm->hw->wiphy, regd); | ||
364 | |||
365 | kfree(regd); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm, | ||
370 | bool *changed) | ||
371 | { | ||
372 | return iwl_mvm_get_regdomain(mvm->hw->wiphy, "ZZ", | ||
373 | iwl_mvm_is_wifi_mcc_supported(mvm) ? | ||
374 | MCC_SOURCE_GET_CURRENT : | ||
375 | MCC_SOURCE_OLD_FW, changed); | ||
376 | } | ||
377 | |||
378 | int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm) | ||
379 | { | ||
380 | enum iwl_mcc_source used_src; | ||
381 | struct ieee80211_regdomain *regd; | ||
382 | const struct ieee80211_regdomain *r = | ||
383 | rtnl_dereference(mvm->hw->wiphy->regd); | ||
384 | |||
385 | if (!r) | ||
386 | return 0; | ||
387 | |||
388 | /* save the last source in case we overwrite it below */ | ||
389 | used_src = mvm->mcc_src; | ||
390 | if (iwl_mvm_is_wifi_mcc_supported(mvm)) { | ||
391 | /* Notify the firmware we support wifi location updates */ | ||
392 | regd = iwl_mvm_get_current_regdomain(mvm, NULL); | ||
393 | if (!IS_ERR_OR_NULL(regd)) | ||
394 | kfree(regd); | ||
395 | } | ||
396 | |||
397 | /* Now set our last stored MCC and source */ | ||
398 | regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, r->alpha2, used_src, NULL); | ||
399 | if (IS_ERR_OR_NULL(regd)) | ||
400 | return -EIO; | ||
401 | |||
402 | regulatory_set_wiphy_regd(mvm->hw->wiphy, regd); | ||
403 | kfree(regd); | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
304 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | 408 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) |
305 | { | 409 | { |
306 | struct ieee80211_hw *hw = mvm->hw; | 410 | struct ieee80211_hw *hw = mvm->hw; |
@@ -356,8 +460,12 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
356 | BIT(NL80211_IFTYPE_ADHOC); | 460 | BIT(NL80211_IFTYPE_ADHOC); |
357 | 461 | ||
358 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 462 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
359 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | | 463 | hw->wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR; |
360 | REGULATORY_DISABLE_BEACON_HINTS; | 464 | if (iwl_mvm_is_lar_supported(mvm)) |
465 | hw->wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; | ||
466 | else | ||
467 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | | ||
468 | REGULATORY_DISABLE_BEACON_HINTS; | ||
361 | 469 | ||
362 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD) | 470 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD) |
363 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | 471 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; |
@@ -1193,7 +1301,7 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm) | |||
1193 | 1301 | ||
1194 | clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); | 1302 | clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); |
1195 | iwl_mvm_d0i3_enable_tx(mvm, NULL); | 1303 | iwl_mvm_d0i3_enable_tx(mvm, NULL); |
1196 | ret = iwl_mvm_update_quotas(mvm, NULL); | 1304 | ret = iwl_mvm_update_quotas(mvm, false, NULL); |
1197 | if (ret) | 1305 | if (ret) |
1198 | IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n", | 1306 | IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n", |
1199 | ret); | 1307 | ret); |
@@ -1872,7 +1980,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
1872 | sizeof(mvmvif->beacon_stats)); | 1980 | sizeof(mvmvif->beacon_stats)); |
1873 | 1981 | ||
1874 | /* add quota for this interface */ | 1982 | /* add quota for this interface */ |
1875 | ret = iwl_mvm_update_quotas(mvm, NULL); | 1983 | ret = iwl_mvm_update_quotas(mvm, true, NULL); |
1876 | if (ret) { | 1984 | if (ret) { |
1877 | IWL_ERR(mvm, "failed to update quotas\n"); | 1985 | IWL_ERR(mvm, "failed to update quotas\n"); |
1878 | return; | 1986 | return; |
@@ -1924,7 +2032,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
1924 | mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; | 2032 | mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; |
1925 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; | 2033 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; |
1926 | /* remove quota for this interface */ | 2034 | /* remove quota for this interface */ |
1927 | ret = iwl_mvm_update_quotas(mvm, NULL); | 2035 | ret = iwl_mvm_update_quotas(mvm, false, NULL); |
1928 | if (ret) | 2036 | if (ret) |
1929 | IWL_ERR(mvm, "failed to update quotas\n"); | 2037 | IWL_ERR(mvm, "failed to update quotas\n"); |
1930 | 2038 | ||
@@ -2043,7 +2151,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
2043 | /* power updated needs to be done before quotas */ | 2151 | /* power updated needs to be done before quotas */ |
2044 | iwl_mvm_power_update_mac(mvm); | 2152 | iwl_mvm_power_update_mac(mvm); |
2045 | 2153 | ||
2046 | ret = iwl_mvm_update_quotas(mvm, NULL); | 2154 | ret = iwl_mvm_update_quotas(mvm, false, NULL); |
2047 | if (ret) | 2155 | if (ret) |
2048 | goto out_quota_failed; | 2156 | goto out_quota_failed; |
2049 | 2157 | ||
@@ -2109,7 +2217,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, | |||
2109 | if (vif->p2p && mvm->p2p_device_vif) | 2217 | if (vif->p2p && mvm->p2p_device_vif) |
2110 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL); | 2218 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL); |
2111 | 2219 | ||
2112 | iwl_mvm_update_quotas(mvm, NULL); | 2220 | iwl_mvm_update_quotas(mvm, false, NULL); |
2113 | iwl_mvm_send_rm_bcast_sta(mvm, vif); | 2221 | iwl_mvm_send_rm_bcast_sta(mvm, vif); |
2114 | iwl_mvm_binding_remove_vif(mvm, vif); | 2222 | iwl_mvm_binding_remove_vif(mvm, vif); |
2115 | 2223 | ||
@@ -2248,6 +2356,12 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | |||
2248 | 2356 | ||
2249 | mutex_lock(&mvm->mutex); | 2357 | mutex_lock(&mvm->mutex); |
2250 | 2358 | ||
2359 | if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) { | ||
2360 | IWL_ERR(mvm, "scan while LAR regdomain is not set\n"); | ||
2361 | ret = -EBUSY; | ||
2362 | goto out; | ||
2363 | } | ||
2364 | |||
2251 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { | 2365 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { |
2252 | ret = -EBUSY; | 2366 | ret = -EBUSY; |
2253 | goto out; | 2367 | goto out; |
@@ -2328,25 +2442,35 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | |||
2328 | { | 2442 | { |
2329 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 2443 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
2330 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 2444 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
2445 | unsigned long txqs = 0, tids = 0; | ||
2331 | int tid; | 2446 | int tid; |
2332 | 2447 | ||
2448 | spin_lock_bh(&mvmsta->lock); | ||
2449 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { | ||
2450 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | ||
2451 | |||
2452 | if (tid_data->state != IWL_AGG_ON && | ||
2453 | tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA) | ||
2454 | continue; | ||
2455 | |||
2456 | __set_bit(tid_data->txq_id, &txqs); | ||
2457 | |||
2458 | if (iwl_mvm_tid_queued(tid_data) == 0) | ||
2459 | continue; | ||
2460 | |||
2461 | __set_bit(tid, &tids); | ||
2462 | } | ||
2463 | |||
2333 | switch (cmd) { | 2464 | switch (cmd) { |
2334 | case STA_NOTIFY_SLEEP: | 2465 | case STA_NOTIFY_SLEEP: |
2335 | if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0) | 2466 | if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0) |
2336 | ieee80211_sta_block_awake(hw, sta, true); | 2467 | ieee80211_sta_block_awake(hw, sta, true); |
2337 | spin_lock_bh(&mvmsta->lock); | ||
2338 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { | ||
2339 | struct iwl_mvm_tid_data *tid_data; | ||
2340 | 2468 | ||
2341 | tid_data = &mvmsta->tid_data[tid]; | 2469 | for_each_set_bit(tid, &tids, IWL_MAX_TID_COUNT) |
2342 | if (tid_data->state != IWL_AGG_ON && | ||
2343 | tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA) | ||
2344 | continue; | ||
2345 | if (iwl_mvm_tid_queued(tid_data) == 0) | ||
2346 | continue; | ||
2347 | ieee80211_sta_set_buffered(sta, tid, true); | 2470 | ieee80211_sta_set_buffered(sta, tid, true); |
2348 | } | 2471 | |
2349 | spin_unlock_bh(&mvmsta->lock); | 2472 | if (txqs) |
2473 | iwl_trans_freeze_txq_timer(mvm->trans, txqs, true); | ||
2350 | /* | 2474 | /* |
2351 | * The fw updates the STA to be asleep. Tx packets on the Tx | 2475 | * The fw updates the STA to be asleep. Tx packets on the Tx |
2352 | * queues to this station will not be transmitted. The fw will | 2476 | * queues to this station will not be transmitted. The fw will |
@@ -2356,11 +2480,15 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | |||
2356 | case STA_NOTIFY_AWAKE: | 2480 | case STA_NOTIFY_AWAKE: |
2357 | if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) | 2481 | if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) |
2358 | break; | 2482 | break; |
2483 | |||
2484 | if (txqs) | ||
2485 | iwl_trans_freeze_txq_timer(mvm->trans, txqs, false); | ||
2359 | iwl_mvm_sta_modify_ps_wake(mvm, sta); | 2486 | iwl_mvm_sta_modify_ps_wake(mvm, sta); |
2360 | break; | 2487 | break; |
2361 | default: | 2488 | default: |
2362 | break; | 2489 | break; |
2363 | } | 2490 | } |
2491 | spin_unlock_bh(&mvmsta->lock); | ||
2364 | } | 2492 | } |
2365 | 2493 | ||
2366 | static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, | 2494 | static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, |
@@ -2598,6 +2726,12 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | |||
2598 | 2726 | ||
2599 | mutex_lock(&mvm->mutex); | 2727 | mutex_lock(&mvm->mutex); |
2600 | 2728 | ||
2729 | if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) { | ||
2730 | IWL_ERR(mvm, "sched-scan while LAR regdomain is not set\n"); | ||
2731 | ret = -EBUSY; | ||
2732 | goto out; | ||
2733 | } | ||
2734 | |||
2601 | if (!vif->bss_conf.idle) { | 2735 | if (!vif->bss_conf.idle) { |
2602 | ret = -EBUSY; | 2736 | ret = -EBUSY; |
2603 | goto out; | 2737 | goto out; |
@@ -3159,14 +3293,14 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, | |||
3159 | */ | 3293 | */ |
3160 | if (vif->type == NL80211_IFTYPE_MONITOR) { | 3294 | if (vif->type == NL80211_IFTYPE_MONITOR) { |
3161 | mvmvif->monitor_active = true; | 3295 | mvmvif->monitor_active = true; |
3162 | ret = iwl_mvm_update_quotas(mvm, NULL); | 3296 | ret = iwl_mvm_update_quotas(mvm, false, NULL); |
3163 | if (ret) | 3297 | if (ret) |
3164 | goto out_remove_binding; | 3298 | goto out_remove_binding; |
3165 | } | 3299 | } |
3166 | 3300 | ||
3167 | /* Handle binding during CSA */ | 3301 | /* Handle binding during CSA */ |
3168 | if (vif->type == NL80211_IFTYPE_AP) { | 3302 | if (vif->type == NL80211_IFTYPE_AP) { |
3169 | iwl_mvm_update_quotas(mvm, NULL); | 3303 | iwl_mvm_update_quotas(mvm, false, NULL); |
3170 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); | 3304 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); |
3171 | } | 3305 | } |
3172 | 3306 | ||
@@ -3190,7 +3324,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, | |||
3190 | 3324 | ||
3191 | iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA); | 3325 | iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA); |
3192 | 3326 | ||
3193 | iwl_mvm_update_quotas(mvm, NULL); | 3327 | iwl_mvm_update_quotas(mvm, false, NULL); |
3194 | } | 3328 | } |
3195 | 3329 | ||
3196 | goto out; | 3330 | goto out; |
@@ -3263,7 +3397,7 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm, | |||
3263 | break; | 3397 | break; |
3264 | } | 3398 | } |
3265 | 3399 | ||
3266 | iwl_mvm_update_quotas(mvm, disabled_vif); | 3400 | iwl_mvm_update_quotas(mvm, false, disabled_vif); |
3267 | iwl_mvm_binding_remove_vif(mvm, vif); | 3401 | iwl_mvm_binding_remove_vif(mvm, vif); |
3268 | 3402 | ||
3269 | out: | 3403 | out: |
@@ -3455,7 +3589,7 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm, | |||
3455 | mvm->noa_duration = noa_duration; | 3589 | mvm->noa_duration = noa_duration; |
3456 | mvm->noa_vif = vif; | 3590 | mvm->noa_vif = vif; |
3457 | 3591 | ||
3458 | return iwl_mvm_update_quotas(mvm, NULL); | 3592 | return iwl_mvm_update_quotas(mvm, false, NULL); |
3459 | case IWL_MVM_TM_CMD_SET_BEACON_FILTER: | 3593 | case IWL_MVM_TM_CMD_SET_BEACON_FILTER: |
3460 | /* must be associated client vif - ignore authorized */ | 3594 | /* must be associated client vif - ignore authorized */ |
3461 | if (!vif || vif->type != NL80211_IFTYPE_STATION || | 3595 | if (!vif || vif->type != NL80211_IFTYPE_STATION || |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 95cad68ab069..4b5c8f66df8b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -810,6 +810,9 @@ struct iwl_mvm { | |||
810 | /* system time of last beacon (for AP/GO interface) */ | 810 | /* system time of last beacon (for AP/GO interface) */ |
811 | u32 ap_last_beacon_gp2; | 811 | u32 ap_last_beacon_gp2; |
812 | 812 | ||
813 | bool lar_regdom_set; | ||
814 | enum iwl_mcc_source mcc_src; | ||
815 | |||
813 | u8 low_latency_agg_frame_limit; | 816 | u8 low_latency_agg_frame_limit; |
814 | 817 | ||
815 | /* TDLS channel switch data */ | 818 | /* TDLS channel switch data */ |
@@ -910,6 +913,30 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) | |||
910 | (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); | 913 | (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); |
911 | } | 914 | } |
912 | 915 | ||
916 | static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm) | ||
917 | { | ||
918 | bool nvm_lar = mvm->nvm_data->lar_enabled; | ||
919 | bool tlv_lar = mvm->fw->ucode_capa.capa[0] & | ||
920 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT; | ||
921 | |||
922 | if (iwlwifi_mod_params.lar_disable) | ||
923 | return false; | ||
924 | |||
925 | /* | ||
926 | * Enable LAR only if it is supported by the FW (TLV) && | ||
927 | * enabled in the NVM | ||
928 | */ | ||
929 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
930 | return nvm_lar && tlv_lar; | ||
931 | else | ||
932 | return tlv_lar; | ||
933 | } | ||
934 | |||
935 | static inline bool iwl_mvm_is_wifi_mcc_supported(struct iwl_mvm *mvm) | ||
936 | { | ||
937 | return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WIFI_MCC_UPDATE; | ||
938 | } | ||
939 | |||
913 | static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) | 940 | static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) |
914 | { | 941 | { |
915 | return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SCD_CFG; | 942 | return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SCD_CFG; |
@@ -921,6 +948,12 @@ static inline bool iwl_mvm_bt_is_plcr_supported(struct iwl_mvm *mvm) | |||
921 | IWL_MVM_BT_COEX_CORUNNING; | 948 | IWL_MVM_BT_COEX_CORUNNING; |
922 | } | 949 | } |
923 | 950 | ||
951 | static inline bool iwl_mvm_bt_is_rrc_supported(struct iwl_mvm *mvm) | ||
952 | { | ||
953 | return (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BT_COEX_RRC) && | ||
954 | IWL_MVM_BT_COEX_RRC; | ||
955 | } | ||
956 | |||
924 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; | 957 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; |
925 | 958 | ||
926 | struct iwl_rate_info { | 959 | struct iwl_rate_info { |
@@ -1106,7 +1139,7 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | |||
1106 | int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 1139 | int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
1107 | 1140 | ||
1108 | /* Quota management */ | 1141 | /* Quota management */ |
1109 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, | 1142 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, bool force_upload, |
1110 | struct ieee80211_vif *disabled_vif); | 1143 | struct ieee80211_vif *disabled_vif); |
1111 | 1144 | ||
1112 | /* Scanning */ | 1145 | /* Scanning */ |
@@ -1282,17 +1315,6 @@ int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm, | |||
1282 | struct iwl_rx_cmd_buffer *rxb, | 1315 | struct iwl_rx_cmd_buffer *rxb, |
1283 | struct iwl_device_cmd *cmd); | 1316 | struct iwl_device_cmd *cmd); |
1284 | 1317 | ||
1285 | enum iwl_bt_kill_msk { | ||
1286 | BT_KILL_MSK_DEFAULT, | ||
1287 | BT_KILL_MSK_NEVER, | ||
1288 | BT_KILL_MSK_ALWAYS, | ||
1289 | BT_KILL_MSK_MAX, | ||
1290 | }; | ||
1291 | |||
1292 | extern const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT]; | ||
1293 | extern const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT]; | ||
1294 | extern const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX]; | ||
1295 | |||
1296 | /* beacon filtering */ | 1318 | /* beacon filtering */ |
1297 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1319 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1298 | void | 1320 | void |
@@ -1389,6 +1411,23 @@ void iwl_mvm_tt_exit(struct iwl_mvm *mvm); | |||
1389 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); | 1411 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); |
1390 | int iwl_mvm_get_temp(struct iwl_mvm *mvm); | 1412 | int iwl_mvm_get_temp(struct iwl_mvm *mvm); |
1391 | 1413 | ||
1414 | /* Location Aware Regulatory */ | ||
1415 | struct iwl_mcc_update_resp * | ||
1416 | iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, | ||
1417 | enum iwl_mcc_source src_id); | ||
1418 | int iwl_mvm_init_mcc(struct iwl_mvm *mvm); | ||
1419 | int iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm, | ||
1420 | struct iwl_rx_cmd_buffer *rxb, | ||
1421 | struct iwl_device_cmd *cmd); | ||
1422 | struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, | ||
1423 | const char *alpha2, | ||
1424 | enum iwl_mcc_source src_id, | ||
1425 | bool *changed); | ||
1426 | struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm, | ||
1427 | bool *changed); | ||
1428 | int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm); | ||
1429 | void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm); | ||
1430 | |||
1392 | /* smart fifo */ | 1431 | /* smart fifo */ |
1393 | int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1432 | int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
1394 | bool added_vif); | 1433 | bool added_vif); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 5383429d96c1..123e0a16aea8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -63,12 +63,16 @@ | |||
63 | * | 63 | * |
64 | *****************************************************************************/ | 64 | *****************************************************************************/ |
65 | #include <linux/firmware.h> | 65 | #include <linux/firmware.h> |
66 | #include <linux/rtnetlink.h> | ||
67 | #include <linux/pci.h> | ||
68 | #include <linux/acpi.h> | ||
66 | #include "iwl-trans.h" | 69 | #include "iwl-trans.h" |
67 | #include "iwl-csr.h" | 70 | #include "iwl-csr.h" |
68 | #include "mvm.h" | 71 | #include "mvm.h" |
69 | #include "iwl-eeprom-parse.h" | 72 | #include "iwl-eeprom-parse.h" |
70 | #include "iwl-eeprom-read.h" | 73 | #include "iwl-eeprom-read.h" |
71 | #include "iwl-nvm-parse.h" | 74 | #include "iwl-nvm-parse.h" |
75 | #include "iwl-prph.h" | ||
72 | 76 | ||
73 | /* Default NVM size to read */ | 77 | /* Default NVM size to read */ |
74 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) | 78 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) |
@@ -262,7 +266,9 @@ static struct iwl_nvm_data * | |||
262 | iwl_parse_nvm_sections(struct iwl_mvm *mvm) | 266 | iwl_parse_nvm_sections(struct iwl_mvm *mvm) |
263 | { | 267 | { |
264 | struct iwl_nvm_section *sections = mvm->nvm_sections; | 268 | struct iwl_nvm_section *sections = mvm->nvm_sections; |
265 | const __le16 *hw, *sw, *calib, *regulatory, *mac_override; | 269 | const __le16 *hw, *sw, *calib, *regulatory, *mac_override, *phy_sku; |
270 | bool is_family_8000_a_step = false, lar_enabled; | ||
271 | u32 mac_addr0, mac_addr1; | ||
266 | 272 | ||
267 | /* Checking for required sections */ | 273 | /* Checking for required sections */ |
268 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { | 274 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
@@ -286,22 +292,43 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
286 | "Can't parse mac_address, empty sections\n"); | 292 | "Can't parse mac_address, empty sections\n"); |
287 | return NULL; | 293 | return NULL; |
288 | } | 294 | } |
295 | |||
296 | if (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP) | ||
297 | is_family_8000_a_step = true; | ||
298 | |||
299 | /* PHY_SKU section is mandatory in B0 */ | ||
300 | if (!is_family_8000_a_step && | ||
301 | !mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) { | ||
302 | IWL_ERR(mvm, | ||
303 | "Can't parse phy_sku in B0, empty sections\n"); | ||
304 | return NULL; | ||
305 | } | ||
289 | } | 306 | } |
290 | 307 | ||
291 | if (WARN_ON(!mvm->cfg)) | 308 | if (WARN_ON(!mvm->cfg)) |
292 | return NULL; | 309 | return NULL; |
293 | 310 | ||
311 | /* read the mac address from WFMP registers */ | ||
312 | mac_addr0 = iwl_trans_read_prph(mvm->trans, WFMP_MAC_ADDR_0); | ||
313 | mac_addr1 = iwl_trans_read_prph(mvm->trans, WFMP_MAC_ADDR_1); | ||
314 | |||
294 | hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data; | 315 | hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data; |
295 | sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; | 316 | sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; |
296 | calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; | 317 | calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; |
297 | regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data; | 318 | regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data; |
298 | mac_override = | 319 | mac_override = |
299 | (const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data; | 320 | (const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data; |
321 | phy_sku = (const __le16 *)sections[NVM_SECTION_TYPE_PHY_SKU].data; | ||
322 | |||
323 | lar_enabled = !iwlwifi_mod_params.lar_disable && | ||
324 | (mvm->fw->ucode_capa.capa[0] & | ||
325 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT); | ||
300 | 326 | ||
301 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, | 327 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, |
302 | regulatory, mac_override, | 328 | regulatory, mac_override, phy_sku, |
303 | mvm->fw->valid_tx_ant, | 329 | mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant, |
304 | mvm->fw->valid_rx_ant); | 330 | lar_enabled, is_family_8000_a_step, |
331 | mac_addr0, mac_addr1); | ||
305 | } | 332 | } |
306 | 333 | ||
307 | #define MAX_NVM_FILE_LEN 16384 | 334 | #define MAX_NVM_FILE_LEN 16384 |
@@ -570,3 +597,258 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) | |||
570 | 597 | ||
571 | return 0; | 598 | return 0; |
572 | } | 599 | } |
600 | |||
601 | struct iwl_mcc_update_resp * | ||
602 | iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, | ||
603 | enum iwl_mcc_source src_id) | ||
604 | { | ||
605 | struct iwl_mcc_update_cmd mcc_update_cmd = { | ||
606 | .mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]), | ||
607 | .source_id = (u8)src_id, | ||
608 | }; | ||
609 | struct iwl_mcc_update_resp *mcc_resp, *resp_cp = NULL; | ||
610 | struct iwl_rx_packet *pkt; | ||
611 | struct iwl_host_cmd cmd = { | ||
612 | .id = MCC_UPDATE_CMD, | ||
613 | .flags = CMD_WANT_SKB, | ||
614 | .data = { &mcc_update_cmd }, | ||
615 | }; | ||
616 | |||
617 | int ret; | ||
618 | u32 status; | ||
619 | int resp_len, n_channels; | ||
620 | u16 mcc; | ||
621 | |||
622 | if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm))) | ||
623 | return ERR_PTR(-EOPNOTSUPP); | ||
624 | |||
625 | cmd.len[0] = sizeof(struct iwl_mcc_update_cmd); | ||
626 | |||
627 | IWL_DEBUG_LAR(mvm, "send MCC update to FW with '%c%c' src = %d\n", | ||
628 | alpha2[0], alpha2[1], src_id); | ||
629 | |||
630 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
631 | if (ret) | ||
632 | return ERR_PTR(ret); | ||
633 | |||
634 | pkt = cmd.resp_pkt; | ||
635 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
636 | IWL_ERR(mvm, "Bad return from MCC_UPDATE_COMMAND (0x%08X)\n", | ||
637 | pkt->hdr.flags); | ||
638 | ret = -EIO; | ||
639 | goto exit; | ||
640 | } | ||
641 | |||
642 | /* Extract MCC response */ | ||
643 | mcc_resp = (void *)pkt->data; | ||
644 | status = le32_to_cpu(mcc_resp->status); | ||
645 | |||
646 | mcc = le16_to_cpu(mcc_resp->mcc); | ||
647 | |||
648 | /* W/A for a FW/NVM issue - returns 0x00 for the world domain */ | ||
649 | if (mcc == 0) { | ||
650 | mcc = 0x3030; /* "00" - world */ | ||
651 | mcc_resp->mcc = cpu_to_le16(mcc); | ||
652 | } | ||
653 | |||
654 | n_channels = __le32_to_cpu(mcc_resp->n_channels); | ||
655 | IWL_DEBUG_LAR(mvm, | ||
656 | "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') change: %d n_chans: %d\n", | ||
657 | status, mcc, mcc >> 8, mcc & 0xff, | ||
658 | !!(status == MCC_RESP_NEW_CHAN_PROFILE), n_channels); | ||
659 | |||
660 | resp_len = sizeof(*mcc_resp) + n_channels * sizeof(__le32); | ||
661 | resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL); | ||
662 | if (!resp_cp) { | ||
663 | ret = -ENOMEM; | ||
664 | goto exit; | ||
665 | } | ||
666 | |||
667 | ret = 0; | ||
668 | exit: | ||
669 | iwl_free_resp(&cmd); | ||
670 | if (ret) | ||
671 | return ERR_PTR(ret); | ||
672 | return resp_cp; | ||
673 | } | ||
674 | |||
675 | #ifdef CONFIG_ACPI | ||
676 | #define WRD_METHOD "WRDD" | ||
677 | #define WRDD_WIFI (0x07) | ||
678 | #define WRDD_WIGIG (0x10) | ||
679 | |||
680 | static u32 iwl_mvm_wrdd_get_mcc(struct iwl_mvm *mvm, union acpi_object *wrdd) | ||
681 | { | ||
682 | union acpi_object *mcc_pkg, *domain_type, *mcc_value; | ||
683 | u32 i; | ||
684 | |||
685 | if (wrdd->type != ACPI_TYPE_PACKAGE || | ||
686 | wrdd->package.count < 2 || | ||
687 | wrdd->package.elements[0].type != ACPI_TYPE_INTEGER || | ||
688 | wrdd->package.elements[0].integer.value != 0) { | ||
689 | IWL_DEBUG_LAR(mvm, "Unsupported wrdd structure\n"); | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | for (i = 1 ; i < wrdd->package.count ; ++i) { | ||
694 | mcc_pkg = &wrdd->package.elements[i]; | ||
695 | |||
696 | if (mcc_pkg->type != ACPI_TYPE_PACKAGE || | ||
697 | mcc_pkg->package.count < 2 || | ||
698 | mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER || | ||
699 | mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { | ||
700 | mcc_pkg = NULL; | ||
701 | continue; | ||
702 | } | ||
703 | |||
704 | domain_type = &mcc_pkg->package.elements[0]; | ||
705 | if (domain_type->integer.value == WRDD_WIFI) | ||
706 | break; | ||
707 | |||
708 | mcc_pkg = NULL; | ||
709 | } | ||
710 | |||
711 | if (mcc_pkg) { | ||
712 | mcc_value = &mcc_pkg->package.elements[1]; | ||
713 | return mcc_value->integer.value; | ||
714 | } | ||
715 | |||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc) | ||
720 | { | ||
721 | acpi_handle root_handle; | ||
722 | acpi_handle handle; | ||
723 | struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
724 | acpi_status status; | ||
725 | u32 mcc_val; | ||
726 | struct pci_dev *pdev = to_pci_dev(mvm->dev); | ||
727 | |||
728 | root_handle = ACPI_HANDLE(&pdev->dev); | ||
729 | if (!root_handle) { | ||
730 | IWL_DEBUG_LAR(mvm, | ||
731 | "Could not retrieve root port ACPI handle\n"); | ||
732 | return -ENOENT; | ||
733 | } | ||
734 | |||
735 | /* Get the method's handle */ | ||
736 | status = acpi_get_handle(root_handle, (acpi_string)WRD_METHOD, &handle); | ||
737 | if (ACPI_FAILURE(status)) { | ||
738 | IWL_DEBUG_LAR(mvm, "WRD method not found\n"); | ||
739 | return -ENOENT; | ||
740 | } | ||
741 | |||
742 | /* Call WRDD with no arguments */ | ||
743 | status = acpi_evaluate_object(handle, NULL, NULL, &wrdd); | ||
744 | if (ACPI_FAILURE(status)) { | ||
745 | IWL_DEBUG_LAR(mvm, "WRDC invocation failed (0x%x)\n", status); | ||
746 | return -ENOENT; | ||
747 | } | ||
748 | |||
749 | mcc_val = iwl_mvm_wrdd_get_mcc(mvm, wrdd.pointer); | ||
750 | kfree(wrdd.pointer); | ||
751 | if (!mcc_val) | ||
752 | return -ENOENT; | ||
753 | |||
754 | mcc[0] = (mcc_val >> 8) & 0xff; | ||
755 | mcc[1] = mcc_val & 0xff; | ||
756 | mcc[2] = '\0'; | ||
757 | return 0; | ||
758 | } | ||
759 | #else /* CONFIG_ACPI */ | ||
760 | static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc) | ||
761 | { | ||
762 | return -ENOENT; | ||
763 | } | ||
764 | #endif | ||
765 | |||
766 | int iwl_mvm_init_mcc(struct iwl_mvm *mvm) | ||
767 | { | ||
768 | bool tlv_lar; | ||
769 | bool nvm_lar; | ||
770 | int retval; | ||
771 | struct ieee80211_regdomain *regd; | ||
772 | char mcc[3]; | ||
773 | |||
774 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000) { | ||
775 | tlv_lar = mvm->fw->ucode_capa.capa[0] & | ||
776 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT; | ||
777 | nvm_lar = mvm->nvm_data->lar_enabled; | ||
778 | if (tlv_lar != nvm_lar) | ||
779 | IWL_INFO(mvm, | ||
780 | "Conflict between TLV & NVM regarding enabling LAR (TLV = %s NVM =%s)\n", | ||
781 | tlv_lar ? "enabled" : "disabled", | ||
782 | nvm_lar ? "enabled" : "disabled"); | ||
783 | } | ||
784 | |||
785 | if (!iwl_mvm_is_lar_supported(mvm)) | ||
786 | return 0; | ||
787 | |||
788 | /* | ||
789 | * During HW restart, only replay the last set MCC to FW. Otherwise, | ||
790 | * queue an update to cfg80211 to retrieve the default alpha2 from FW. | ||
791 | */ | ||
792 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | ||
793 | /* This should only be called during vif up and hold RTNL */ | ||
794 | return iwl_mvm_init_fw_regd(mvm); | ||
795 | } | ||
796 | |||
797 | /* | ||
798 | * Driver regulatory hint for initial update, this also informs the | ||
799 | * firmware we support wifi location updates. | ||
800 | * Disallow scans that might crash the FW while the LAR regdomain | ||
801 | * is not set. | ||
802 | */ | ||
803 | mvm->lar_regdom_set = false; | ||
804 | |||
805 | regd = iwl_mvm_get_current_regdomain(mvm, NULL); | ||
806 | if (IS_ERR_OR_NULL(regd)) | ||
807 | return -EIO; | ||
808 | |||
809 | if (iwl_mvm_is_wifi_mcc_supported(mvm) && | ||
810 | !iwl_mvm_get_bios_mcc(mvm, mcc)) { | ||
811 | kfree(regd); | ||
812 | regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc, | ||
813 | MCC_SOURCE_BIOS, NULL); | ||
814 | if (IS_ERR_OR_NULL(regd)) | ||
815 | return -EIO; | ||
816 | } | ||
817 | |||
818 | retval = regulatory_set_wiphy_regd_sync_rtnl(mvm->hw->wiphy, regd); | ||
819 | kfree(regd); | ||
820 | return retval; | ||
821 | } | ||
822 | |||
823 | int iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm, | ||
824 | struct iwl_rx_cmd_buffer *rxb, | ||
825 | struct iwl_device_cmd *cmd) | ||
826 | { | ||
827 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
828 | struct iwl_mcc_chub_notif *notif = (void *)pkt->data; | ||
829 | enum iwl_mcc_source src; | ||
830 | char mcc[3]; | ||
831 | struct ieee80211_regdomain *regd; | ||
832 | |||
833 | lockdep_assert_held(&mvm->mutex); | ||
834 | |||
835 | if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm))) | ||
836 | return 0; | ||
837 | |||
838 | mcc[0] = notif->mcc >> 8; | ||
839 | mcc[1] = notif->mcc & 0xff; | ||
840 | mcc[2] = '\0'; | ||
841 | src = notif->source_id; | ||
842 | |||
843 | IWL_DEBUG_LAR(mvm, | ||
844 | "RX: received chub update mcc cmd (mcc '%s' src %d)\n", | ||
845 | mcc, src); | ||
846 | regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc, src, NULL); | ||
847 | if (IS_ERR_OR_NULL(regd)) | ||
848 | return 0; | ||
849 | |||
850 | regulatory_set_wiphy_regd(mvm->hw->wiphy, regd); | ||
851 | kfree(regd); | ||
852 | |||
853 | return 0; | ||
854 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index fe40922a6b0d..80121e41ca22 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -82,7 +82,6 @@ | |||
82 | #include "rs.h" | 82 | #include "rs.h" |
83 | #include "fw-api-scan.h" | 83 | #include "fw-api-scan.h" |
84 | #include "time-event.h" | 84 | #include "time-event.h" |
85 | #include "iwl-fw-error-dump.h" | ||
86 | 85 | ||
87 | #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" | 86 | #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" |
88 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | 87 | MODULE_DESCRIPTION(DRV_DESCRIPTION); |
@@ -234,6 +233,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
234 | iwl_mvm_rx_ant_coupling_notif, true), | 233 | iwl_mvm_rx_ant_coupling_notif, true), |
235 | 234 | ||
236 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), | 235 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), |
236 | RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc, true), | ||
237 | 237 | ||
238 | RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false), | 238 | RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false), |
239 | 239 | ||
@@ -358,6 +358,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
358 | CMD(TDLS_CHANNEL_SWITCH_CMD), | 358 | CMD(TDLS_CHANNEL_SWITCH_CMD), |
359 | CMD(TDLS_CHANNEL_SWITCH_NOTIFICATION), | 359 | CMD(TDLS_CHANNEL_SWITCH_NOTIFICATION), |
360 | CMD(TDLS_CONFIG_CMD), | 360 | CMD(TDLS_CONFIG_CMD), |
361 | CMD(MCC_UPDATE_CMD), | ||
361 | }; | 362 | }; |
362 | #undef CMD | 363 | #undef CMD |
363 | 364 | ||
@@ -871,8 +872,8 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work) | |||
871 | 872 | ||
872 | /* start recording again if the firmware is not crashed */ | 873 | /* start recording again if the firmware is not crashed */ |
873 | WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) && | 874 | WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) && |
874 | mvm->fw->dbg_dest_tlv && | 875 | mvm->fw->dbg_dest_tlv && |
875 | iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf)); | 876 | iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf)); |
876 | 877 | ||
877 | mutex_unlock(&mvm->mutex); | 878 | mutex_unlock(&mvm->mutex); |
878 | 879 | ||
@@ -1270,6 +1271,10 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
1270 | iwl_free_resp(&get_status_cmd); | 1271 | iwl_free_resp(&get_status_cmd); |
1271 | out: | 1272 | out: |
1272 | iwl_mvm_d0i3_enable_tx(mvm, qos_seq); | 1273 | iwl_mvm_d0i3_enable_tx(mvm, qos_seq); |
1274 | |||
1275 | /* the FW might have updated the regdomain */ | ||
1276 | iwl_mvm_update_changed_regdom(mvm); | ||
1277 | |||
1273 | iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK); | 1278 | iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK); |
1274 | mutex_unlock(&mvm->mutex); | 1279 | mutex_unlock(&mvm->mutex); |
1275 | } | 1280 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 33bbdde0046f..d2c6ba9d326b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -358,7 +358,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
358 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 358 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
359 | 359 | ||
360 | if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) || | 360 | if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) || |
361 | !mvmvif->pm_enabled || iwl_mvm_tdls_sta_count(mvm, vif)) | 361 | !mvmvif->pm_enabled) |
362 | return; | 362 | return; |
363 | 363 | ||
364 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | 364 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); |
@@ -639,6 +639,10 @@ static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm, | |||
639 | if (vifs->ap_vif) | 639 | if (vifs->ap_vif) |
640 | ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif); | 640 | ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif); |
641 | 641 | ||
642 | /* don't allow PM if any TDLS stations exist */ | ||
643 | if (iwl_mvm_tdls_sta_count(mvm, NULL)) | ||
644 | return; | ||
645 | |||
642 | /* enable PM on bss if bss stand alone */ | 646 | /* enable PM on bss if bss stand alone */ |
643 | if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) { | 647 | if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) { |
644 | bss_mvmvif->pm_enabled = true; | 648 | bss_mvmvif->pm_enabled = true; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index dbb2594390e9..509a66d05245 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
@@ -172,6 +172,7 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm, | |||
172 | } | 172 | } |
173 | 173 | ||
174 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, | 174 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, |
175 | bool force_update, | ||
175 | struct ieee80211_vif *disabled_vif) | 176 | struct ieee80211_vif *disabled_vif) |
176 | { | 177 | { |
177 | struct iwl_time_quota_cmd cmd = {}; | 178 | struct iwl_time_quota_cmd cmd = {}; |
@@ -309,7 +310,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, | |||
309 | "zero quota on binding %d\n", i); | 310 | "zero quota on binding %d\n", i); |
310 | } | 311 | } |
311 | 312 | ||
312 | if (!send) { | 313 | if (!send && !force_update) { |
313 | /* don't send a practically unchanged command, the firmware has | 314 | /* don't send a practically unchanged command, the firmware has |
314 | * to re-initialize a lot of state and that can have an adverse | 315 | * to re-initialize a lot of state and that can have an adverse |
315 | * impact on it | 316 | * impact on it |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 6578498dd5af..dd457df9601e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -1065,6 +1065,37 @@ static inline bool rs_rate_column_match(struct rs_rate *a, | |||
1065 | && ant_match; | 1065 | && ant_match; |
1066 | } | 1066 | } |
1067 | 1067 | ||
1068 | static inline enum rs_column rs_get_column_from_rate(struct rs_rate *rate) | ||
1069 | { | ||
1070 | if (is_legacy(rate)) { | ||
1071 | if (rate->ant == ANT_A) | ||
1072 | return RS_COLUMN_LEGACY_ANT_A; | ||
1073 | |||
1074 | if (rate->ant == ANT_B) | ||
1075 | return RS_COLUMN_LEGACY_ANT_B; | ||
1076 | |||
1077 | goto err; | ||
1078 | } | ||
1079 | |||
1080 | if (is_siso(rate)) { | ||
1081 | if (rate->ant == ANT_A || rate->stbc || rate->bfer) | ||
1082 | return rate->sgi ? RS_COLUMN_SISO_ANT_A_SGI : | ||
1083 | RS_COLUMN_SISO_ANT_A; | ||
1084 | |||
1085 | if (rate->ant == ANT_B) | ||
1086 | return rate->sgi ? RS_COLUMN_SISO_ANT_B_SGI : | ||
1087 | RS_COLUMN_SISO_ANT_B; | ||
1088 | |||
1089 | goto err; | ||
1090 | } | ||
1091 | |||
1092 | if (is_mimo(rate)) | ||
1093 | return rate->sgi ? RS_COLUMN_MIMO2_SGI : RS_COLUMN_MIMO2; | ||
1094 | |||
1095 | err: | ||
1096 | return RS_COLUMN_INVALID; | ||
1097 | } | ||
1098 | |||
1068 | static u8 rs_get_tid(struct ieee80211_hdr *hdr) | 1099 | static u8 rs_get_tid(struct ieee80211_hdr *hdr) |
1069 | { | 1100 | { |
1070 | u8 tid = IWL_MAX_TID_COUNT; | 1101 | u8 tid = IWL_MAX_TID_COUNT; |
@@ -1106,17 +1137,43 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1106 | return; | 1137 | return; |
1107 | } | 1138 | } |
1108 | 1139 | ||
1140 | /* This packet was aggregated but doesn't carry status info */ | ||
1141 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | ||
1142 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | ||
1143 | return; | ||
1144 | |||
1145 | rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate); | ||
1146 | |||
1109 | #ifdef CONFIG_MAC80211_DEBUGFS | 1147 | #ifdef CONFIG_MAC80211_DEBUGFS |
1110 | /* Disable last tx check if we are debugging with fixed rate */ | 1148 | /* Disable last tx check if we are debugging with fixed rate but |
1149 | * update tx stats */ | ||
1111 | if (lq_sta->pers.dbg_fixed_rate) { | 1150 | if (lq_sta->pers.dbg_fixed_rate) { |
1112 | IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n"); | 1151 | int index = tx_resp_rate.index; |
1152 | enum rs_column column; | ||
1153 | int attempts, success; | ||
1154 | |||
1155 | column = rs_get_column_from_rate(&tx_resp_rate); | ||
1156 | if (WARN_ONCE(column == RS_COLUMN_INVALID, | ||
1157 | "Can't map rate 0x%x to column", | ||
1158 | tx_resp_hwrate)) | ||
1159 | return; | ||
1160 | |||
1161 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { | ||
1162 | attempts = info->status.ampdu_len; | ||
1163 | success = info->status.ampdu_ack_len; | ||
1164 | } else { | ||
1165 | attempts = info->status.rates[0].count; | ||
1166 | success = !!(info->flags & IEEE80211_TX_STAT_ACK); | ||
1167 | } | ||
1168 | |||
1169 | lq_sta->pers.tx_stats[column][index].total += attempts; | ||
1170 | lq_sta->pers.tx_stats[column][index].success += success; | ||
1171 | |||
1172 | IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n", | ||
1173 | tx_resp_hwrate, success, attempts); | ||
1113 | return; | 1174 | return; |
1114 | } | 1175 | } |
1115 | #endif | 1176 | #endif |
1116 | /* This packet was aggregated but doesn't carry status info */ | ||
1117 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | ||
1118 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | ||
1119 | return; | ||
1120 | 1177 | ||
1121 | if (time_after(jiffies, | 1178 | if (time_after(jiffies, |
1122 | (unsigned long)(lq_sta->last_tx + | 1179 | (unsigned long)(lq_sta->last_tx + |
@@ -1142,7 +1199,6 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1142 | table = &lq_sta->lq; | 1199 | table = &lq_sta->lq; |
1143 | lq_hwrate = le32_to_cpu(table->rs_table[0]); | 1200 | lq_hwrate = le32_to_cpu(table->rs_table[0]); |
1144 | rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate); | 1201 | rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate); |
1145 | rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate); | ||
1146 | 1202 | ||
1147 | /* Here we actually compare this rate to the latest LQ command */ | 1203 | /* Here we actually compare this rate to the latest LQ command */ |
1148 | if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) { | 1204 | if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) { |
@@ -3343,16 +3399,16 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3343 | (is_legacy(rate)) ? "legacy" : | 3399 | (is_legacy(rate)) ? "legacy" : |
3344 | is_vht(rate) ? "VHT" : "HT"); | 3400 | is_vht(rate) ? "VHT" : "HT"); |
3345 | if (!is_legacy(rate)) { | 3401 | if (!is_legacy(rate)) { |
3346 | desc += sprintf(buff+desc, " %s", | 3402 | desc += sprintf(buff + desc, " %s", |
3347 | (is_siso(rate)) ? "SISO" : "MIMO2"); | 3403 | (is_siso(rate)) ? "SISO" : "MIMO2"); |
3348 | desc += sprintf(buff+desc, " %s", | 3404 | desc += sprintf(buff + desc, " %s", |
3349 | (is_ht20(rate)) ? "20MHz" : | 3405 | (is_ht20(rate)) ? "20MHz" : |
3350 | (is_ht40(rate)) ? "40MHz" : | 3406 | (is_ht40(rate)) ? "40MHz" : |
3351 | (is_ht80(rate)) ? "80Mhz" : "BAD BW"); | 3407 | (is_ht80(rate)) ? "80Mhz" : "BAD BW"); |
3352 | desc += sprintf(buff+desc, " %s %s %s\n", | 3408 | desc += sprintf(buff + desc, " %s %s %s\n", |
3353 | (rate->sgi) ? "SGI" : "NGI", | 3409 | (rate->sgi) ? "SGI" : "NGI", |
3354 | (rate->ldpc) ? "LDPC" : "BCC", | 3410 | (rate->ldpc) ? "LDPC" : "BCC", |
3355 | (lq_sta->is_agg) ? "AGG on" : ""); | 3411 | (lq_sta->is_agg) ? "AGG on" : ""); |
3356 | } | 3412 | } |
3357 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", | 3413 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", |
3358 | lq_sta->last_rate_n_flags); | 3414 | lq_sta->last_rate_n_flags); |
@@ -3373,13 +3429,13 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3373 | ss_params = le32_to_cpu(lq_sta->lq.ss_params); | 3429 | ss_params = le32_to_cpu(lq_sta->lq.ss_params); |
3374 | desc += sprintf(buff+desc, "single stream params: %s%s%s%s\n", | 3430 | desc += sprintf(buff+desc, "single stream params: %s%s%s%s\n", |
3375 | (ss_params & LQ_SS_PARAMS_VALID) ? | 3431 | (ss_params & LQ_SS_PARAMS_VALID) ? |
3376 | "VALID," : "INVALID", | 3432 | "VALID" : "INVALID", |
3377 | (ss_params & LQ_SS_BFER_ALLOWED) ? | 3433 | (ss_params & LQ_SS_BFER_ALLOWED) ? |
3378 | "BFER," : "", | 3434 | ", BFER" : "", |
3379 | (ss_params & LQ_SS_STBC_1SS_ALLOWED) ? | 3435 | (ss_params & LQ_SS_STBC_1SS_ALLOWED) ? |
3380 | "STBC," : "", | 3436 | ", STBC" : "", |
3381 | (ss_params & LQ_SS_FORCE) ? | 3437 | (ss_params & LQ_SS_FORCE) ? |
3382 | "FORCE" : ""); | 3438 | ", FORCE" : ""); |
3383 | desc += sprintf(buff+desc, | 3439 | desc += sprintf(buff+desc, |
3384 | "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n", | 3440 | "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n", |
3385 | lq_sta->lq.initial_rate_index[0], | 3441 | lq_sta->lq.initial_rate_index[0], |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index 7eb78e2c240a..b0f59fdd287c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c | |||
@@ -99,7 +99,35 @@ static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac, | |||
99 | 99 | ||
100 | /* | 100 | /* |
101 | * Aging and idle timeouts for the different possible scenarios | 101 | * Aging and idle timeouts for the different possible scenarios |
102 | * in SF_FULL_ON state. | 102 | * in default configuration |
103 | */ | ||
104 | static const | ||
105 | __le32 sf_full_timeout_def[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = { | ||
106 | { | ||
107 | cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER_DEF), | ||
108 | cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER_DEF) | ||
109 | }, | ||
110 | { | ||
111 | cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER_DEF), | ||
112 | cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER_DEF) | ||
113 | }, | ||
114 | { | ||
115 | cpu_to_le32(SF_MCAST_AGING_TIMER_DEF), | ||
116 | cpu_to_le32(SF_MCAST_IDLE_TIMER_DEF) | ||
117 | }, | ||
118 | { | ||
119 | cpu_to_le32(SF_BA_AGING_TIMER_DEF), | ||
120 | cpu_to_le32(SF_BA_IDLE_TIMER_DEF) | ||
121 | }, | ||
122 | { | ||
123 | cpu_to_le32(SF_TX_RE_AGING_TIMER_DEF), | ||
124 | cpu_to_le32(SF_TX_RE_IDLE_TIMER_DEF) | ||
125 | }, | ||
126 | }; | ||
127 | |||
128 | /* | ||
129 | * Aging and idle timeouts for the different possible scenarios | ||
130 | * in single BSS MAC configuration. | ||
103 | */ | 131 | */ |
104 | static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = { | 132 | static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = { |
105 | { | 133 | { |
@@ -124,7 +152,8 @@ static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = { | |||
124 | }, | 152 | }, |
125 | }; | 153 | }; |
126 | 154 | ||
127 | static void iwl_mvm_fill_sf_command(struct iwl_sf_cfg_cmd *sf_cmd, | 155 | static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm, |
156 | struct iwl_sf_cfg_cmd *sf_cmd, | ||
128 | struct ieee80211_sta *sta) | 157 | struct ieee80211_sta *sta) |
129 | { | 158 | { |
130 | int i, j, watermark; | 159 | int i, j, watermark; |
@@ -163,24 +192,38 @@ static void iwl_mvm_fill_sf_command(struct iwl_sf_cfg_cmd *sf_cmd, | |||
163 | cpu_to_le32(SF_LONG_DELAY_AGING_TIMER); | 192 | cpu_to_le32(SF_LONG_DELAY_AGING_TIMER); |
164 | } | 193 | } |
165 | } | 194 | } |
166 | BUILD_BUG_ON(sizeof(sf_full_timeout) != | ||
167 | sizeof(__le32) * SF_NUM_SCENARIO * SF_NUM_TIMEOUT_TYPES); | ||
168 | 195 | ||
169 | memcpy(sf_cmd->full_on_timeouts, sf_full_timeout, | 196 | if (sta || IWL_UCODE_API(mvm->fw->ucode_ver) < 13) { |
170 | sizeof(sf_full_timeout)); | 197 | BUILD_BUG_ON(sizeof(sf_full_timeout) != |
198 | sizeof(__le32) * SF_NUM_SCENARIO * | ||
199 | SF_NUM_TIMEOUT_TYPES); | ||
200 | |||
201 | memcpy(sf_cmd->full_on_timeouts, sf_full_timeout, | ||
202 | sizeof(sf_full_timeout)); | ||
203 | } else { | ||
204 | BUILD_BUG_ON(sizeof(sf_full_timeout_def) != | ||
205 | sizeof(__le32) * SF_NUM_SCENARIO * | ||
206 | SF_NUM_TIMEOUT_TYPES); | ||
207 | |||
208 | memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def, | ||
209 | sizeof(sf_full_timeout_def)); | ||
210 | } | ||
211 | |||
171 | } | 212 | } |
172 | 213 | ||
173 | static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, | 214 | static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, |
174 | enum iwl_sf_state new_state) | 215 | enum iwl_sf_state new_state) |
175 | { | 216 | { |
176 | struct iwl_sf_cfg_cmd sf_cmd = { | 217 | struct iwl_sf_cfg_cmd sf_cmd = { |
177 | .state = cpu_to_le32(new_state), | 218 | .state = cpu_to_le32(SF_FULL_ON), |
178 | }; | 219 | }; |
179 | struct ieee80211_sta *sta; | 220 | struct ieee80211_sta *sta; |
180 | int ret = 0; | 221 | int ret = 0; |
181 | 222 | ||
182 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF && | 223 | if (IWL_UCODE_API(mvm->fw->ucode_ver) < 13) |
183 | mvm->cfg->disable_dummy_notification) | 224 | sf_cmd.state = cpu_to_le32(new_state); |
225 | |||
226 | if (mvm->cfg->disable_dummy_notification) | ||
184 | sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF); | 227 | sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF); |
185 | 228 | ||
186 | /* | 229 | /* |
@@ -192,6 +235,8 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, | |||
192 | 235 | ||
193 | switch (new_state) { | 236 | switch (new_state) { |
194 | case SF_UNINIT: | 237 | case SF_UNINIT: |
238 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 13) | ||
239 | iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL); | ||
195 | break; | 240 | break; |
196 | case SF_FULL_ON: | 241 | case SF_FULL_ON: |
197 | if (sta_id == IWL_MVM_STATION_COUNT) { | 242 | if (sta_id == IWL_MVM_STATION_COUNT) { |
@@ -206,11 +251,11 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, | |||
206 | rcu_read_unlock(); | 251 | rcu_read_unlock(); |
207 | return -EINVAL; | 252 | return -EINVAL; |
208 | } | 253 | } |
209 | iwl_mvm_fill_sf_command(&sf_cmd, sta); | 254 | iwl_mvm_fill_sf_command(mvm, &sf_cmd, sta); |
210 | rcu_read_unlock(); | 255 | rcu_read_unlock(); |
211 | break; | 256 | break; |
212 | case SF_INIT_OFF: | 257 | case SF_INIT_OFF: |
213 | iwl_mvm_fill_sf_command(&sf_cmd, NULL); | 258 | iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL); |
214 | break; | 259 | break; |
215 | default: | 260 | default: |
216 | WARN_ONCE(1, "Invalid state: %d. not sending Smart Fifo cmd\n", | 261 | WARN_ONCE(1, "Invalid state: %d. not sending Smart Fifo cmd\n", |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 5c23cddaaae3..50f9288368af 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -273,7 +273,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
273 | else | 273 | else |
274 | sta_id = mvm_sta->sta_id; | 274 | sta_id = mvm_sta->sta_id; |
275 | 275 | ||
276 | if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT)) | 276 | if (sta_id == IWL_MVM_STATION_COUNT) |
277 | return -ENOSPC; | 277 | return -ENOSPC; |
278 | 278 | ||
279 | spin_lock_init(&mvm_sta->lock); | 279 | spin_lock_init(&mvm_sta->lock); |
@@ -1681,9 +1681,6 @@ void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, | |||
1681 | }; | 1681 | }; |
1682 | int ret; | 1682 | int ret; |
1683 | 1683 | ||
1684 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_DISABLE_STA_TX)) | ||
1685 | return; | ||
1686 | |||
1687 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); | 1684 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); |
1688 | if (ret) | 1685 | if (ret) |
1689 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | 1686 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index f8d6f306dd76..8d179ab67cc2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -197,6 +197,8 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm, | |||
197 | struct iwl_time_event_notif *notif) | 197 | struct iwl_time_event_notif *notif) |
198 | { | 198 | { |
199 | if (!le32_to_cpu(notif->status)) { | 199 | if (!le32_to_cpu(notif->status)) { |
200 | if (te_data->vif->type == NL80211_IFTYPE_STATION) | ||
201 | ieee80211_connection_loss(te_data->vif); | ||
200 | IWL_DEBUG_TE(mvm, "CSA time event failed to start\n"); | 202 | IWL_DEBUG_TE(mvm, "CSA time event failed to start\n"); |
201 | iwl_mvm_te_clear_data(mvm, te_data); | 203 | iwl_mvm_te_clear_data(mvm, te_data); |
202 | return; | 204 | return; |
@@ -261,17 +263,23 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
261 | "TE ended - current time %lu, estimated end %lu\n", | 263 | "TE ended - current time %lu, estimated end %lu\n", |
262 | jiffies, te_data->end_jiffies); | 264 | jiffies, te_data->end_jiffies); |
263 | 265 | ||
264 | if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { | 266 | switch (te_data->vif->type) { |
267 | case NL80211_IFTYPE_P2P_DEVICE: | ||
265 | ieee80211_remain_on_channel_expired(mvm->hw); | 268 | ieee80211_remain_on_channel_expired(mvm->hw); |
266 | iwl_mvm_roc_finished(mvm); | 269 | iwl_mvm_roc_finished(mvm); |
270 | break; | ||
271 | case NL80211_IFTYPE_STATION: | ||
272 | /* | ||
273 | * By now, we should have finished association | ||
274 | * and know the dtim period. | ||
275 | */ | ||
276 | iwl_mvm_te_check_disconnect(mvm, te_data->vif, | ||
277 | "No association and the time event is over already..."); | ||
278 | break; | ||
279 | default: | ||
280 | break; | ||
267 | } | 281 | } |
268 | 282 | ||
269 | /* | ||
270 | * By now, we should have finished association | ||
271 | * and know the dtim period. | ||
272 | */ | ||
273 | iwl_mvm_te_check_disconnect(mvm, te_data->vif, | ||
274 | "No association and the time event is over already..."); | ||
275 | iwl_mvm_te_clear_data(mvm, te_data); | 283 | iwl_mvm_te_clear_data(mvm, te_data); |
276 | } else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) { | 284 | } else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) { |
277 | te_data->running = true; | 285 | te_data->running = true; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 2b9de63951e6..435faee0a28e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -857,7 +857,7 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
857 | 857 | ||
858 | mvmvif->low_latency = value; | 858 | mvmvif->low_latency = value; |
859 | 859 | ||
860 | res = iwl_mvm_update_quotas(mvm, NULL); | 860 | res = iwl_mvm_update_quotas(mvm, false, NULL); |
861 | if (res) | 861 | if (res) |
862 | return res; | 862 | return res; |
863 | 863 | ||