iwlwifi: mvm: support CHANNEL_SWITCH_TIME_EVENT_CMD command
[linux-2.6-block.git] / drivers / net / wireless / intel / iwlwifi / mvm / mac-ctxt.c
CommitLineData
8ca151b5
JB
1/******************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
51368bf7 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
8b4139dc 9 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
09856582 10 * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
86e177d8 11 * Copyright(c) 2018 Intel Corporation
8ca151b5
JB
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of version 2 of the GNU General Public License as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
8ca151b5 22 * The full GNU General Public License is included in this distribution
410dc5aa 23 * in the file called COPYING.
8ca151b5
JB
24 *
25 * Contact Information:
cb2f8277 26 * Intel Linux Wireless <linuxwifi@intel.com>
8ca151b5
JB
27 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
28 *
29 * BSD LICENSE
30 *
51368bf7 31 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
8b4139dc 32 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
09856582 33 * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
86e177d8 34 * Copyright(c) 2018 Intel Corporation
8ca151b5
JB
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 *
41 * * Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * * Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in
45 * the documentation and/or other materials provided with the
46 * distribution.
47 * * Neither the name Intel Corporation nor the names of its
48 * contributors may be used to endorse or promote products derived
49 * from this software without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
52 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
53 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
54 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
55 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
56 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
57 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
61 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 *
63 *****************************************************************************/
64
65#include <linux/etherdevice.h>
66#include <net/mac80211.h>
67#include "iwl-io.h"
68#include "iwl-prph.h"
69#include "fw-api.h"
70#include "mvm.h"
7f0a7c67 71#include "time-event.h"
8ca151b5
JB
72
73const u8 iwl_mvm_ac_to_tx_fifo[] = {
8ca151b5 74 IWL_MVM_TX_FIFO_VO,
3dd94794
EG
75 IWL_MVM_TX_FIFO_VI,
76 IWL_MVM_TX_FIFO_BE,
77 IWL_MVM_TX_FIFO_BK,
8ca151b5
JB
78};
79
cf6c6ea3
EG
80const u8 iwl_mvm_ac_to_gen2_tx_fifo[] = {
81 IWL_GEN2_EDCA_TX_FIFO_VO,
82 IWL_GEN2_EDCA_TX_FIFO_VI,
83 IWL_GEN2_EDCA_TX_FIFO_BE,
84 IWL_GEN2_EDCA_TX_FIFO_BK,
7126b6f2
SS
85 IWL_GEN2_TRIG_TX_FIFO_VO,
86 IWL_GEN2_TRIG_TX_FIFO_VI,
87 IWL_GEN2_TRIG_TX_FIFO_BE,
88 IWL_GEN2_TRIG_TX_FIFO_BK,
cf6c6ea3
EG
89};
90
8ca151b5
JB
91struct iwl_mvm_mac_iface_iterator_data {
92 struct iwl_mvm *mvm;
93 struct ieee80211_vif *vif;
94 unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)];
95 unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)];
8ca151b5
JB
96 enum iwl_tsf_id preferred_tsf;
97 bool found_vif;
98};
99
6e97b0d2
IP
100static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
101 struct ieee80211_vif *vif)
8ca151b5
JB
102{
103 struct iwl_mvm_mac_iface_iterator_data *data = _data;
104 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
2c3e62a1 105 u16 min_bi;
8ca151b5 106
6e97b0d2
IP
107 /* Skip the interface for which we are trying to assign a tsf_id */
108 if (vif == data->vif)
8ca151b5 109 return;
8ca151b5
JB
110
111 /*
112 * The TSF is a hardware/firmware resource, there are 4 and
113 * the driver should assign and free them as needed. However,
114 * there are cases where 2 MACs should share the same TSF ID
115 * for the purpose of clock sync, an optimization to avoid
116 * clock drift causing overlapping TBTTs/DTIMs for a GO and
117 * client in the system.
118 *
119 * The firmware will decide according to the MAC type which
120 * will be the master and slave. Clients that need to sync
121 * with a remote station will be the master, and an AP or GO
122 * will be the slave.
123 *
124 * Depending on the new interface type it can be slaved to
125 * or become the master of an existing interface.
126 */
127 switch (data->vif->type) {
128 case NL80211_IFTYPE_STATION:
129 /*
2c3e62a1
IP
130 * The new interface is a client, so if the one we're iterating
131 * is an AP, and the beacon interval of the AP is a multiple or
132 * divisor of the beacon interval of the client, the same TSF
133 * should be used to avoid drift between the new client and
134 * existing AP. The existing AP will get drift updates from the
135 * new client context in this case.
8ca151b5 136 */
2c3e62a1
IP
137 if (vif->type != NL80211_IFTYPE_AP ||
138 data->preferred_tsf != NUM_TSF_IDS ||
139 !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
140 break;
141
142 min_bi = min(data->vif->bss_conf.beacon_int,
143 vif->bss_conf.beacon_int);
144
145 if (!min_bi)
146 break;
147
148 if ((data->vif->bss_conf.beacon_int -
149 vif->bss_conf.beacon_int) % min_bi == 0) {
150 data->preferred_tsf = mvmvif->tsf_id;
151 return;
8ca151b5
JB
152 }
153 break;
2c3e62a1 154
8ca151b5
JB
155 case NL80211_IFTYPE_AP:
156 /*
2c3e62a1
IP
157 * The new interface is AP/GO, so if its beacon interval is a
158 * multiple or a divisor of the beacon interval of an existing
159 * interface, it should get drift updates from an existing
160 * client or use the same TSF as an existing GO. There's no
161 * drift between TSFs internally but if they used different
162 * TSFs then a new client MAC could update one of them and
163 * cause drift that way.
8ca151b5 164 */
2c3e62a1
IP
165 if ((vif->type != NL80211_IFTYPE_AP &&
166 vif->type != NL80211_IFTYPE_STATION) ||
167 data->preferred_tsf != NUM_TSF_IDS ||
168 !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
169 break;
170
171 min_bi = min(data->vif->bss_conf.beacon_int,
172 vif->bss_conf.beacon_int);
173
174 if (!min_bi)
175 break;
176
177 if ((data->vif->bss_conf.beacon_int -
178 vif->bss_conf.beacon_int) % min_bi == 0) {
179 data->preferred_tsf = mvmvif->tsf_id;
180 return;
8ca151b5
JB
181 }
182 break;
183 default:
184 /*
185 * For all other interface types there's no need to
186 * take drift into account. Either they're exclusive
187 * like IBSS and monitor, or we don't care much about
188 * their TSF (like P2P Device), but we won't be able
189 * to share the TSF resource.
190 */
191 break;
192 }
193
194 /*
195 * Unless we exited above, we can't share the TSF resource
196 * that the virtual interface we're iterating over is using
197 * with the new one, so clear the available bit and if this
198 * was the preferred one, reset that as well.
199 */
200 __clear_bit(mvmvif->tsf_id, data->available_tsf_ids);
201
202 if (data->preferred_tsf == mvmvif->tsf_id)
203 data->preferred_tsf = NUM_TSF_IDS;
204}
205
6e97b0d2
IP
206static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
207 struct ieee80211_vif *vif)
208{
209 struct iwl_mvm_mac_iface_iterator_data *data = _data;
210 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
6e97b0d2
IP
211
212 /* Iterator may already find the interface being added -- skip it */
213 if (vif == data->vif) {
214 data->found_vif = true;
215 return;
216 }
217
6e97b0d2
IP
218 /* Mark MAC IDs as used by clearing the available bit, and
219 * (below) mark TSFs as used if their existing use is not
220 * compatible with the new interface type.
221 * No locking or atomic bit operations are needed since the
222 * data is on the stack of the caller function.
223 */
224 __clear_bit(mvmvif->id, data->available_mac_ids);
225
226 /* find a suitable tsf_id */
227 iwl_mvm_mac_tsf_id_iter(_data, mac, vif);
228}
229
6e97b0d2
IP
230void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
231 struct ieee80211_vif *vif)
232{
233 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
234 struct iwl_mvm_mac_iface_iterator_data data = {
235 .mvm = mvm,
236 .vif = vif,
237 .available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
238 /* no preference yet */
239 .preferred_tsf = NUM_TSF_IDS,
240 };
241
242 ieee80211_iterate_active_interfaces_atomic(
243 mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
244 iwl_mvm_mac_tsf_id_iter, &data);
245
246 if (data.preferred_tsf != NUM_TSF_IDS)
247 mvmvif->tsf_id = data.preferred_tsf;
248 else if (!test_bit(mvmvif->tsf_id, data.available_tsf_ids))
249 mvmvif->tsf_id = find_first_bit(data.available_tsf_ids,
250 NUM_TSF_IDS);
251}
252
c8f54701 253int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
8ca151b5
JB
254{
255 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
256 struct iwl_mvm_mac_iface_iterator_data data = {
257 .mvm = mvm,
258 .vif = vif,
259 .available_mac_ids = { (1 << NUM_MAC_INDEX_DRIVER) - 1 },
260 .available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
261 /* no preference yet */
262 .preferred_tsf = NUM_TSF_IDS,
8ca151b5
JB
263 .found_vif = false,
264 };
265 u32 ac;
32026e8f 266 int ret, i, queue_limit;
110cf810 267 unsigned long used_hw_queues;
8ca151b5 268
c8f54701
JB
269 lockdep_assert_held(&mvm->mutex);
270
8ca151b5
JB
271 /*
272 * Allocate a MAC ID and a TSF for this MAC, along with the queues
273 * and other resources.
274 */
275
276 /*
277 * Before the iterator, we start with all MAC IDs and TSFs available.
278 *
279 * During iteration, all MAC IDs are cleared that are in use by other
280 * virtual interfaces, and all TSF IDs are cleared that can't be used
281 * by this new virtual interface because they're used by an interface
282 * that can't share it with the new one.
283 * At the same time, we check if there's a preferred TSF in the case
284 * that we should share it with another interface.
285 */
286
5023d966
JB
287 /* Currently, MAC ID 0 should be used only for the managed/IBSS vif */
288 switch (vif->type) {
289 case NL80211_IFTYPE_ADHOC:
290 break;
291 case NL80211_IFTYPE_STATION:
292 if (!vif->p2p)
293 break;
294 /* fall through */
295 default:
ec8b6885 296 __clear_bit(0, data.available_mac_ids);
5023d966 297 }
ec8b6885 298
8ca151b5
JB
299 ieee80211_iterate_active_interfaces_atomic(
300 mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
301 iwl_mvm_mac_iface_iterator, &data);
302
303 /*
304 * In the case we're getting here during resume, it's similar to
305 * firmware restart, and with RESUME_ALL the iterator will find
306 * the vif being added already.
307 * We don't want to reassign any IDs in either case since doing
308 * so would probably assign different IDs (as interfaces aren't
309 * necessarily added in the same order), but the old IDs were
310 * preserved anyway, so skip ID assignment for both resume and
311 * recovery.
312 */
313 if (data.found_vif)
314 return 0;
315
316 /* Therefore, in recovery, we can't get here */
fd11bd05
IP
317 if (WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
318 return -EBUSY;
8ca151b5
JB
319
320 mvmvif->id = find_first_bit(data.available_mac_ids,
321 NUM_MAC_INDEX_DRIVER);
322 if (mvmvif->id == NUM_MAC_INDEX_DRIVER) {
323 IWL_ERR(mvm, "Failed to init MAC context - no free ID!\n");
324 ret = -EIO;
325 goto exit_fail;
326 }
327
328 if (data.preferred_tsf != NUM_TSF_IDS)
329 mvmvif->tsf_id = data.preferred_tsf;
330 else
331 mvmvif->tsf_id = find_first_bit(data.available_tsf_ids,
332 NUM_TSF_IDS);
333 if (mvmvif->tsf_id == NUM_TSF_IDS) {
334 IWL_ERR(mvm, "Failed to init MAC context - no free TSF!\n");
335 ret = -EIO;
336 goto exit_fail;
337 }
338
339 mvmvif->color = 0;
340
1e849c93
IP
341 INIT_LIST_HEAD(&mvmvif->time_event_data.list);
342 mvmvif->time_event_data.id = TE_MAX;
343
8ca151b5
JB
344 /* No need to allocate data queues to P2P Device MAC.*/
345 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
346 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
347 vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE;
348
349 return 0;
350 }
351
c8f54701
JB
352 /*
353 * queues in mac80211 almost entirely independent of
354 * the ones here - no real limit
355 */
356 queue_limit = IEEE80211_MAX_QUEUES;
32026e8f 357
24afba76
LK
358 /*
359 * Find available queues, and allocate them to the ACs. When in
360 * DQA-mode they aren't really used, and this is done only so the
361 * mac80211 ieee80211_check_queues() function won't fail
362 */
8ca151b5 363 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
32026e8f 364 u8 queue = find_first_zero_bit(&used_hw_queues, queue_limit);
8ca151b5 365
32026e8f 366 if (queue >= queue_limit) {
8ca151b5
JB
367 IWL_ERR(mvm, "Failed to allocate queue\n");
368 ret = -EIO;
369 goto exit_fail;
370 }
371
110cf810 372 __set_bit(queue, &used_hw_queues);
8ca151b5
JB
373 vif->hw_queue[ac] = queue;
374 }
375
376 /* Allocate the CAB queue for softAP and GO interfaces */
fc07bd8c
SS
377 if (vif->type == NL80211_IFTYPE_AP ||
378 vif->type == NL80211_IFTYPE_ADHOC) {
e2af3fab
SS
379 /*
380 * For TVQM this will be overwritten later with the FW assigned
381 * queue value (when queue is enabled).
382 */
c8f54701 383 mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
8ca151b5
JB
384 }
385
0ae98812
SS
386 mvmvif->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
387 mvmvif->mcast_sta.sta_id = IWL_MVM_INVALID_STA;
388 mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
8ca151b5 389
9ee718aa
EL
390 for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
391 mvmvif->smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
392
8ca151b5
JB
393 return 0;
394
395exit_fail:
396 memset(mvmvif, 0, sizeof(struct iwl_mvm_vif));
8ca151b5
JB
397 return ret;
398}
399
8ca151b5
JB
400static void iwl_mvm_ack_rates(struct iwl_mvm *mvm,
401 struct ieee80211_vif *vif,
57fbcce3 402 enum nl80211_band band,
8ca151b5
JB
403 u8 *cck_rates, u8 *ofdm_rates)
404{
405 struct ieee80211_supported_band *sband;
406 unsigned long basic = vif->bss_conf.basic_rates;
407 int lowest_present_ofdm = 100;
408 int lowest_present_cck = 100;
409 u8 cck = 0;
410 u8 ofdm = 0;
411 int i;
412
413 sband = mvm->hw->wiphy->bands[band];
414
415 for_each_set_bit(i, &basic, BITS_PER_LONG) {
416 int hw = sband->bitrates[i].hw_value;
417 if (hw >= IWL_FIRST_OFDM_RATE) {
418 ofdm |= BIT(hw - IWL_FIRST_OFDM_RATE);
419 if (lowest_present_ofdm > hw)
420 lowest_present_ofdm = hw;
421 } else {
422 BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
423
424 cck |= BIT(hw);
425 if (lowest_present_cck > hw)
426 lowest_present_cck = hw;
427 }
428 }
429
430 /*
431 * Now we've got the basic rates as bitmaps in the ofdm and cck
432 * variables. This isn't sufficient though, as there might not
433 * be all the right rates in the bitmap. E.g. if the only basic
434 * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
435 * and 6 Mbps because the 802.11-2007 standard says in 9.6:
436 *
437 * [...] a STA responding to a received frame shall transmit
438 * its Control Response frame [...] at the highest rate in the
439 * BSSBasicRateSet parameter that is less than or equal to the
440 * rate of the immediately previous frame in the frame exchange
441 * sequence ([...]) and that is of the same modulation class
442 * ([...]) as the received frame. If no rate contained in the
443 * BSSBasicRateSet parameter meets these conditions, then the
444 * control frame sent in response to a received frame shall be
445 * transmitted at the highest mandatory rate of the PHY that is
446 * less than or equal to the rate of the received frame, and
447 * that is of the same modulation class as the received frame.
448 *
449 * As a consequence, we need to add all mandatory rates that are
450 * lower than all of the basic rates to these bitmaps.
451 */
452
453 if (IWL_RATE_24M_INDEX < lowest_present_ofdm)
454 ofdm |= IWL_RATE_BIT_MSK(24) >> IWL_FIRST_OFDM_RATE;
455 if (IWL_RATE_12M_INDEX < lowest_present_ofdm)
456 ofdm |= IWL_RATE_BIT_MSK(12) >> IWL_FIRST_OFDM_RATE;
457 /* 6M already there or needed so always add */
458 ofdm |= IWL_RATE_BIT_MSK(6) >> IWL_FIRST_OFDM_RATE;
459
460 /*
461 * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
462 * Note, however:
463 * - if no CCK rates are basic, it must be ERP since there must
464 * be some basic rates at all, so they're OFDM => ERP PHY
465 * (or we're in 5 GHz, and the cck bitmap will never be used)
466 * - if 11M is a basic rate, it must be ERP as well, so add 5.5M
467 * - if 5.5M is basic, 1M and 2M are mandatory
468 * - if 2M is basic, 1M is mandatory
469 * - if 1M is basic, that's the only valid ACK rate.
470 * As a consequence, it's not as complicated as it sounds, just add
471 * any lower rates to the ACK rate bitmap.
472 */
473 if (IWL_RATE_11M_INDEX < lowest_present_cck)
474 cck |= IWL_RATE_BIT_MSK(11) >> IWL_FIRST_CCK_RATE;
475 if (IWL_RATE_5M_INDEX < lowest_present_cck)
476 cck |= IWL_RATE_BIT_MSK(5) >> IWL_FIRST_CCK_RATE;
477 if (IWL_RATE_2M_INDEX < lowest_present_cck)
478 cck |= IWL_RATE_BIT_MSK(2) >> IWL_FIRST_CCK_RATE;
479 /* 1M already there or needed so always add */
480 cck |= IWL_RATE_BIT_MSK(1) >> IWL_FIRST_CCK_RATE;
481
482 *cck_rates = cck;
483 *ofdm_rates = ofdm;
484}
485
8a5e3660
AA
486static void iwl_mvm_mac_ctxt_set_ht_flags(struct iwl_mvm *mvm,
487 struct ieee80211_vif *vif,
488 struct iwl_mac_ctx_cmd *cmd)
489{
490 /* for both sta and ap, ht_operation_mode hold the protection_mode */
491 u8 protection_mode = vif->bss_conf.ht_operation_mode &
492 IEEE80211_HT_OP_MODE_PROTECTION;
493 /* The fw does not distinguish between ht and fat */
494 u32 ht_flag = MAC_PROT_FLG_HT_PROT | MAC_PROT_FLG_FAT_PROT;
495
496 IWL_DEBUG_RATE(mvm, "protection mode set to %d\n", protection_mode);
497 /*
498 * See section 9.23.3.1 of IEEE 80211-2012.
499 * Nongreenfield HT STAs Present is not supported.
500 */
501 switch (protection_mode) {
502 case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
503 break;
504 case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
505 case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
506 cmd->protection_flags |= cpu_to_le32(ht_flag);
507 break;
508 case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
509 /* Protect when channel wider than 20MHz */
510 if (vif->bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
511 cmd->protection_flags |= cpu_to_le32(ht_flag);
512 break;
513 default:
514 IWL_ERR(mvm, "Illegal protection mode %d\n",
515 protection_mode);
516 break;
517 }
518}
519
8ca151b5
JB
520static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
521 struct ieee80211_vif *vif,
522 struct iwl_mac_ctx_cmd *cmd,
3dfd3a97 523 const u8 *bssid_override,
8ca151b5
JB
524 u32 action)
525{
526 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
527 struct ieee80211_chanctx_conf *chanctx;
8a5e3660
AA
528 bool ht_enabled = !!(vif->bss_conf.ht_operation_mode &
529 IEEE80211_HT_OP_MODE_PROTECTION);
8ca151b5 530 u8 cck_ack_rates, ofdm_ack_rates;
3dfd3a97 531 const u8 *bssid = bssid_override ?: vif->bss_conf.bssid;
8ca151b5
JB
532 int i;
533
534 cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
535 mvmvif->color));
536 cmd->action = cpu_to_le32(action);
537
538 switch (vif->type) {
539 case NL80211_IFTYPE_STATION:
540 if (vif->p2p)
541 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_STA);
542 else
543 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_BSS_STA);
544 break;
545 case NL80211_IFTYPE_AP:
546 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_GO);
547 break;
548 case NL80211_IFTYPE_MONITOR:
549 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_LISTENER);
550 break;
551 case NL80211_IFTYPE_P2P_DEVICE:
552 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_DEVICE);
553 break;
554 case NL80211_IFTYPE_ADHOC:
555 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_IBSS);
556 break;
557 default:
558 WARN_ON_ONCE(1);
559 }
560
561 cmd->tsf_id = cpu_to_le32(mvmvif->tsf_id);
562
563 memcpy(cmd->node_addr, vif->addr, ETH_ALEN);
3dfd3a97
JB
564
565 if (bssid)
566 memcpy(cmd->bssid_addr, bssid, ETH_ALEN);
8ca151b5
JB
567 else
568 eth_broadcast_addr(cmd->bssid_addr);
569
570 rcu_read_lock();
571 chanctx = rcu_dereference(vif->chanctx_conf);
572 iwl_mvm_ack_rates(mvm, vif, chanctx ? chanctx->def.chan->band
57fbcce3 573 : NL80211_BAND_2GHZ,
8ca151b5
JB
574 &cck_ack_rates, &ofdm_ack_rates);
575 rcu_read_unlock();
576
577 cmd->cck_rates = cpu_to_le32((u32)cck_ack_rates);
578 cmd->ofdm_rates = cpu_to_le32((u32)ofdm_ack_rates);
579
580 cmd->cck_short_preamble =
581 cpu_to_le32(vif->bss_conf.use_short_preamble ?
582 MAC_FLG_SHORT_PREAMBLE : 0);
583 cmd->short_slot =
584 cpu_to_le32(vif->bss_conf.use_short_slot ?
585 MAC_FLG_SHORT_SLOT : 0);
586
bd6f5bd7
AB
587 cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
588
3dd94794 589 for (i = 0; i < IEEE80211_NUM_ACS; i++) {
cf6c6ea3 590 u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
3dd94794
EG
591
592 cmd->ac[txf].cw_min =
593 cpu_to_le16(mvmvif->queue_params[i].cw_min);
594 cmd->ac[txf].cw_max =
595 cpu_to_le16(mvmvif->queue_params[i].cw_max);
596 cmd->ac[txf].edca_txop =
8ca151b5 597 cpu_to_le16(mvmvif->queue_params[i].txop * 32);
3dd94794
EG
598 cmd->ac[txf].aifsn = mvmvif->queue_params[i].aifs;
599 cmd->ac[txf].fifos_mask = BIT(txf);
8ca151b5
JB
600 }
601
602 if (vif->bss_conf.qos)
603 cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
604
dc271ee0 605 if (vif->bss_conf.use_cts_prot)
cc7ee2ba 606 cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
dc271ee0 607
8a5e3660
AA
608 IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n",
609 vif->bss_conf.use_cts_prot,
610 vif->bss_conf.ht_operation_mode);
611 if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
8ca151b5 612 cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
8a5e3660
AA
613 if (ht_enabled)
614 iwl_mvm_mac_ctxt_set_ht_flags(mvm, vif, cmd);
8ca151b5
JB
615}
616
617static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
618 struct iwl_mac_ctx_cmd *cmd)
619{
a1022927 620 int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,
8ca151b5
JB
621 sizeof(*cmd), cmd);
622 if (ret)
623 IWL_ERR(mvm, "Failed to send MAC context (action:%d): %d\n",
624 le32_to_cpu(cmd->action), ret);
625 return ret;
626}
627
cf52023c
LC
628static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
629 struct ieee80211_vif *vif,
3dfd3a97
JB
630 u32 action, bool force_assoc_off,
631 const u8 *bssid_override)
8ca151b5 632{
cf52023c
LC
633 struct iwl_mac_ctx_cmd cmd = {};
634 struct iwl_mac_data_sta *ctxt_sta;
635
636 WARN_ON(vif->type != NL80211_IFTYPE_STATION);
637
638 /* Fill the common data for all mac context types */
3dfd3a97 639 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, bssid_override, action);
cf52023c
LC
640
641 if (vif->p2p) {
642 struct ieee80211_p2p_noa_attr *noa =
643 &vif->bss_conf.p2p_noa_attr;
644
645 cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
646 IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
647 ctxt_sta = &cmd.p2p_sta.sta;
648 } else {
cf52023c
LC
649 ctxt_sta = &cmd.sta;
650 }
651
210a544e 652 /* We need the dtim_period to set the MAC as associated */
ba283927
AB
653 if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
654 !force_assoc_off) {
d2931bbd
JB
655 u32 dtim_offs;
656
657 /*
658 * The DTIM count counts down, so when it is N that means N
659 * more beacon intervals happen until the DTIM TBTT. Therefore
660 * add this to the current time. If that ends up being in the
661 * future, the firmware will handle it.
662 *
663 * Also note that the system_timestamp (which we get here as
664 * "sync_device_ts") and TSF timestamp aren't at exactly the
665 * same offset in the frame -- the TSF is at the first symbol
666 * of the TSF, the system timestamp is at signal acquisition
667 * time. This means there's an offset between them of at most
668 * a few hundred microseconds (24 * 8 bits + PLCP time gives
669 * 384us in the longest case), this is currently not relevant
670 * as the firmware wakes up around 2ms before the TBTT.
671 */
672 dtim_offs = vif->bss_conf.sync_dtim_count *
673 vif->bss_conf.beacon_int;
674 /* convert TU to usecs */
675 dtim_offs *= 1024;
676
677 ctxt_sta->dtim_tsf =
678 cpu_to_le64(vif->bss_conf.sync_tsf + dtim_offs);
679 ctxt_sta->dtim_time =
680 cpu_to_le32(vif->bss_conf.sync_device_ts + dtim_offs);
b5669727
AS
681 ctxt_sta->assoc_beacon_arrive_time =
682 cpu_to_le32(vif->bss_conf.sync_device_ts);
d2931bbd
JB
683
684 IWL_DEBUG_INFO(mvm, "DTIM TBTT is 0x%llx/0x%x, offset %d\n",
685 le64_to_cpu(ctxt_sta->dtim_tsf),
686 le32_to_cpu(ctxt_sta->dtim_time),
687 dtim_offs);
688
210a544e 689 ctxt_sta->is_assoc = cpu_to_le32(1);
d2931bbd 690 } else {
210a544e 691 ctxt_sta->is_assoc = cpu_to_le32(0);
7c8b3bc6
LC
692
693 /* Allow beacons to pass through as long as we are not
694 * associated, or we do not have dtim period information.
695 */
696 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
d2931bbd 697 }
8ca151b5
JB
698
699 ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int);
8ca151b5
JB
700 ctxt_sta->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
701 vif->bss_conf.dtim_period);
8ca151b5
JB
702
703 ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval);
704 ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid);
8ca151b5 705
effd1929
AO
706 if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p)
707 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
708
230ba6c5 709 if (vif->bss_conf.assoc && vif->bss_conf.he_support &&
d91d9b94 710 !iwlwifi_mod_params.disable_11ax) {
514c3069 711 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
866a6a85
EG
712 if (vif->bss_conf.twt_requester)
713 ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED);
d91d9b94
EG
714 }
715
514c3069 716
8ca151b5
JB
717 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
718}
719
720static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
721 struct ieee80211_vif *vif,
722 u32 action)
723{
724 struct iwl_mac_ctx_cmd cmd = {};
b13f43a4 725 u32 tfd_queue_msk = BIT(mvm->snif_queue);
c8f54701 726 int ret;
8ca151b5
JB
727
728 WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
729
3dfd3a97 730 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
53585495
JB
731
732 cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
733 MAC_FILTER_IN_CONTROL_AND_MGMT |
734 MAC_FILTER_IN_BEACON |
fb8b8ee1
JB
735 MAC_FILTER_IN_PROBE_REQUEST |
736 MAC_FILTER_IN_CRC32);
30686bf7 737 ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
53585495 738
0e39eb03
CRI
739 /* Allocate sniffer station */
740 ret = iwl_mvm_allocate_int_sta(mvm, &mvm->snif_sta, tfd_queue_msk,
ced19f26 741 vif->type, IWL_STA_GENERAL_PURPOSE);
0e39eb03
CRI
742 if (ret)
743 return ret;
744
8ca151b5
JB
745 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
746}
747
5023d966
JB
748static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
749 struct ieee80211_vif *vif,
750 u32 action)
751{
752 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
753 struct iwl_mac_ctx_cmd cmd = {};
754
755 WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
756
3dfd3a97 757 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
5023d966
JB
758
759 cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON |
760 MAC_FILTER_IN_PROBE_REQUEST);
761
762 /* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */
763 cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int);
5023d966
JB
764
765 /* TODO: Assumes that the beacon id == mac context id */
766 cmd.ibss.beacon_template = cpu_to_le32(mvmvif->id);
767
768 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
769}
770
8ca151b5
JB
771struct iwl_mvm_go_iterator_data {
772 bool go_active;
773};
774
775static void iwl_mvm_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif)
776{
777 struct iwl_mvm_go_iterator_data *data = _data;
778 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
779
5023d966
JB
780 if (vif->type == NL80211_IFTYPE_AP && vif->p2p &&
781 mvmvif->ap_ibss_active)
8ca151b5
JB
782 data->go_active = true;
783}
784
785static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
786 struct ieee80211_vif *vif,
787 u32 action)
788{
789 struct iwl_mac_ctx_cmd cmd = {};
790 struct iwl_mvm_go_iterator_data data = {};
791
792 WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
793
3dfd3a97 794 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
8ca151b5 795
1dcd15ee
IP
796 /* Override the filter flags to accept only probe requests */
797 cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
8ca151b5
JB
798
799 /*
800 * This flag should be set to true when the P2P Device is
801 * discoverable and there is at least another active P2P GO. Settings
802 * this flag will allow the P2P Device to be discoverable on other
803 * channels in addition to its listen channel.
804 * Note that this flag should not be set in other cases as it opens the
805 * Rx filters on all MAC and increases the number of interrupts.
806 */
807 ieee80211_iterate_active_interfaces_atomic(
808 mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
809 iwl_mvm_go_iterator, &data);
810
811 cmd.p2p_dev.is_disc_extended = cpu_to_le32(data.go_active ? 1 : 0);
812 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
813}
814
815static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
8364fbb4 816 __le32 *tim_index, __le32 *tim_size,
8ca151b5
JB
817 u8 *beacon, u32 frame_size)
818{
819 u32 tim_idx;
820 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
821
822 /* The index is relative to frame start but we start looking at the
823 * variable-length part of the beacon. */
824 tim_idx = mgmt->u.beacon.variable - beacon;
825
826 /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
827 while ((tim_idx < (frame_size - 2)) &&
828 (beacon[tim_idx] != WLAN_EID_TIM))
829 tim_idx += beacon[tim_idx+1] + 2;
830
831 /* If TIM field was found, set variables */
832 if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
8364fbb4
SS
833 *tim_index = cpu_to_le32(tim_idx);
834 *tim_size = cpu_to_le32((u32)beacon[tim_idx + 1]);
8ca151b5
JB
835 } else {
836 IWL_WARN(mvm, "Unable to find TIM Element in beacon\n");
837 }
838}
839
d3a108a4
AO
840static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
841{
842 struct ieee80211_mgmt *mgmt = (void *)beacon;
843 const u8 *ie;
844
845 if (WARN_ON_ONCE(frame_size <= (mgmt->u.beacon.variable - beacon)))
846 return 0;
847
848 frame_size -= mgmt->u.beacon.variable - beacon;
849
850 ie = cfg80211_find_ie(eid, mgmt->u.beacon.variable, frame_size);
851 if (!ie)
852 return 0;
853
854 return ie - beacon;
855}
856
6ca33f8b
HD
857static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
858 struct ieee80211_vif *vif)
859{
860 u8 rate;
861
862 if (info->band == NL80211_BAND_5GHZ || vif->p2p)
863 rate = IWL_FIRST_OFDM_RATE;
864 else
865 rate = IWL_FIRST_CCK_RATE;
866
867 return rate;
868}
869
09856582
LC
870static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
871 struct ieee80211_vif *vif,
872 struct sk_buff *beacon,
873 struct iwl_tx_cmd *tx)
8ca151b5
JB
874{
875 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
8ca151b5 876 struct ieee80211_tx_info *info;
6ca33f8b
HD
877 u8 rate;
878 u32 tx_flags;
8ca151b5 879
75f6b9b6 880 info = IEEE80211_SKB_CB(beacon);
8ca151b5
JB
881
882 /* Set up TX command fields */
09856582
LC
883 tx->len = cpu_to_le16((u16)beacon->len);
884 tx->sta_id = mvmvif->bcast_sta.sta_id;
885 tx->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
75f6b9b6
EG
886 tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
887 tx_flags |=
888 iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) <<
889 TX_CMD_FLG_BT_PRIO_POS;
09856582 890 tx->tx_flags = cpu_to_le32(tx_flags);
8ca151b5 891
1e3c3c35 892 if (!fw_has_capa(&mvm->fw->ucode_capa,
656fca00
AS
893 IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION))
894 iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
8ca151b5 895
09856582 896 tx->rate_n_flags =
8ca151b5
JB
897 cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
898 RATE_MCS_ANT_POS);
899
6ca33f8b 900 rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
8ca151b5 901
09856582 902 tx->rate_n_flags |= cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate));
6ca33f8b
HD
903 if (rate == IWL_FIRST_CCK_RATE)
904 tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK);
905
09856582
LC
906}
907
908static int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
909 struct sk_buff *beacon,
910 void *data, int len)
911{
912 struct iwl_host_cmd cmd = {
913 .id = BEACON_TEMPLATE_CMD,
914 .flags = CMD_ASYNC,
915 };
8ca151b5 916
09856582
LC
917 cmd.len[0] = len;
918 cmd.data[0] = data;
8ca151b5 919 cmd.dataflags[0] = 0;
09856582 920 cmd.len[1] = beacon->len;
8ca151b5
JB
921 cmd.data[1] = beacon->data;
922 cmd.dataflags[1] = IWL_HCMD_DFL_DUP;
923
924 return iwl_mvm_send_cmd(mvm, &cmd);
925}
926
09856582
LC
927static int iwl_mvm_mac_ctxt_send_beacon_v6(struct iwl_mvm *mvm,
928 struct ieee80211_vif *vif,
929 struct sk_buff *beacon)
930{
931 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
932 struct iwl_mac_beacon_cmd_v6 beacon_cmd = {};
933
934 iwl_mvm_mac_ctxt_set_tx(mvm, vif, beacon, &beacon_cmd.tx);
935
936 beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
937
938 if (vif->type == NL80211_IFTYPE_AP)
939 iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
940 &beacon_cmd.tim_size,
941 beacon->data, beacon->len);
942
943 return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
944 sizeof(beacon_cmd));
945}
946
947static int iwl_mvm_mac_ctxt_send_beacon_v7(struct iwl_mvm *mvm,
948 struct ieee80211_vif *vif,
949 struct sk_buff *beacon)
950{
951 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
952 struct iwl_mac_beacon_cmd_v7 beacon_cmd = {};
953
954 iwl_mvm_mac_ctxt_set_tx(mvm, vif, beacon, &beacon_cmd.tx);
955
956 beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
957
958 if (vif->type == NL80211_IFTYPE_AP)
959 iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
960 &beacon_cmd.tim_size,
961 beacon->data, beacon->len);
962
963 beacon_cmd.csa_offset =
964 cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
965 WLAN_EID_CHANNEL_SWITCH,
966 beacon->len));
967 beacon_cmd.ecsa_offset =
968 cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
969 WLAN_EID_EXT_CHANSWITCH_ANN,
970 beacon->len));
971
972 return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
973 sizeof(beacon_cmd));
974}
975
6ca33f8b 976static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
09856582
LC
977 struct ieee80211_vif *vif,
978 struct sk_buff *beacon)
979{
980 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
6ca33f8b 981 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(beacon);
09856582 982 struct iwl_mac_beacon_cmd beacon_cmd = {};
6ca33f8b
HD
983 u8 rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
984 u16 flags;
985
986 flags = iwl_mvm_mac80211_idx_to_hwrate(rate);
09856582 987
6ca33f8b
HD
988 if (rate == IWL_FIRST_CCK_RATE)
989 flags |= IWL_MAC_BEACON_CCK;
990
991 beacon_cmd.flags = cpu_to_le16(flags);
09856582
LC
992 beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
993 beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
994
995 if (vif->type == NL80211_IFTYPE_AP)
6ca33f8b 996 iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
09856582
LC
997 &beacon_cmd.tim_size,
998 beacon->data, beacon->len);
999
1000 beacon_cmd.csa_offset =
1001 cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
1002 WLAN_EID_CHANNEL_SWITCH,
1003 beacon->len));
1004 beacon_cmd.ecsa_offset =
1005 cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
1006 WLAN_EID_EXT_CHANSWITCH_ANN,
1007 beacon->len));
1008
1009 return iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
1010 sizeof(beacon_cmd));
1011}
1012
1013static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
1014 struct ieee80211_vif *vif,
1015 struct sk_buff *beacon)
1016{
1017 if (WARN_ON(!beacon))
1018 return -EINVAL;
1019
1020 if (!fw_has_capa(&mvm->fw->ucode_capa,
1021 IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD))
1022 return iwl_mvm_mac_ctxt_send_beacon_v6(mvm, vif, beacon);
1023
6ca33f8b
HD
1024 if (fw_has_api(&mvm->fw->ucode_capa,
1025 IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
1026 return iwl_mvm_mac_ctxt_send_beacon_v9(mvm, vif, beacon);
09856582 1027
6ca33f8b 1028 return iwl_mvm_mac_ctxt_send_beacon_v7(mvm, vif, beacon);
09856582
LC
1029}
1030
5023d966 1031/* The beacon template for the AP/GO/IBSS has changed and needs update */
8ca151b5
JB
1032int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
1033 struct ieee80211_vif *vif)
1034{
1035 struct sk_buff *beacon;
1036 int ret;
1037
5023d966
JB
1038 WARN_ON(vif->type != NL80211_IFTYPE_AP &&
1039 vif->type != NL80211_IFTYPE_ADHOC);
8ca151b5 1040
fe887665 1041 beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL);
8ca151b5
JB
1042 if (!beacon)
1043 return -ENOMEM;
1044
1045 ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon);
1046 dev_kfree_skb(beacon);
1047 return ret;
1048}
1049
3a3cb92e
IP
1050struct iwl_mvm_mac_ap_iterator_data {
1051 struct iwl_mvm *mvm;
1052 struct ieee80211_vif *vif;
1053 u32 beacon_device_ts;
1054 u16 beacon_int;
1055};
1056
1057/* Find the beacon_device_ts and beacon_int for a managed interface */
1058static void iwl_mvm_mac_ap_iterator(void *_data, u8 *mac,
1059 struct ieee80211_vif *vif)
1060{
1061 struct iwl_mvm_mac_ap_iterator_data *data = _data;
1062
1063 if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc)
1064 return;
1065
1066 /* Station client has higher priority over P2P client*/
1067 if (vif->p2p && data->beacon_device_ts)
1068 return;
1069
1070 data->beacon_device_ts = vif->bss_conf.sync_device_ts;
1071 data->beacon_int = vif->bss_conf.beacon_int;
1072}
1073
8ca151b5
JB
1074/*
1075 * Fill the specific data for mac context of type AP of P2P GO
1076 */
1077static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
1078 struct ieee80211_vif *vif,
186cd49a 1079 struct iwl_mac_ctx_cmd *cmd,
506a81e6
JB
1080 struct iwl_mac_data_ap *ctxt_ap,
1081 bool add)
8ca151b5
JB
1082{
1083 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
3a3cb92e
IP
1084 struct iwl_mvm_mac_ap_iterator_data data = {
1085 .mvm = mvm,
1086 .vif = vif,
1087 .beacon_device_ts = 0
1088 };
8ca151b5 1089
186cd49a
JB
1090 /* in AP mode, the MCAST FIFO takes the EDCA params from VO */
1091 cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST);
1092
1093 /*
1094 * in AP mode, pass probe requests and beacons from other APs
1095 * (needed for ht protection); when there're no any associated
1096 * station don't ask FW to pass beacons to prevent unnecessary
1097 * wake-ups.
1098 */
1099 cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
1100 if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) {
1101 cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
1102 IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
1103 } else {
1104 IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
1105 }
1106
3b5ee8dd
ST
1107 if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax)
1108 cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
1109
8ca151b5 1110 ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
8ca151b5
JB
1111 ctxt_ap->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
1112 vif->bss_conf.dtim_period);
8ca151b5 1113
ced19f26
SS
1114 if (!fw_has_api(&mvm->fw->ucode_capa,
1115 IWL_UCODE_TLV_API_STA_TYPE))
cfbc6c4c 1116 ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->cab_queue);
8ca151b5 1117
506a81e6 1118 /*
3a3cb92e 1119 * Only set the beacon time when the MAC is being added, when we
506a81e6
JB
1120 * just modify the MAC then we should keep the time -- the firmware
1121 * can otherwise have a "jumping" TBTT.
1122 */
3a3cb92e
IP
1123 if (add) {
1124 /*
1125 * If there is a station/P2P client interface which is
1126 * associated, set the AP's TBTT far enough from the station's
1127 * TBTT. Otherwise, set it to the current system time
1128 */
1129 ieee80211_iterate_active_interfaces_atomic(
1130 mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
1131 iwl_mvm_mac_ap_iterator, &data);
1132
1133 if (data.beacon_device_ts) {
9f8f8ca5 1134 u32 rand = (prandom_u32() % (64 - 36)) + 36;
3a3cb92e
IP
1135 mvmvif->ap_beacon_time = data.beacon_device_ts +
1136 ieee80211_tu_to_usec(data.beacon_int * rand /
1137 100);
1138 } else {
1139 mvmvif->ap_beacon_time =
1140 iwl_read_prph(mvm->trans,
1141 DEVICE_SYSTEM_TIME_REG);
1142 }
1143 }
506a81e6
JB
1144
1145 ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time);
506a81e6 1146 ctxt_ap->beacon_tsf = 0; /* unused */
8ca151b5
JB
1147
1148 /* TODO: Assume that the beacon id == mac context id */
1149 ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id);
1150}
1151
f82c8339
IP
1152static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
1153 struct ieee80211_vif *vif,
1154 u32 action)
8ca151b5
JB
1155{
1156 struct iwl_mac_ctx_cmd cmd = {};
1157
1158 WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p);
1159
1160 /* Fill the common data for all mac context types */
3dfd3a97 1161 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
8ca151b5
JB
1162
1163 /* Fill the data specific for ap mode */
186cd49a 1164 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd, &cmd.ap,
506a81e6 1165 action == FW_CTXT_ACTION_ADD);
8ca151b5
JB
1166
1167 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
1168}
1169
1170static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
1171 struct ieee80211_vif *vif,
1172 u32 action)
1173{
1174 struct iwl_mac_ctx_cmd cmd = {};
67baf663 1175 struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
8ca151b5
JB
1176
1177 WARN_ON(vif->type != NL80211_IFTYPE_AP || !vif->p2p);
1178
1179 /* Fill the common data for all mac context types */
3dfd3a97 1180 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
8ca151b5
JB
1181
1182 /* Fill the data specific for GO mode */
186cd49a 1183 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd, &cmd.go.ap,
506a81e6 1184 action == FW_CTXT_ACTION_ADD);
8ca151b5 1185
67baf663
JD
1186 cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow &
1187 IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
1188 cmd.go.opp_ps_enabled =
1189 cpu_to_le32(!!(noa->oppps_ctwindow &
1190 IEEE80211_P2P_OPPPS_ENABLE_BIT));
8ca151b5
JB
1191
1192 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
1193}
1194
1195static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
3dfd3a97
JB
1196 u32 action, bool force_assoc_off,
1197 const u8 *bssid_override)
8ca151b5
JB
1198{
1199 switch (vif->type) {
1200 case NL80211_IFTYPE_STATION:
cf52023c 1201 return iwl_mvm_mac_ctxt_cmd_sta(mvm, vif, action,
3dfd3a97
JB
1202 force_assoc_off,
1203 bssid_override);
8ca151b5
JB
1204 break;
1205 case NL80211_IFTYPE_AP:
1206 if (!vif->p2p)
1207 return iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, action);
1208 else
1209 return iwl_mvm_mac_ctxt_cmd_go(mvm, vif, action);
1210 break;
1211 case NL80211_IFTYPE_MONITOR:
1212 return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action);
1213 case NL80211_IFTYPE_P2P_DEVICE:
1214 return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action);
5023d966
JB
1215 case NL80211_IFTYPE_ADHOC:
1216 return iwl_mvm_mac_ctxt_cmd_ibss(mvm, vif, action);
8ca151b5
JB
1217 default:
1218 break;
1219 }
1220
1221 return -EOPNOTSUPP;
1222}
1223
1224int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1225{
1226 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1227 int ret;
1228
1229 if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
1230 vif->addr, ieee80211_vif_type_p2p(vif)))
1231 return -EIO;
1232
bca49d9a 1233 ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD,
3dfd3a97 1234 true, NULL);
8ca151b5
JB
1235 if (ret)
1236 return ret;
1237
6d9d32b8
JB
1238 /* will only do anything at resume from D3 time */
1239 iwl_mvm_set_last_nonqos_seq(mvm, vif);
1240
8ca151b5
JB
1241 mvmvif->uploaded = true;
1242 return 0;
1243}
1244
bca49d9a 1245int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
3dfd3a97 1246 bool force_assoc_off, const u8 *bssid_override)
8ca151b5
JB
1247{
1248 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1249
1250 if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
1251 vif->addr, ieee80211_vif_type_p2p(vif)))
1252 return -EIO;
1253
bca49d9a 1254 return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY,
3dfd3a97 1255 force_assoc_off, bssid_override);
8ca151b5
JB
1256}
1257
1258int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1259{
1260 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1261 struct iwl_mac_ctx_cmd cmd;
1262 int ret;
1263
1264 if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
1265 vif->addr, ieee80211_vif_type_p2p(vif)))
1266 return -EIO;
1267
1268 memset(&cmd, 0, sizeof(cmd));
1269
1270 cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
1271 mvmvif->color));
1272 cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
1273
a1022927 1274 ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,
8ca151b5
JB
1275 sizeof(cmd), &cmd);
1276 if (ret) {
1277 IWL_ERR(mvm, "Failed to remove MAC context: %d\n", ret);
1278 return ret;
1279 }
1280
1281 mvmvif->uploaded = false;
fb8b8ee1 1282
0e39eb03 1283 if (vif->type == NL80211_IFTYPE_MONITOR) {
30686bf7 1284 __clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
0e39eb03
CRI
1285 iwl_mvm_dealloc_snif_sta(mvm);
1286 }
fb8b8ee1 1287
8ca151b5
JB
1288 return 0;
1289}
571765c8 1290
7f0a7c67 1291static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
7ef0aab6
AO
1292 struct ieee80211_vif *csa_vif, u32 gp2,
1293 bool tx_success)
7f0a7c67
AO
1294{
1295 struct iwl_mvm_vif *mvmvif =
1296 iwl_mvm_vif_from_mac80211(csa_vif);
1297
7ef0aab6
AO
1298 /* Don't start to countdown from a failed beacon */
1299 if (!tx_success && !mvmvif->csa_countdown)
1300 return;
1301
1302 mvmvif->csa_countdown = true;
1303
7f0a7c67
AO
1304 if (!ieee80211_csa_is_complete(csa_vif)) {
1305 int c = ieee80211_csa_update_counter(csa_vif);
1306
1307 iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
1308 if (csa_vif->p2p &&
7ef0aab6
AO
1309 !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2 &&
1310 tx_success) {
7f0a7c67
AO
1311 u32 rel_time = (c + 1) *
1312 csa_vif->bss_conf.beacon_int -
f991e17b 1313 IWL_MVM_CHANNEL_SWITCH_TIME_GO;
7f0a7c67
AO
1314 u32 apply_time = gp2 + rel_time * 1024;
1315
f991e17b
LC
1316 iwl_mvm_schedule_csa_period(mvm, csa_vif,
1317 IWL_MVM_CHANNEL_SWITCH_TIME_GO -
1318 IWL_MVM_CHANNEL_SWITCH_MARGIN,
1319 apply_time);
7f0a7c67
AO
1320 }
1321 } else if (!iwl_mvm_te_scheduled(&mvmvif->time_event_data)) {
1322 /* we don't have CSA NoA scheduled yet, switch now */
1323 ieee80211_csa_finish(csa_vif);
1324 RCU_INIT_POINTER(mvm->csa_vif, NULL);
1325 }
1326}
1327
0416841d
JB
1328void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
1329 struct iwl_rx_cmd_buffer *rxb)
571765c8
IP
1330{
1331 struct iwl_rx_packet *pkt = rxb_addr(rxb);
2d2c0e9c 1332 struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
1c87bbad 1333 struct iwl_mvm_tx_resp *beacon_notify_hdr;
664322fa 1334 struct ieee80211_vif *csa_vif;
003e5236 1335 struct ieee80211_vif *tx_blocked_vif;
12db294c 1336 struct agg_tx_status *agg_status;
7ef0aab6 1337 u16 status;
571765c8 1338
bd3398e2
AO
1339 lockdep_assert_held(&mvm->mutex);
1340
2d2c0e9c
EG
1341 beacon_notify_hdr = &beacon->beacon_notify_hdr;
1342 mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
2f0282db 1343 mvm->ibss_manager = beacon->ibss_mgr_status != 0;
1c87bbad 1344
12db294c
SS
1345 agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr);
1346 status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK;
1c87bbad 1347 IWL_DEBUG_RX(mvm,
677837b8 1348 "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n",
2d2c0e9c
EG
1349 status, beacon_notify_hdr->failure_frame,
1350 le64_to_cpu(beacon->tsf),
1c87bbad
DS
1351 mvm->ap_last_beacon_gp2,
1352 le32_to_cpu(beacon_notify_hdr->initial_rate));
bd3398e2 1353
664322fa
AO
1354 csa_vif = rcu_dereference_protected(mvm->csa_vif,
1355 lockdep_is_held(&mvm->mutex));
7f0a7c67 1356 if (unlikely(csa_vif && csa_vif->csa_active))
7ef0aab6
AO
1357 iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2,
1358 (status == TX_STATUS_SUCCESS));
bd3398e2 1359
003e5236
AO
1360 tx_blocked_vif = rcu_dereference_protected(mvm->csa_tx_blocked_vif,
1361 lockdep_is_held(&mvm->mutex));
1362 if (unlikely(tx_blocked_vif)) {
1363 struct iwl_mvm_vif *mvmvif =
1364 iwl_mvm_vif_from_mac80211(tx_blocked_vif);
1365
1366 /*
1367 * The channel switch is started and we have blocked the
1368 * stations. If this is the first beacon (the timeout wasn't
1369 * set), set the unblock timeout, otherwise countdown
1370 */
1371 if (!mvm->csa_tx_block_bcn_timeout)
1372 mvm->csa_tx_block_bcn_timeout =
1373 IWL_MVM_CS_UNBLOCK_TX_TIMEOUT;
1374 else
1375 mvm->csa_tx_block_bcn_timeout--;
1376
1377 /* Check if the timeout is expired, and unblock tx */
1378 if (mvm->csa_tx_block_bcn_timeout == 0) {
1379 iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
1380 RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
1381 }
1382 }
571765c8 1383}
d64048ed 1384
698478c4
SS
1385void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
1386 struct iwl_rx_cmd_buffer *rxb)
d64048ed 1387{
698478c4
SS
1388 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1389 struct iwl_missed_beacons_notif *mb = (void *)pkt->data;
9d761fd8
EG
1390 struct iwl_fw_dbg_trigger_missed_bcon *bcon_trig;
1391 struct iwl_fw_dbg_trigger_tlv *trigger;
1392 u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx;
1393 u32 rx_missed_bcon, rx_missed_bcon_since_rx;
698478c4
SS
1394 struct ieee80211_vif *vif;
1395 u32 id = le32_to_cpu(mb->mac_id);
d64048ed 1396
698478c4
SS
1397 IWL_DEBUG_INFO(mvm,
1398 "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
1399 le32_to_cpu(mb->mac_id),
1400 le32_to_cpu(mb->consec_missed_beacons),
1401 le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
1402 le32_to_cpu(mb->num_recvd_beacons),
1403 le32_to_cpu(mb->num_expected_beacons));
1404
1405 rcu_read_lock();
1406
1407 vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
1408 if (!vif)
1409 goto out;
12d423e8 1410
698478c4 1411 rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons);
9d761fd8 1412 rx_missed_bcon_since_rx =
698478c4 1413 le32_to_cpu(mb->consec_missed_beacons_since_last_rx);
12d423e8
IP
1414 /*
1415 * TODO: the threshold should be adjusted based on latency conditions,
1416 * and/or in case of a CS flow on one of the other AP vifs.
1417 */
babea2d4
AO
1418 if (rx_missed_bcon > IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG)
1419 iwl_mvm_connection_loss(mvm, vif, "missed beacons");
1420 else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD)
d64048ed 1421 ieee80211_beacon_loss(vif);
9d761fd8 1422
6c042d75
SS
1423 trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
1424 FW_DBG_TRIGGER_MISSED_BEACONS);
1425 if (!trigger)
698478c4 1426 goto out;
9d761fd8 1427
9d761fd8
EG
1428 bcon_trig = (void *)trigger->data;
1429 stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon);
1430 stop_trig_missed_bcon_since_rx =
1431 le32_to_cpu(bcon_trig->stop_consec_missed_bcon_since_rx);
1432
1433 /* TODO: implement start trigger */
1434
9d761fd8
EG
1435 if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx ||
1436 rx_missed_bcon >= stop_trig_missed_bcon)
7174beb6 1437 iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
da2eb669
SS
1438
1439 iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_MISSED_BEACONS);
698478c4
SS
1440
1441out:
1442 rcu_read_unlock();
d64048ed 1443}
0db056d3
SS
1444
1445void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
1446 struct iwl_rx_cmd_buffer *rxb)
1447{
1448 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1449 struct iwl_stored_beacon_notif *sb = (void *)pkt->data;
1450 struct ieee80211_rx_status rx_status;
1451 struct sk_buff *skb;
1452 u32 size = le32_to_cpu(sb->byte_count);
1453
1454 if (size == 0)
1455 return;
1456
1457 skb = alloc_skb(size, GFP_ATOMIC);
1458 if (!skb) {
1459 IWL_ERR(mvm, "alloc_skb failed\n");
1460 return;
1461 }
1462
1463 /* update rx_status according to the notification's metadata */
1464 memset(&rx_status, 0, sizeof(rx_status));
1465 rx_status.mactime = le64_to_cpu(sb->tsf);
77fe7395
SS
1466 /* TSF as indicated by the firmware is at INA time */
1467 rx_status.flag |= RX_FLAG_MACTIME_PLCP_START;
0db056d3
SS
1468 rx_status.device_timestamp = le32_to_cpu(sb->system_time);
1469 rx_status.band =
34118c25 1470 (sb->band & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
57fbcce3 1471 NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
0db056d3
SS
1472 rx_status.freq =
1473 ieee80211_channel_to_frequency(le16_to_cpu(sb->channel),
1474 rx_status.band);
1475
1476 /* copy the data */
59ae1d12 1477 skb_put_data(skb, sb->data, size);
0db056d3
SS
1478 memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
1479
1480 /* pass it as regular rx to mac80211 */
d63b548f 1481 ieee80211_rx_napi(mvm->hw, NULL, skb, NULL);
0db056d3 1482}
d3a108a4 1483
698478c4
SS
1484void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
1485 struct iwl_rx_cmd_buffer *rxb)
86e177d8 1486{
698478c4
SS
1487 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1488 struct iwl_probe_resp_data_notif *notif = (void *)pkt->data;
86e177d8 1489 struct iwl_probe_resp_data *old_data, *new_data;
698478c4
SS
1490 int len = iwl_rx_packet_payload_len(pkt);
1491 u32 id = le32_to_cpu(notif->mac_id);
1492 struct ieee80211_vif *vif;
1493 struct iwl_mvm_vif *mvmvif;
1494
1495 if (WARN_ON_ONCE(len < sizeof(*notif)))
1496 return;
1497
1498 IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n",
1499 notif->noa_active, notif->csa_counter);
86e177d8 1500
698478c4
SS
1501 vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false);
1502 if (!vif)
86e177d8
GG
1503 return;
1504
698478c4
SS
1505 mvmvif = iwl_mvm_vif_from_mac80211(vif);
1506
86e177d8
GG
1507 new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
1508 if (!new_data)
1509 return;
1510
1511 memcpy(&new_data->notif, notif, sizeof(new_data->notif));
1512
1513 /* noa_attr contains 1 reserved byte, need to substruct it */
1514 new_data->noa_len = sizeof(struct ieee80211_vendor_ie) +
1515 sizeof(new_data->notif.noa_attr) - 1;
1516
1517 /*
1518 * If it's a one time NoA, only one descriptor is needed,
1519 * adjust the length according to len_low.
1520 */
1521 if (new_data->notif.noa_attr.len_low ==
1522 sizeof(struct ieee80211_p2p_noa_desc) + 2)
1523 new_data->noa_len -= sizeof(struct ieee80211_p2p_noa_desc);
1524
1525 old_data = rcu_dereference_protected(mvmvif->probe_resp_data,
1526 lockdep_is_held(&mvmvif->mvm->mutex));
1527 rcu_assign_pointer(mvmvif->probe_resp_data, new_data);
1528
1529 if (old_data)
1530 kfree_rcu(old_data, rcu_head);
1531
1532 if (notif->csa_counter != IWL_PROBE_RESP_DATA_NO_CSA &&
1533 notif->csa_counter >= 1)
1534 ieee80211_csa_set_counter(vif, notif->csa_counter);
1535}
1536
d3a108a4
AO
1537void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
1538 struct iwl_rx_cmd_buffer *rxb)
1539{
1540 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1541 struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data;
74a10252 1542 struct ieee80211_vif *csa_vif, *vif;
d3a108a4
AO
1543 struct iwl_mvm_vif *mvmvif;
1544 int len = iwl_rx_packet_payload_len(pkt);
74a10252 1545 u32 id_n_color, csa_id, mac_id;
d3a108a4
AO
1546
1547 if (WARN_ON_ONCE(len < sizeof(*notif)))
1548 return;
1549
d3a108a4 1550 id_n_color = le32_to_cpu(notif->id_and_color);
74a10252 1551 mac_id = id_n_color & FW_CTXT_ID_MSK;
d3a108a4 1552
74a10252
SS
1553 if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER))
1554 return;
d3a108a4 1555
74a10252
SS
1556 rcu_read_lock();
1557 vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]);
d3a108a4 1558
74a10252
SS
1559 switch (vif->type) {
1560 case NL80211_IFTYPE_AP:
1561 csa_vif = rcu_dereference(mvm->csa_vif);
1562 if (WARN_ON(!csa_vif || !csa_vif->csa_active ||
1563 csa_vif != vif))
1564 goto out_unlock;
d3a108a4 1565
74a10252
SS
1566 mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
1567 csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
1568 if (WARN(csa_id != id_n_color,
1569 "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
1570 csa_id, id_n_color))
1571 goto out_unlock;
d3a108a4 1572
74a10252 1573 IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n");
d3a108a4 1574
74a10252
SS
1575 schedule_delayed_work(&mvm->cs_tx_unblock_dwork,
1576 msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT *
1577 csa_vif->bss_conf.beacon_int));
d3a108a4 1578
74a10252 1579 ieee80211_csa_finish(csa_vif);
d3a108a4 1580
74a10252
SS
1581 rcu_read_unlock();
1582
1583 RCU_INIT_POINTER(mvm->csa_vif, NULL);
1584 return;
1585 case NL80211_IFTYPE_STATION:
1586 iwl_mvm_csa_client_absent(mvm, vif);
1587 ieee80211_chswitch_done(vif, true);
1588 break;
1589 default:
1590 /* should never happen */
1591 WARN_ON_ONCE(1);
1592 break;
1593 }
d3a108a4
AO
1594out_unlock:
1595 rcu_read_unlock();
1596}