aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-01-24 08:25:36 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-01 05:27:15 -0500
commit8ca151b568b67a7b72dcfc6ee6ea7c107ddd795c (patch)
treedac0236038f3791140e9f864c5db2be873c568f0 /drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
parentb1e1adfa7d30cd0e8ad9a5c6a89e8c45ebe084f4 (diff)
iwlwifi: add the MVM driver
Newer firmware revisions have a completely new firmware API. This is the new driver for this new API. I've listed the people who directly contributed code, but many others from various teams have contributed in other ways. Cc: Alexander Bondar <alexander.bondar@intel.com> Cc: Amit Beka <amit.beka@intel.com> Cc: Amnon Paz <amnonx.paz@intel.com> Cc: Assaf Krauss <assaf.krauss@intel.com> Cc: David Spinadel <david.spinadel@intel.com> Cc: Dor Shaish <dor.shaish@intel.com> Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Cc: Eytan Lifshitz <eytan.lifshitz@intel.com> Cc: Ilan Peer <ilan.peer@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c951
1 files changed, 951 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
new file mode 100644
index 000000000000..c08a17a3cab9
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -0,0 +1,951 @@
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 *
8 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22 * USA
23 *
24 * The full GNU General Public License is included in this distribution
25 * in the file called LICENSE.GPL.
26 *
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 *
31 * BSD LICENSE
32 *
33 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
45 * distribution.
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *
62 *****************************************************************************/
63
64#include <linux/etherdevice.h>
65#include <net/mac80211.h>
66#include "iwl-io.h"
67#include "iwl-prph.h"
68#include "fw-api.h"
69#include "mvm.h"
70
71const u8 iwl_mvm_ac_to_tx_fifo[] = {
72 IWL_MVM_TX_FIFO_BK,
73 IWL_MVM_TX_FIFO_BE,
74 IWL_MVM_TX_FIFO_VI,
75 IWL_MVM_TX_FIFO_VO,
76};
77
78struct iwl_mvm_mac_iface_iterator_data {
79 struct iwl_mvm *mvm;
80 struct ieee80211_vif *vif;
81 unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)];
82 unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)];
83 unsigned long used_hw_queues[BITS_TO_LONGS(IWL_MVM_FIRST_AGG_QUEUE)];
84 enum iwl_tsf_id preferred_tsf;
85 bool found_vif;
86};
87
88static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
89 struct ieee80211_vif *vif)
90{
91 struct iwl_mvm_mac_iface_iterator_data *data = _data;
92 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
93 u32 ac;
94
95 /* Iterator may already find the interface being added -- skip it */
96 if (vif == data->vif) {
97 data->found_vif = true;
98 return;
99 }
100
101 /* Mark the queues used by the vif */
102 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
103 if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
104 __set_bit(vif->hw_queue[ac], data->used_hw_queues);
105
106 if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
107 __set_bit(vif->cab_queue, data->used_hw_queues);
108
109 /*
110 * Mark MAC IDs as used by clearing the available bit, and
111 * (below) mark TSFs as used if their existing use is not
112 * compatible with the new interface type.
113 * No locking or atomic bit operations are needed since the
114 * data is on the stack of the caller function.
115 */
116 __clear_bit(mvmvif->id, data->available_mac_ids);
117
118 /*
119 * The TSF is a hardware/firmware resource, there are 4 and
120 * the driver should assign and free them as needed. However,
121 * there are cases where 2 MACs should share the same TSF ID
122 * for the purpose of clock sync, an optimization to avoid
123 * clock drift causing overlapping TBTTs/DTIMs for a GO and
124 * client in the system.
125 *
126 * The firmware will decide according to the MAC type which
127 * will be the master and slave. Clients that need to sync
128 * with a remote station will be the master, and an AP or GO
129 * will be the slave.
130 *
131 * Depending on the new interface type it can be slaved to
132 * or become the master of an existing interface.
133 */
134 switch (data->vif->type) {
135 case NL80211_IFTYPE_STATION:
136 /*
137 * The new interface is client, so if the existing one
138 * we're iterating is an AP, the TSF should be used to
139 * avoid drift between the new client and existing AP,
140 * the existing AP will get drift updates from the new
141 * client context in this case
142 */
143 if (vif->type == NL80211_IFTYPE_AP) {
144 if (data->preferred_tsf == NUM_TSF_IDS &&
145 test_bit(mvmvif->tsf_id, data->available_tsf_ids))
146 data->preferred_tsf = mvmvif->tsf_id;
147 return;
148 }
149 break;
150 case NL80211_IFTYPE_AP:
151 /*
152 * The new interface is AP/GO, so should get drift
153 * updates from an existing client or use the same
154 * TSF as an existing GO. There's no drift between
155 * TSFs internally but if they used different TSFs
156 * then a new client MAC could update one of them
157 * and cause drift that way.
158 */
159 if (vif->type == NL80211_IFTYPE_STATION ||
160 vif->type == NL80211_IFTYPE_AP) {
161 if (data->preferred_tsf == NUM_TSF_IDS &&
162 test_bit(mvmvif->tsf_id, data->available_tsf_ids))
163 data->preferred_tsf = mvmvif->tsf_id;
164 return;
165 }
166 break;
167 default:
168 /*
169 * For all other interface types there's no need to
170 * take drift into account. Either they're exclusive
171 * like IBSS and monitor, or we don't care much about
172 * their TSF (like P2P Device), but we won't be able
173 * to share the TSF resource.
174 */
175 break;
176 }
177
178 /*
179 * Unless we exited above, we can't share the TSF resource
180 * that the virtual interface we're iterating over is using
181 * with the new one, so clear the available bit and if this
182 * was the preferred one, reset that as well.
183 */
184 __clear_bit(mvmvif->tsf_id, data->available_tsf_ids);
185
186 if (data->preferred_tsf == mvmvif->tsf_id)
187 data->preferred_tsf = NUM_TSF_IDS;
188}
189
190/*
191 * Get the mask of the queus used by the vif
192 */
193u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
194 struct ieee80211_vif *vif)
195{
196 u32 qmask, ac;
197
198 if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
199 return BIT(IWL_OFFCHANNEL_QUEUE);
200
201 qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ?
202 BIT(vif->cab_queue) : 0;
203
204 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
205 if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
206 qmask |= BIT(vif->hw_queue[ac]);
207
208 return qmask;
209}
210
211static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
212 struct ieee80211_vif *vif)
213{
214 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
215 struct iwl_mvm_mac_iface_iterator_data data = {
216 .mvm = mvm,
217 .vif = vif,
218 .available_mac_ids = { (1 << NUM_MAC_INDEX_DRIVER) - 1 },
219 .available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
220 /* no preference yet */
221 .preferred_tsf = NUM_TSF_IDS,
222 .used_hw_queues = {
223 BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
224 BIT(IWL_MVM_AUX_QUEUE) |
225 BIT(IWL_MVM_CMD_QUEUE)
226 },
227 .found_vif = false,
228 };
229 u32 ac;
230 int ret;
231
232 /*
233 * Allocate a MAC ID and a TSF for this MAC, along with the queues
234 * and other resources.
235 */
236
237 /*
238 * Before the iterator, we start with all MAC IDs and TSFs available.
239 *
240 * During iteration, all MAC IDs are cleared that are in use by other
241 * virtual interfaces, and all TSF IDs are cleared that can't be used
242 * by this new virtual interface because they're used by an interface
243 * that can't share it with the new one.
244 * At the same time, we check if there's a preferred TSF in the case
245 * that we should share it with another interface.
246 */
247
248 ieee80211_iterate_active_interfaces_atomic(
249 mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
250 iwl_mvm_mac_iface_iterator, &data);
251
252 /*
253 * In the case we're getting here during resume, it's similar to
254 * firmware restart, and with RESUME_ALL the iterator will find
255 * the vif being added already.
256 * We don't want to reassign any IDs in either case since doing
257 * so would probably assign different IDs (as interfaces aren't
258 * necessarily added in the same order), but the old IDs were
259 * preserved anyway, so skip ID assignment for both resume and
260 * recovery.
261 */
262 if (data.found_vif)
263 return 0;
264
265 /* Therefore, in recovery, we can't get here */
266 WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status));
267
268 mvmvif->id = find_first_bit(data.available_mac_ids,
269 NUM_MAC_INDEX_DRIVER);
270 if (mvmvif->id == NUM_MAC_INDEX_DRIVER) {
271 IWL_ERR(mvm, "Failed to init MAC context - no free ID!\n");
272 ret = -EIO;
273 goto exit_fail;
274 }
275
276 if (data.preferred_tsf != NUM_TSF_IDS)
277 mvmvif->tsf_id = data.preferred_tsf;
278 else
279 mvmvif->tsf_id = find_first_bit(data.available_tsf_ids,
280 NUM_TSF_IDS);
281 if (mvmvif->tsf_id == NUM_TSF_IDS) {
282 IWL_ERR(mvm, "Failed to init MAC context - no free TSF!\n");
283 ret = -EIO;
284 goto exit_fail;
285 }
286
287 mvmvif->color = 0;
288
289 /* No need to allocate data queues to P2P Device MAC.*/
290 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
291 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
292 vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE;
293
294 return 0;
295 }
296
297 /* Find available queues, and allocate them to the ACs */
298 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
299 u8 queue = find_first_zero_bit(data.used_hw_queues,
300 IWL_MVM_FIRST_AGG_QUEUE);
301
302 if (queue >= IWL_MVM_FIRST_AGG_QUEUE) {
303 IWL_ERR(mvm, "Failed to allocate queue\n");
304 ret = -EIO;
305 goto exit_fail;
306 }
307
308 __set_bit(queue, data.used_hw_queues);
309 vif->hw_queue[ac] = queue;
310 }
311
312 /* Allocate the CAB queue for softAP and GO interfaces */
313 if (vif->type == NL80211_IFTYPE_AP) {
314 u8 queue = find_first_zero_bit(data.used_hw_queues,
315 IWL_MVM_FIRST_AGG_QUEUE);
316
317 if (queue >= IWL_MVM_FIRST_AGG_QUEUE) {
318 IWL_ERR(mvm, "Failed to allocate cab queue\n");
319 ret = -EIO;
320 goto exit_fail;
321 }
322
323 vif->cab_queue = queue;
324 } else {
325 vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
326 }
327
328 mvmvif->bcast_sta.sta_id = IWL_MVM_STATION_COUNT;
329 mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
330
331 INIT_LIST_HEAD(&mvmvif->time_event_data.list);
332 mvmvif->time_event_data.id = TE_MAX;
333
334 return 0;
335
336exit_fail:
337 memset(mvmvif, 0, sizeof(struct iwl_mvm_vif));
338 memset(vif->hw_queue, IEEE80211_INVAL_HW_QUEUE, sizeof(vif->hw_queue));
339 vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
340 return ret;
341}
342
343int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
344{
345 u32 ac;
346 int ret;
347
348 lockdep_assert_held(&mvm->mutex);
349
350 ret = iwl_mvm_mac_ctxt_allocate_resources(mvm, vif);
351 if (ret)
352 return ret;
353
354 switch (vif->type) {
355 case NL80211_IFTYPE_P2P_DEVICE:
356 iwl_trans_ac_txq_enable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE,
357 IWL_MVM_TX_FIFO_VO);
358 break;
359 case NL80211_IFTYPE_AP:
360 iwl_trans_ac_txq_enable(mvm->trans, vif->cab_queue,
361 IWL_MVM_TX_FIFO_VO);
362 /* fall through */
363 default:
364 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
365 iwl_trans_ac_txq_enable(mvm->trans, vif->hw_queue[ac],
366 iwl_mvm_ac_to_tx_fifo[ac]);
367 break;
368 }
369
370 return 0;
371}
372
373void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
374{
375 int ac;
376
377 lockdep_assert_held(&mvm->mutex);
378
379 switch (vif->type) {
380 case NL80211_IFTYPE_P2P_DEVICE:
381 iwl_trans_txq_disable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE);
382 break;
383 case NL80211_IFTYPE_AP:
384 iwl_trans_txq_disable(mvm->trans, vif->cab_queue);
385 /* fall through */
386 default:
387 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
388 iwl_trans_txq_disable(mvm->trans, vif->hw_queue[ac]);
389 }
390}
391
392static void iwl_mvm_ack_rates(struct iwl_mvm *mvm,
393 struct ieee80211_vif *vif,
394 enum ieee80211_band band,
395 u8 *cck_rates, u8 *ofdm_rates)
396{
397 struct ieee80211_supported_band *sband;
398 unsigned long basic = vif->bss_conf.basic_rates;
399 int lowest_present_ofdm = 100;
400 int lowest_present_cck = 100;
401 u8 cck = 0;
402 u8 ofdm = 0;
403 int i;
404
405 sband = mvm->hw->wiphy->bands[band];
406
407 for_each_set_bit(i, &basic, BITS_PER_LONG) {
408 int hw = sband->bitrates[i].hw_value;
409 if (hw >= IWL_FIRST_OFDM_RATE) {
410 ofdm |= BIT(hw - IWL_FIRST_OFDM_RATE);
411 if (lowest_present_ofdm > hw)
412 lowest_present_ofdm = hw;
413 } else {
414 BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
415
416 cck |= BIT(hw);
417 if (lowest_present_cck > hw)
418 lowest_present_cck = hw;
419 }
420 }
421
422 /*
423 * Now we've got the basic rates as bitmaps in the ofdm and cck
424 * variables. This isn't sufficient though, as there might not
425 * be all the right rates in the bitmap. E.g. if the only basic
426 * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
427 * and 6 Mbps because the 802.11-2007 standard says in 9.6:
428 *
429 * [...] a STA responding to a received frame shall transmit
430 * its Control Response frame [...] at the highest rate in the
431 * BSSBasicRateSet parameter that is less than or equal to the
432 * rate of the immediately previous frame in the frame exchange
433 * sequence ([...]) and that is of the same modulation class
434 * ([...]) as the received frame. If no rate contained in the
435 * BSSBasicRateSet parameter meets these conditions, then the
436 * control frame sent in response to a received frame shall be
437 * transmitted at the highest mandatory rate of the PHY that is
438 * less than or equal to the rate of the received frame, and
439 * that is of the same modulation class as the received frame.
440 *
441 * As a consequence, we need to add all mandatory rates that are
442 * lower than all of the basic rates to these bitmaps.
443 */
444
445 if (IWL_RATE_24M_INDEX < lowest_present_ofdm)
446 ofdm |= IWL_RATE_BIT_MSK(24) >> IWL_FIRST_OFDM_RATE;
447 if (IWL_RATE_12M_INDEX < lowest_present_ofdm)
448 ofdm |= IWL_RATE_BIT_MSK(12) >> IWL_FIRST_OFDM_RATE;
449 /* 6M already there or needed so always add */
450 ofdm |= IWL_RATE_BIT_MSK(6) >> IWL_FIRST_OFDM_RATE;
451
452 /*
453 * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
454 * Note, however:
455 * - if no CCK rates are basic, it must be ERP since there must
456 * be some basic rates at all, so they're OFDM => ERP PHY
457 * (or we're in 5 GHz, and the cck bitmap will never be used)
458 * - if 11M is a basic rate, it must be ERP as well, so add 5.5M
459 * - if 5.5M is basic, 1M and 2M are mandatory
460 * - if 2M is basic, 1M is mandatory
461 * - if 1M is basic, that's the only valid ACK rate.
462 * As a consequence, it's not as complicated as it sounds, just add
463 * any lower rates to the ACK rate bitmap.
464 */
465 if (IWL_RATE_11M_INDEX < lowest_present_cck)
466 cck |= IWL_RATE_BIT_MSK(11) >> IWL_FIRST_CCK_RATE;
467 if (IWL_RATE_5M_INDEX < lowest_present_cck)
468 cck |= IWL_RATE_BIT_MSK(5) >> IWL_FIRST_CCK_RATE;
469 if (IWL_RATE_2M_INDEX < lowest_present_cck)
470 cck |= IWL_RATE_BIT_MSK(2) >> IWL_FIRST_CCK_RATE;
471 /* 1M already there or needed so always add */
472 cck |= IWL_RATE_BIT_MSK(1) >> IWL_FIRST_CCK_RATE;
473
474 *cck_rates = cck;
475 *ofdm_rates = ofdm;
476}
477
478static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
479 struct ieee80211_vif *vif,
480 struct iwl_mac_ctx_cmd *cmd,
481 u32 action)
482{
483 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
484 struct ieee80211_chanctx_conf *chanctx;
485 u8 cck_ack_rates, ofdm_ack_rates;
486 int i;
487
488 cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
489 mvmvif->color));
490 cmd->action = cpu_to_le32(action);
491
492 switch (vif->type) {
493 case NL80211_IFTYPE_STATION:
494 if (vif->p2p)
495 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_STA);
496 else
497 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_BSS_STA);
498 break;
499 case NL80211_IFTYPE_AP:
500 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_GO);
501 break;
502 case NL80211_IFTYPE_MONITOR:
503 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_LISTENER);
504 break;
505 case NL80211_IFTYPE_P2P_DEVICE:
506 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_DEVICE);
507 break;
508 case NL80211_IFTYPE_ADHOC:
509 cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_IBSS);
510 break;
511 default:
512 WARN_ON_ONCE(1);
513 }
514
515 cmd->tsf_id = cpu_to_le32(mvmvif->tsf_id);
516
517 memcpy(cmd->node_addr, vif->addr, ETH_ALEN);
518 if (vif->bss_conf.bssid)
519 memcpy(cmd->bssid_addr, vif->bss_conf.bssid, ETH_ALEN);
520 else
521 eth_broadcast_addr(cmd->bssid_addr);
522
523 rcu_read_lock();
524 chanctx = rcu_dereference(vif->chanctx_conf);
525 iwl_mvm_ack_rates(mvm, vif, chanctx ? chanctx->def.chan->band
526 : IEEE80211_BAND_2GHZ,
527 &cck_ack_rates, &ofdm_ack_rates);
528 rcu_read_unlock();
529
530 cmd->cck_rates = cpu_to_le32((u32)cck_ack_rates);
531 cmd->ofdm_rates = cpu_to_le32((u32)ofdm_ack_rates);
532
533 cmd->cck_short_preamble =
534 cpu_to_le32(vif->bss_conf.use_short_preamble ?
535 MAC_FLG_SHORT_PREAMBLE : 0);
536 cmd->short_slot =
537 cpu_to_le32(vif->bss_conf.use_short_slot ?
538 MAC_FLG_SHORT_SLOT : 0);
539
540 for (i = 0; i < AC_NUM; i++) {
541 cmd->ac[i].cw_min = cpu_to_le16(mvmvif->queue_params[i].cw_min);
542 cmd->ac[i].cw_max = cpu_to_le16(mvmvif->queue_params[i].cw_max);
543 cmd->ac[i].aifsn = mvmvif->queue_params[i].aifs;
544 cmd->ac[i].edca_txop =
545 cpu_to_le16(mvmvif->queue_params[i].txop * 32);
546 cmd->ac[i].fifos_mask = BIT(iwl_mvm_ac_to_tx_fifo[i]);
547 }
548
549 if (vif->bss_conf.qos)
550 cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
551
552 if (vif->bss_conf.use_cts_prot)
553 cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT |
554 MAC_PROT_FLG_SELF_CTS_EN);
555
556 /*
557 * I think that we should enable these 2 flags regardless the HT PROT
558 * fields in the HT IE, but I am not sure. Someone knows whom to ask?...
559 */
560 if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
561 cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
562 cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_HT_PROT |
563 MAC_PROT_FLG_FAT_PROT);
564 }
565
566 cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
567}
568
569static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
570 struct iwl_mac_ctx_cmd *cmd)
571{
572 int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC,
573 sizeof(*cmd), cmd);
574 if (ret)
575 IWL_ERR(mvm, "Failed to send MAC context (action:%d): %d\n",
576 le32_to_cpu(cmd->action), ret);
577 return ret;
578}
579
580/*
581 * Fill the specific data for mac context of type station or p2p client
582 */
583static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm,
584 struct ieee80211_vif *vif,
585 struct iwl_mac_data_sta *ctxt_sta)
586{
587 ctxt_sta->is_assoc = cpu_to_le32(vif->bss_conf.assoc ? 1 : 0);
588
589 ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int);
590 ctxt_sta->bi_reciprocal =
591 cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int));
592 ctxt_sta->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
593 vif->bss_conf.dtim_period);
594 ctxt_sta->dtim_reciprocal =
595 cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int *
596 vif->bss_conf.dtim_period));
597
598 ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval);
599 ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid);
600}
601
602static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm,
603 struct ieee80211_vif *vif,
604 u32 action)
605{
606 struct iwl_mac_ctx_cmd cmd = {};
607
608 WARN_ON(vif->type != NL80211_IFTYPE_STATION || vif->p2p);
609
610 /* Fill the common data for all mac context types */
611 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
612
613 /* Fill the data specific for station mode */
614 iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta);
615
616 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
617}
618
619static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
620 struct ieee80211_vif *vif,
621 u32 action)
622{
623 struct iwl_mac_ctx_cmd cmd = {};
624
625 WARN_ON(vif->type != NL80211_IFTYPE_STATION || !vif->p2p);
626
627 /* Fill the common data for all mac context types */
628 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
629
630 /* Fill the data specific for station mode */
631 iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta);
632
633 cmd.p2p_sta.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
634
635 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
636}
637
638static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
639 struct ieee80211_vif *vif,
640 u32 action)
641{
642 struct iwl_mac_ctx_cmd cmd = {};
643
644 WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
645
646 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
647 /* No other data to be filled */
648 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
649}
650
651struct iwl_mvm_go_iterator_data {
652 bool go_active;
653};
654
655static void iwl_mvm_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif)
656{
657 struct iwl_mvm_go_iterator_data *data = _data;
658 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
659
660 if (vif->type == NL80211_IFTYPE_AP && vif->p2p && mvmvif->ap_active)
661 data->go_active = true;
662}
663
664static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
665 struct ieee80211_vif *vif,
666 u32 action)
667{
668 struct iwl_mac_ctx_cmd cmd = {};
669 struct iwl_mvm_go_iterator_data data = {};
670
671 WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
672
673 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
674
675 cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
676 cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROMISC);
677
678 /*
679 * This flag should be set to true when the P2P Device is
680 * discoverable and there is at least another active P2P GO. Settings
681 * this flag will allow the P2P Device to be discoverable on other
682 * channels in addition to its listen channel.
683 * Note that this flag should not be set in other cases as it opens the
684 * Rx filters on all MAC and increases the number of interrupts.
685 */
686 ieee80211_iterate_active_interfaces_atomic(
687 mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
688 iwl_mvm_go_iterator, &data);
689
690 cmd.p2p_dev.is_disc_extended = cpu_to_le32(data.go_active ? 1 : 0);
691 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
692}
693
694static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
695 struct iwl_mac_beacon_cmd *beacon_cmd,
696 u8 *beacon, u32 frame_size)
697{
698 u32 tim_idx;
699 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
700
701 /* The index is relative to frame start but we start looking at the
702 * variable-length part of the beacon. */
703 tim_idx = mgmt->u.beacon.variable - beacon;
704
705 /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
706 while ((tim_idx < (frame_size - 2)) &&
707 (beacon[tim_idx] != WLAN_EID_TIM))
708 tim_idx += beacon[tim_idx+1] + 2;
709
710 /* If TIM field was found, set variables */
711 if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
712 beacon_cmd->tim_idx = cpu_to_le32(tim_idx);
713 beacon_cmd->tim_size = cpu_to_le32((u32)beacon[tim_idx+1]);
714 } else {
715 IWL_WARN(mvm, "Unable to find TIM Element in beacon\n");
716 }
717}
718
719static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
720 struct ieee80211_vif *vif,
721 struct sk_buff *beacon)
722{
723 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
724 struct iwl_host_cmd cmd = {
725 .id = BEACON_TEMPLATE_CMD,
726 .flags = CMD_ASYNC,
727 };
728 struct iwl_mac_beacon_cmd beacon_cmd = {};
729 struct ieee80211_tx_info *info;
730 u32 beacon_skb_len;
731 u32 rate;
732
733 if (WARN_ON(!beacon))
734 return -EINVAL;
735
736 beacon_skb_len = beacon->len;
737
738 /* TODO: for now the beacon template id is set to be the mac context id.
739 * Might be better to handle it as another resource ... */
740 beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
741
742 /* Set up TX command fields */
743 beacon_cmd.tx.len = cpu_to_le16((u16)beacon_skb_len);
744 beacon_cmd.tx.sta_id = mvmvif->bcast_sta.sta_id;
745 beacon_cmd.tx.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
746 beacon_cmd.tx.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
747 TX_CMD_FLG_BT_DIS |
748 TX_CMD_FLG_TSF);
749
750 mvm->mgmt_last_antenna_idx =
751 iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant,
752 mvm->mgmt_last_antenna_idx);
753
754 beacon_cmd.tx.rate_n_flags =
755 cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
756 RATE_MCS_ANT_POS);
757
758 info = IEEE80211_SKB_CB(beacon);
759
760 if (info->band == IEEE80211_BAND_5GHZ || vif->p2p) {
761 rate = IWL_FIRST_OFDM_RATE;
762 } else {
763 rate = IWL_FIRST_CCK_RATE;
764 beacon_cmd.tx.rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK);
765 }
766 beacon_cmd.tx.rate_n_flags |=
767 cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate));
768
769 /* Set up TX beacon command fields */
770 iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd,
771 beacon->data,
772 beacon_skb_len);
773
774 /* Submit command */
775 cmd.len[0] = sizeof(beacon_cmd);
776 cmd.data[0] = &beacon_cmd;
777 cmd.dataflags[0] = 0;
778 cmd.len[1] = beacon_skb_len;
779 cmd.data[1] = beacon->data;
780 cmd.dataflags[1] = IWL_HCMD_DFL_DUP;
781
782 return iwl_mvm_send_cmd(mvm, &cmd);
783}
784
785/* The beacon template for the AP/GO context has changed and needs update */
786int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
787 struct ieee80211_vif *vif)
788{
789 struct sk_buff *beacon;
790 int ret;
791
792 WARN_ON(vif->type != NL80211_IFTYPE_AP);
793
794 beacon = ieee80211_beacon_get(mvm->hw, vif);
795 if (!beacon)
796 return -ENOMEM;
797
798 ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon);
799 dev_kfree_skb(beacon);
800 return ret;
801}
802
803/*
804 * Fill the specific data for mac context of type AP of P2P GO
805 */
806static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
807 struct ieee80211_vif *vif,
808 struct iwl_mac_data_ap *ctxt_ap)
809{
810 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
811 u32 curr_dev_time;
812
813 ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
814 ctxt_ap->bi_reciprocal =
815 cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int));
816 ctxt_ap->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
817 vif->bss_conf.dtim_period);
818 ctxt_ap->dtim_reciprocal =
819 cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int *
820 vif->bss_conf.dtim_period));
821
822 ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue);
823 curr_dev_time = iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
824 ctxt_ap->beacon_time = cpu_to_le32(curr_dev_time);
825
826 ctxt_ap->beacon_tsf = cpu_to_le64(curr_dev_time);
827
828 /* TODO: Assume that the beacon id == mac context id */
829 ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id);
830}
831
832static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
833 struct ieee80211_vif *vif,
834 u32 action)
835{
836 struct iwl_mac_ctx_cmd cmd = {};
837
838 WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p);
839
840 /* Fill the common data for all mac context types */
841 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
842
843 /* Fill the data specific for ap mode */
844 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap);
845
846 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
847}
848
849static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
850 struct ieee80211_vif *vif,
851 u32 action)
852{
853 struct iwl_mac_ctx_cmd cmd = {};
854
855 WARN_ON(vif->type != NL80211_IFTYPE_AP || !vif->p2p);
856
857 /* Fill the common data for all mac context types */
858 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
859
860 /* Fill the data specific for GO mode */
861 iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap);
862
863 cmd.go.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
864 cmd.go.opp_ps_enabled = cpu_to_le32(!!vif->bss_conf.p2p_oppps);
865
866 return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
867}
868
869static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
870 u32 action)
871{
872 switch (vif->type) {
873 case NL80211_IFTYPE_STATION:
874 if (!vif->p2p)
875 return iwl_mvm_mac_ctxt_cmd_station(mvm, vif,
876 action);
877 else
878 return iwl_mvm_mac_ctxt_cmd_p2p_client(mvm, vif,
879 action);
880 break;
881 case NL80211_IFTYPE_AP:
882 if (!vif->p2p)
883 return iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, action);
884 else
885 return iwl_mvm_mac_ctxt_cmd_go(mvm, vif, action);
886 break;
887 case NL80211_IFTYPE_MONITOR:
888 return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action);
889 case NL80211_IFTYPE_P2P_DEVICE:
890 return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action);
891 default:
892 break;
893 }
894
895 return -EOPNOTSUPP;
896}
897
898int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
899{
900 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
901 int ret;
902
903 if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
904 vif->addr, ieee80211_vif_type_p2p(vif)))
905 return -EIO;
906
907 ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD);
908 if (ret)
909 return ret;
910
911 mvmvif->uploaded = true;
912 return 0;
913}
914
915int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
916{
917 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
918
919 if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
920 vif->addr, ieee80211_vif_type_p2p(vif)))
921 return -EIO;
922
923 return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY);
924}
925
926int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
927{
928 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
929 struct iwl_mac_ctx_cmd cmd;
930 int ret;
931
932 if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
933 vif->addr, ieee80211_vif_type_p2p(vif)))
934 return -EIO;
935
936 memset(&cmd, 0, sizeof(cmd));
937
938 cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
939 mvmvif->color));
940 cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
941
942 ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC,
943 sizeof(cmd), &cmd);
944 if (ret) {
945 IWL_ERR(mvm, "Failed to remove MAC context: %d\n", ret);
946 return ret;
947 }
948
949 mvmvif->uploaded = false;
950 return 0;
951}