iwlwifi: mvm: program DTIM timings properly
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / mvm / mac80211.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 *
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#include <linux/kernel.h>
64#include <linux/slab.h>
65#include <linux/skbuff.h>
66#include <linux/netdevice.h>
67#include <linux/etherdevice.h>
68#include <net/mac80211.h>
69
70#include "iwl-op-mode.h"
71#include "iwl-io.h"
72#include "mvm.h"
73#include "sta.h"
74#include "time-event.h"
75#include "iwl-eeprom-parse.h"
76#include "fw-api-scan.h"
77#include "iwl-phy-db.h"
78
79static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
80 {
81 .max = 1,
82 .types = BIT(NL80211_IFTYPE_STATION) |
83 BIT(NL80211_IFTYPE_AP),
84 },
85 {
86 .max = 1,
87 .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
88 BIT(NL80211_IFTYPE_P2P_GO),
89 },
90 {
91 .max = 1,
92 .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
93 },
94};
95
96static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = {
97 {
98 .num_different_channels = 1,
99 .max_interfaces = 3,
100 .limits = iwl_mvm_limits,
101 .n_limits = ARRAY_SIZE(iwl_mvm_limits),
102 },
103};
104
105int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
106{
107 struct ieee80211_hw *hw = mvm->hw;
108 int num_mac, ret;
109
110 /* Tell mac80211 our characteristics */
111 hw->flags = IEEE80211_HW_SIGNAL_DBM |
112 IEEE80211_HW_SPECTRUM_MGMT |
113 IEEE80211_HW_REPORTS_TX_ACK_STATUS |
114 IEEE80211_HW_QUEUE_CONTROL |
115 IEEE80211_HW_WANT_MONITOR_VIF |
8ca151b5
JB
116 IEEE80211_HW_SUPPORTS_PS |
117 IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
d2931bbd
JB
118 IEEE80211_HW_AMPDU_AGGREGATION |
119 IEEE80211_HW_TIMING_BEACON_ONLY;
8ca151b5
JB
120
121 hw->queues = IWL_FIRST_AMPDU_QUEUE;
122 hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE;
123 hw->rate_control_algorithm = "iwl-mvm-rs";
124
125 /*
126 * Enable 11w if advertised by firmware and software crypto
127 * is not enabled (as the firmware will interpret some mgmt
128 * packets, so enabling it with software crypto isn't safe)
129 */
130 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_MFP &&
131 !iwlwifi_mod_params.sw_crypto)
132 hw->flags |= IEEE80211_HW_MFP_CAPABLE;
133
134 hw->sta_data_size = sizeof(struct iwl_mvm_sta);
135 hw->vif_data_size = sizeof(struct iwl_mvm_vif);
136 hw->chanctx_data_size = sizeof(struct iwl_mvm_phy_ctxt);
137
138 hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
139 BIT(NL80211_IFTYPE_P2P_CLIENT) |
140 BIT(NL80211_IFTYPE_AP) |
141 BIT(NL80211_IFTYPE_P2P_GO) |
142 BIT(NL80211_IFTYPE_P2P_DEVICE);
143
144 hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
145 WIPHY_FLAG_DISABLE_BEACON_HINTS |
146 WIPHY_FLAG_IBSS_RSN;
147
148 hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
149 hw->wiphy->n_iface_combinations =
150 ARRAY_SIZE(iwl_mvm_iface_combinations);
151
152 hw->wiphy->max_remain_on_channel_duration = 500;
153 hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
154
155 /* Extract MAC address */
156 memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN);
157 hw->wiphy->addresses = mvm->addresses;
158 hw->wiphy->n_addresses = 1;
159 num_mac = mvm->nvm_data->n_hw_addrs;
160 if (num_mac > 1) {
161 memcpy(mvm->addresses[1].addr, mvm->addresses[0].addr,
162 ETH_ALEN);
163 mvm->addresses[1].addr[5]++;
164 hw->wiphy->n_addresses++;
165 }
166
167 /* we create the 802.11 header and a max-length SSID element */
168 hw->wiphy->max_scan_ie_len =
169 mvm->fw->ucode_capa.max_probe_length - 24 - 34;
170 hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
171
172 if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels)
173 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
174 &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ];
175 if (mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels)
176 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
177 &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ];
178
179 hw->wiphy->hw_version = mvm->trans->hw_id;
180
181 if (iwlwifi_mod_params.power_save)
182 hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
183 else
184 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
185
186 hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
187 NL80211_FEATURE_P2P_GO_OPPPS;
188
189 mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
190
191#ifdef CONFIG_PM_SLEEP
192 if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
193 mvm->trans->ops->d3_suspend &&
194 mvm->trans->ops->d3_resume &&
195 device_can_wakeup(mvm->trans->dev)) {
196 hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
197 WIPHY_WOWLAN_DISCONNECT |
198 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
199 WIPHY_WOWLAN_RFKILL_RELEASE;
200 if (!iwlwifi_mod_params.sw_crypto)
201 hw->wiphy->wowlan.flags |=
202 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
203 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
204 WIPHY_WOWLAN_4WAY_HANDSHAKE;
205
206 hw->wiphy->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS;
207 hw->wiphy->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN;
208 hw->wiphy->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN;
209 }
210#endif
211
212 ret = iwl_mvm_leds_init(mvm);
213 if (ret)
214 return ret;
215
216 return ieee80211_register_hw(mvm->hw);
217}
218
219static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
220 struct ieee80211_tx_control *control,
221 struct sk_buff *skb)
222{
223 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
224
225 if (test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status)) {
226 IWL_DEBUG_DROP(mvm, "Dropping - RF KILL\n");
227 goto drop;
228 }
229
230 if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_OFFCHANNEL_QUEUE &&
231 !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
232 goto drop;
233
234 if (control->sta) {
235 if (iwl_mvm_tx_skb(mvm, skb, control->sta))
236 goto drop;
237 return;
238 }
239
240 if (iwl_mvm_tx_skb_non_sta(mvm, skb))
241 goto drop;
242 return;
243 drop:
244 ieee80211_free_txskb(hw, skb);
245}
246
247static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
248 struct ieee80211_vif *vif,
249 enum ieee80211_ampdu_mlme_action action,
250 struct ieee80211_sta *sta, u16 tid,
251 u16 *ssn, u8 buf_size)
252{
253 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
254 int ret;
255
256 IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n",
257 sta->addr, tid, action);
258
259 if (!(mvm->nvm_data->sku_cap_11n_enable))
260 return -EACCES;
261
262 mutex_lock(&mvm->mutex);
263
264 switch (action) {
265 case IEEE80211_AMPDU_RX_START:
266 if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) {
267 ret = -EINVAL;
268 break;
269 }
270 ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, *ssn, true);
271 break;
272 case IEEE80211_AMPDU_RX_STOP:
273 ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false);
274 break;
275 case IEEE80211_AMPDU_TX_START:
276 ret = iwl_mvm_sta_tx_agg_start(mvm, vif, sta, tid, ssn);
277 break;
278 case IEEE80211_AMPDU_TX_STOP_CONT:
279 case IEEE80211_AMPDU_TX_STOP_FLUSH:
280 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
281 ret = iwl_mvm_sta_tx_agg_stop(mvm, vif, sta, tid);
282 break;
283 case IEEE80211_AMPDU_TX_OPERATIONAL:
284 ret = iwl_mvm_sta_tx_agg_oper(mvm, vif, sta, tid, buf_size);
285 break;
286 default:
287 WARN_ON_ONCE(1);
288 ret = -EINVAL;
289 break;
290 }
291 mutex_unlock(&mvm->mutex);
292
293 return ret;
294}
295
296static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
297 struct ieee80211_vif *vif)
298{
299 struct iwl_mvm *mvm = data;
300 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
301
302 mvmvif->uploaded = false;
303 mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
304
305 /* does this make sense at all? */
306 mvmvif->color++;
307
308 spin_lock_bh(&mvm->time_event_lock);
309 iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data);
310 spin_unlock_bh(&mvm->time_event_lock);
311
312 if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
313 mvmvif->phy_ctxt = NULL;
314}
315
316static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
317{
318 iwl_trans_stop_device(mvm->trans);
319 iwl_trans_stop_hw(mvm->trans, false);
320
321 mvm->scan_status = IWL_MVM_SCAN_NONE;
322
323 /* just in case one was running */
324 ieee80211_remain_on_channel_expired(mvm->hw);
325
326 ieee80211_iterate_active_interfaces_atomic(
327 mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
328 iwl_mvm_cleanup_iterator, mvm);
329
330 memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
331 memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
332
333 ieee80211_wake_queues(mvm->hw);
334
335 mvm->vif_count = 0;
336}
337
338static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
339{
340 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
341 int ret;
342
343 mutex_lock(&mvm->mutex);
344
345 /* Clean up some internal and mac80211 state on restart */
346 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
347 iwl_mvm_restart_cleanup(mvm);
348
349 ret = iwl_mvm_up(mvm);
350 mutex_unlock(&mvm->mutex);
351
352 return ret;
353}
354
355static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw)
356{
357 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
358 int ret;
359
360 mutex_lock(&mvm->mutex);
361
362 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
363 ret = iwl_mvm_update_quotas(mvm, NULL);
364 if (ret)
365 IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n",
366 ret);
367
368 mutex_unlock(&mvm->mutex);
369}
370
371static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
372{
373 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
374
375 flush_work(&mvm->async_handlers_wk);
376
377 mutex_lock(&mvm->mutex);
378 /* async_handlers_wk is now blocked */
379
380 /*
381 * The work item could be running or queued if the
382 * ROC time event stops just as we get here.
383 */
384 cancel_work_sync(&mvm->roc_done_wk);
385
386 iwl_trans_stop_device(mvm->trans);
387 iwl_trans_stop_hw(mvm->trans, false);
388
389 iwl_mvm_async_handlers_purge(mvm);
390 /* async_handlers_list is empty and will stay empty: HW is stopped */
391
392 /* the fw is stopped, the aux sta is dead: clean up driver state */
393 iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
394
395 mutex_unlock(&mvm->mutex);
396
397 /*
398 * The worker might have been waiting for the mutex, let it run and
399 * discover that its list is now empty.
400 */
401 cancel_work_sync(&mvm->async_handlers_wk);
402}
403
404static void iwl_mvm_pm_disable_iterator(void *data, u8 *mac,
405 struct ieee80211_vif *vif)
406{
407 struct iwl_mvm *mvm = data;
408 int ret;
409
410 ret = iwl_mvm_power_disable(mvm, vif);
411 if (ret)
412 IWL_ERR(mvm, "failed to disable power management\n");
413}
414
415static void iwl_mvm_power_update_iterator(void *data, u8 *mac,
416 struct ieee80211_vif *vif)
417{
418 struct iwl_mvm *mvm = data;
419
420 iwl_mvm_power_update_mode(mvm, vif);
421}
422
423static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
424 struct ieee80211_vif *vif)
425{
426 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
427 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
428 int ret;
429
430 /*
431 * Not much to do here. The stack will not allow interface
432 * types or combinations that we didn't advertise, so we
433 * don't really have to check the types.
434 */
435
436 mutex_lock(&mvm->mutex);
437
438 /* Allocate resources for the MAC context, and add it the the fw */
439 ret = iwl_mvm_mac_ctxt_init(mvm, vif);
440 if (ret)
441 goto out_unlock;
442
443 /*
444 * The AP binding flow can be done only after the beacon
445 * template is configured (which happens only in the mac80211
446 * start_ap() flow), and adding the broadcast station can happen
447 * only after the binding.
448 * In addition, since modifying the MAC before adding a bcast
449 * station is not allowed by the FW, delay the adding of MAC context to
450 * the point where we can also add the bcast station.
451 * In short: there's not much we can do at this point, other than
452 * allocating resources :)
453 */
454 if (vif->type == NL80211_IFTYPE_AP) {
455 u32 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
456 ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta,
457 qmask);
458 if (ret) {
459 IWL_ERR(mvm, "Failed to allocate bcast sta\n");
460 goto out_release;
461 }
462
463 goto out_unlock;
464 }
465
466 /*
467 * TODO: remove this temporary code.
468 * Currently MVM FW supports power management only on single MAC.
469 * Iterate and disable PM on all active interfaces.
470 * Note: the method below does not count the new interface being added
471 * at this moment.
472 */
473 mvm->vif_count++;
474 if (mvm->vif_count > 1) {
475 IWL_DEBUG_MAC80211(mvm,
476 "Disable power on existing interfaces\n");
5360cfb2 477 ieee80211_iterate_active_interfaces_atomic(
8ca151b5
JB
478 mvm->hw,
479 IEEE80211_IFACE_ITER_NORMAL,
480 iwl_mvm_pm_disable_iterator, mvm);
481 }
482
483 ret = iwl_mvm_mac_ctxt_add(mvm, vif);
484 if (ret)
485 goto out_release;
486
487 /*
488 * Update power state on the new interface. Admittedly, based on
489 * mac80211 logics this power update will disable power management
490 */
491 iwl_mvm_power_update_mode(mvm, vif);
492
493 /*
494 * P2P_DEVICE interface does not have a channel context assigned to it,
495 * so a dedicated PHY context is allocated to it and the corresponding
496 * MAC context is bound to it at this stage.
497 */
498 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
499 struct ieee80211_channel *chan;
500 struct cfg80211_chan_def chandef;
501
502 mvmvif->phy_ctxt = &mvm->phy_ctxt_roc;
503
504 /*
505 * The channel used here isn't relevant as it's
506 * going to be overwritten as part of the ROC flow.
507 * For now use the first channel we have.
508 */
509 chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0];
510 cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
511 ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->phy_ctxt,
512 &chandef, 1, 1);
513 if (ret)
514 goto out_remove_mac;
515
516 ret = iwl_mvm_binding_add_vif(mvm, vif);
517 if (ret)
518 goto out_remove_phy;
519
520 ret = iwl_mvm_add_bcast_sta(mvm, vif, &mvmvif->bcast_sta);
521 if (ret)
522 goto out_unbind;
523
524 /* Save a pointer to p2p device vif, so it can later be used to
525 * update the p2p device MAC when a GO is started/stopped */
526 mvm->p2p_device_vif = vif;
527 }
528
529 goto out_unlock;
530
531 out_unbind:
532 iwl_mvm_binding_remove_vif(mvm, vif);
533 out_remove_phy:
534 iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt);
535 out_remove_mac:
536 mvmvif->phy_ctxt = NULL;
537 iwl_mvm_mac_ctxt_remove(mvm, vif);
538 out_release:
539 /*
540 * TODO: remove this temporary code.
541 * Currently MVM FW supports power management only on single MAC.
542 * Check if only one additional interface remains after rereasing
543 * current one. Update power mode on the remaining interface.
544 */
545 mvm->vif_count--;
546 IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
547 mvm->vif_count);
548 if (mvm->vif_count == 1) {
549 ieee80211_iterate_active_interfaces(
550 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
551 iwl_mvm_power_update_iterator, mvm);
552 }
553 iwl_mvm_mac_ctxt_release(mvm, vif);
554 out_unlock:
555 mutex_unlock(&mvm->mutex);
556
557 return ret;
558}
559
560static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
561 struct ieee80211_vif *vif)
562{
563 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
564 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
565 u32 tfd_msk = 0, ac;
566
567 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
568 if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
569 tfd_msk |= BIT(vif->hw_queue[ac]);
570
571 if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
572 tfd_msk |= BIT(vif->cab_queue);
573
574 if (tfd_msk) {
575 mutex_lock(&mvm->mutex);
576 iwl_mvm_flush_tx_path(mvm, tfd_msk, true);
577 mutex_unlock(&mvm->mutex);
578 }
579
580 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
581 /*
582 * Flush the ROC worker which will flush the OFFCHANNEL queue.
583 * We assume here that all the packets sent to the OFFCHANNEL
584 * queue are sent in ROC session.
585 */
586 flush_work(&mvm->roc_done_wk);
587 } else {
588 /*
589 * By now, all the AC queues are empty. The AGG queues are
590 * empty too. We already got all the Tx responses for all the
591 * packets in the queues. The drain work can have been
592 * triggered. Flush it. This work item takes the mutex, so kill
593 * it before we take it.
594 */
595 flush_work(&mvm->sta_drained_wk);
596 }
597
598 mutex_lock(&mvm->mutex);
599
600 /*
601 * For AP/GO interface, the tear down of the resources allocated to the
602 * interface should be handled as part of the bss_info_changed flow.
603 */
604 if (vif->type == NL80211_IFTYPE_AP) {
605 iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
606 goto out_release;
607 }
608
609 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
610 mvm->p2p_device_vif = NULL;
611 iwl_mvm_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
612 iwl_mvm_binding_remove_vif(mvm, vif);
613 iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt);
614 mvmvif->phy_ctxt = NULL;
615 }
616
617 /*
618 * TODO: remove this temporary code.
619 * Currently MVM FW supports power management only on single MAC.
620 * Check if only one additional interface remains after removing
621 * current one. Update power mode on the remaining interface.
622 */
623 if (mvm->vif_count)
624 mvm->vif_count--;
625 IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
626 mvm->vif_count);
627 if (mvm->vif_count == 1) {
628 ieee80211_iterate_active_interfaces(
629 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
630 iwl_mvm_power_update_iterator, mvm);
631 }
632
633 iwl_mvm_mac_ctxt_remove(mvm, vif);
634
635out_release:
636 iwl_mvm_mac_ctxt_release(mvm, vif);
637 mutex_unlock(&mvm->mutex);
638}
639
640static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
641{
642 return 0;
643}
644
645static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
646 unsigned int changed_flags,
647 unsigned int *total_flags,
648 u64 multicast)
649{
650 *total_flags = 0;
651}
652
653static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
654 struct ieee80211_vif *vif,
655 struct ieee80211_bss_conf *bss_conf,
656 u32 changes)
657{
658 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
659 int ret;
660
661 ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
662 if (ret)
663 IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
664
665 if (changes & BSS_CHANGED_ASSOC) {
666 if (bss_conf->assoc) {
667 /* add quota for this interface */
668 ret = iwl_mvm_update_quotas(mvm, vif);
669 if (ret) {
670 IWL_ERR(mvm, "failed to update quotas\n");
671 return;
672 }
8ca151b5
JB
673 } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
674 /* remove AP station now that the MAC is unassoc */
675 ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
676 if (ret)
677 IWL_ERR(mvm, "failed to remove AP station\n");
678 mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
679 /* remove quota for this interface */
680 ret = iwl_mvm_update_quotas(mvm, NULL);
681 if (ret)
682 IWL_ERR(mvm, "failed to update quotas\n");
683 }
210a544e
JB
684 } else if (changes & BSS_CHANGED_DTIM_PERIOD) {
685 /*
686 * We received a beacon _after_ association so
687 * remove the session protection.
688 */
689 iwl_mvm_remove_time_event(mvm, mvmvif,
690 &mvmvif->time_event_data);
8ca151b5
JB
691 } else if (changes & BSS_CHANGED_PS) {
692 /*
693 * TODO: remove this temporary code.
694 * Currently MVM FW supports power management only on single
695 * MAC. Avoid power mode update if more than one interface
696 * is active.
697 */
698 IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
699 mvm->vif_count);
700 if (mvm->vif_count == 1) {
701 ret = iwl_mvm_power_update_mode(mvm, vif);
702 if (ret)
703 IWL_ERR(mvm, "failed to update power mode\n");
704 }
705 }
706}
707
708static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
709{
710 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
711 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
712 int ret;
713
714 mutex_lock(&mvm->mutex);
715
716 /* Send the beacon template */
717 ret = iwl_mvm_mac_ctxt_beacon_changed(mvm, vif);
718 if (ret)
719 goto out_unlock;
720
721 /* Add the mac context */
722 ret = iwl_mvm_mac_ctxt_add(mvm, vif);
723 if (ret)
724 goto out_unlock;
725
726 /* Perform the binding */
727 ret = iwl_mvm_binding_add_vif(mvm, vif);
728 if (ret)
729 goto out_remove;
730
731 mvmvif->ap_active = true;
732
733 /* Send the bcast station. At this stage the TBTT and DTIM time events
734 * are added and applied to the scheduler */
735 ret = iwl_mvm_send_bcast_sta(mvm, vif, &mvmvif->bcast_sta);
736 if (ret)
737 goto out_unbind;
738
739 ret = iwl_mvm_update_quotas(mvm, vif);
740 if (ret)
741 goto out_rm_bcast;
742
743 /* Need to update the P2P Device MAC */
744 if (vif->p2p && mvm->p2p_device_vif)
745 iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif);
746
747 mutex_unlock(&mvm->mutex);
748 return 0;
749
750out_rm_bcast:
751 iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
752out_unbind:
753 iwl_mvm_binding_remove_vif(mvm, vif);
754out_remove:
755 iwl_mvm_mac_ctxt_remove(mvm, vif);
756out_unlock:
757 mutex_unlock(&mvm->mutex);
758 return ret;
759}
760
761static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
762{
763 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
764 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
765
766 mutex_lock(&mvm->mutex);
767
768 mvmvif->ap_active = false;
769
770 /* Need to update the P2P Device MAC */
771 if (vif->p2p && mvm->p2p_device_vif)
772 iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif);
773
774 iwl_mvm_update_quotas(mvm, NULL);
775 iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
776 iwl_mvm_binding_remove_vif(mvm, vif);
777 iwl_mvm_mac_ctxt_remove(mvm, vif);
778
779 mutex_unlock(&mvm->mutex);
780}
781
782static void iwl_mvm_bss_info_changed_ap(struct iwl_mvm *mvm,
783 struct ieee80211_vif *vif,
784 struct ieee80211_bss_conf *bss_conf,
785 u32 changes)
786{
787 /* Need to send a new beacon template to the FW */
788 if (changes & BSS_CHANGED_BEACON) {
789 if (iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
790 IWL_WARN(mvm, "Failed updating beacon data\n");
791 }
792}
793
794static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
795 struct ieee80211_vif *vif,
796 struct ieee80211_bss_conf *bss_conf,
797 u32 changes)
798{
799 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
800
801 mutex_lock(&mvm->mutex);
802
803 switch (vif->type) {
804 case NL80211_IFTYPE_STATION:
805 iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes);
806 break;
807 case NL80211_IFTYPE_AP:
808 iwl_mvm_bss_info_changed_ap(mvm, vif, bss_conf, changes);
809 break;
810 default:
811 /* shouldn't happen */
812 WARN_ON_ONCE(1);
813 }
814
815 mutex_unlock(&mvm->mutex);
816}
817
818static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
819 struct ieee80211_vif *vif,
820 struct cfg80211_scan_request *req)
821{
822 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
823 int ret;
824
825 if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS)
826 return -EINVAL;
827
828 mutex_lock(&mvm->mutex);
829
830 if (mvm->scan_status == IWL_MVM_SCAN_NONE)
831 ret = iwl_mvm_scan_request(mvm, vif, req);
832 else
833 ret = -EBUSY;
834
835 mutex_unlock(&mvm->mutex);
836
837 return ret;
838}
839
840static void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
841 struct ieee80211_vif *vif)
842{
843 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
844
845 mutex_lock(&mvm->mutex);
846
847 iwl_mvm_cancel_scan(mvm);
848
849 mutex_unlock(&mvm->mutex);
850}
851
852static void
853iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw,
854 struct ieee80211_sta *sta, u16 tid,
855 int num_frames,
856 enum ieee80211_frame_release_type reason,
857 bool more_data)
858{
859 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
860 struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
861
862 /* TODO: how do we tell the fw to send frames for a specific TID */
863
864 /*
865 * The fw will send EOSP notification when the last frame will be
866 * transmitted.
867 */
868 iwl_mvm_sta_modify_sleep_tx_count(mvm, mvmsta->sta_id, reason,
869 num_frames);
870}
871
872static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
873 struct ieee80211_vif *vif,
874 enum sta_notify_cmd cmd,
875 struct ieee80211_sta *sta)
876{
877 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
878 struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
879
880 switch (cmd) {
881 case STA_NOTIFY_SLEEP:
882 if (atomic_read(&mvmsta->pending_frames) > 0)
883 ieee80211_sta_block_awake(hw, sta, true);
884 /*
885 * The fw updates the STA to be asleep. Tx packets on the Tx
886 * queues to this station will not be transmitted. The fw will
887 * send a Tx response with TX_STATUS_FAIL_DEST_PS.
888 */
889 break;
890 case STA_NOTIFY_AWAKE:
891 if (WARN_ON(mvmsta->sta_id == IWL_INVALID_STATION))
892 break;
893 iwl_mvm_sta_modify_ps_wake(mvm, mvmsta->sta_id);
894 break;
895 default:
896 break;
897 }
898}
899
900static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
901 struct ieee80211_vif *vif,
902 struct ieee80211_sta *sta,
903 enum ieee80211_sta_state old_state,
904 enum ieee80211_sta_state new_state)
905{
906 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
907 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
908 int ret;
909
910 IWL_DEBUG_MAC80211(mvm, "station %pM state change %d->%d\n",
911 sta->addr, old_state, new_state);
912
913 /* this would be a mac80211 bug ... but don't crash */
914 if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
915 return -EINVAL;
916
917 /* if a STA is being removed, reuse its ID */
918 flush_work(&mvm->sta_drained_wk);
919
920 mutex_lock(&mvm->mutex);
921 if (old_state == IEEE80211_STA_NOTEXIST &&
922 new_state == IEEE80211_STA_NONE) {
923 ret = iwl_mvm_add_sta(mvm, vif, sta);
924 } else if (old_state == IEEE80211_STA_NONE &&
925 new_state == IEEE80211_STA_AUTH) {
926 ret = 0;
927 } else if (old_state == IEEE80211_STA_AUTH &&
928 new_state == IEEE80211_STA_ASSOC) {
7a453973
JB
929 ret = iwl_mvm_update_sta(mvm, vif, sta);
930 if (ret == 0)
931 iwl_mvm_rs_rate_init(mvm, sta,
932 mvmvif->phy_ctxt->channel->band);
8ca151b5
JB
933 } else if (old_state == IEEE80211_STA_ASSOC &&
934 new_state == IEEE80211_STA_AUTHORIZED) {
935 ret = 0;
936 } else if (old_state == IEEE80211_STA_AUTHORIZED &&
937 new_state == IEEE80211_STA_ASSOC) {
938 ret = 0;
939 } else if (old_state == IEEE80211_STA_ASSOC &&
940 new_state == IEEE80211_STA_AUTH) {
941 ret = 0;
942 } else if (old_state == IEEE80211_STA_AUTH &&
943 new_state == IEEE80211_STA_NONE) {
944 ret = 0;
945 } else if (old_state == IEEE80211_STA_NONE &&
946 new_state == IEEE80211_STA_NOTEXIST) {
947 ret = iwl_mvm_rm_sta(mvm, vif, sta);
948 } else {
949 ret = -EIO;
950 }
951 mutex_unlock(&mvm->mutex);
952
953 return ret;
954}
955
956static int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
957{
958 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
959
960 mvm->rts_threshold = value;
961
962 return 0;
963}
964
965static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
966 struct ieee80211_vif *vif, u16 ac,
967 const struct ieee80211_tx_queue_params *params)
968{
969 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
970 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
971
972 mvmvif->queue_params[ac] = *params;
973
974 /*
975 * No need to update right away, we'll get BSS_CHANGED_QOS
976 * The exception is P2P_DEVICE interface which needs immediate update.
977 */
978 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
979 int ret;
980
981 mutex_lock(&mvm->mutex);
982 ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
983 mutex_unlock(&mvm->mutex);
984 return ret;
985 }
986 return 0;
987}
988
989static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
990 struct ieee80211_vif *vif)
991{
992 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
993 u32 duration = min(IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS,
994 200 + vif->bss_conf.beacon_int);
995 u32 min_duration = min(IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS,
996 100 + vif->bss_conf.beacon_int);
997
998 if (WARN_ON_ONCE(vif->bss_conf.assoc))
999 return;
1000
1001 mutex_lock(&mvm->mutex);
1002 /* Try really hard to protect the session and hear a beacon */
1003 iwl_mvm_protect_session(mvm, vif, duration, min_duration);
1004 mutex_unlock(&mvm->mutex);
1005}
1006
1007static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
1008 enum set_key_cmd cmd,
1009 struct ieee80211_vif *vif,
1010 struct ieee80211_sta *sta,
1011 struct ieee80211_key_conf *key)
1012{
1013 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1014 int ret;
1015
1016 if (iwlwifi_mod_params.sw_crypto) {
1017 IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n");
1018 return -EOPNOTSUPP;
1019 }
1020
1021 switch (key->cipher) {
1022 case WLAN_CIPHER_SUITE_TKIP:
1023 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
1024 /* fall-through */
1025 case WLAN_CIPHER_SUITE_CCMP:
1026 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
1027 break;
1028 case WLAN_CIPHER_SUITE_AES_CMAC:
1029 WARN_ON_ONCE(!(hw->flags & IEEE80211_HW_MFP_CAPABLE));
1030 break;
1031 case WLAN_CIPHER_SUITE_WEP40:
1032 case WLAN_CIPHER_SUITE_WEP104:
1033 /*
1034 * Support for TX only, at least for now, so accept
1035 * the key and do nothing else. Then mac80211 will
1036 * pass it for TX but we don't have to use it for RX.
1037 */
1038 return 0;
1039 default:
1040 return -EOPNOTSUPP;
1041 }
1042
1043 mutex_lock(&mvm->mutex);
1044
1045 switch (cmd) {
1046 case SET_KEY:
1047 IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
1048 ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false);
1049 if (ret) {
1050 IWL_WARN(mvm, "set key failed\n");
1051 /*
1052 * can't add key for RX, but we don't need it
1053 * in the device for TX so still return 0
1054 */
1055 ret = 0;
1056 }
1057
1058 break;
1059 case DISABLE_KEY:
1060 IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
1061 ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
1062 break;
1063 default:
1064 ret = -EINVAL;
1065 }
1066
1067 mutex_unlock(&mvm->mutex);
1068 return ret;
1069}
1070
1071static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
1072 struct ieee80211_vif *vif,
1073 struct ieee80211_key_conf *keyconf,
1074 struct ieee80211_sta *sta,
1075 u32 iv32, u16 *phase1key)
1076{
1077 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1078
1079 iwl_mvm_update_tkip_key(mvm, vif, keyconf, sta, iv32, phase1key);
1080}
1081
1082
1083static int iwl_mvm_roc(struct ieee80211_hw *hw,
1084 struct ieee80211_vif *vif,
1085 struct ieee80211_channel *channel,
1086 int duration)
1087{
1088 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1089 struct cfg80211_chan_def chandef;
1090 int ret;
1091
1092 if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
1093 IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type);
1094 return -EINVAL;
1095 }
1096
1097 IWL_DEBUG_MAC80211(mvm, "enter (%d, %d)\n", channel->hw_value,
1098 duration);
1099
1100 mutex_lock(&mvm->mutex);
1101
1102 cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
1103 ret = iwl_mvm_phy_ctxt_changed(mvm, &mvm->phy_ctxt_roc,
1104 &chandef, 1, 1);
1105
1106 /* Schedule the time events */
1107 ret = iwl_mvm_start_p2p_roc(mvm, vif, duration);
1108
1109 mutex_unlock(&mvm->mutex);
1110 IWL_DEBUG_MAC80211(mvm, "leave\n");
1111
1112 return ret;
1113}
1114
1115static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw)
1116{
1117 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1118
1119 IWL_DEBUG_MAC80211(mvm, "enter\n");
1120
1121 mutex_lock(&mvm->mutex);
1122 iwl_mvm_stop_p2p_roc(mvm);
1123 mutex_unlock(&mvm->mutex);
1124
1125 IWL_DEBUG_MAC80211(mvm, "leave\n");
1126 return 0;
1127}
1128
1129static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
1130 struct ieee80211_chanctx_conf *ctx)
1131{
1132 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1133 struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv;
1134 int ret;
1135
1136 mutex_lock(&mvm->mutex);
1137
1138 IWL_DEBUG_MAC80211(mvm, "Add PHY context\n");
1139 ret = iwl_mvm_phy_ctxt_add(mvm, phy_ctxt, &ctx->def,
1140 ctx->rx_chains_static,
1141 ctx->rx_chains_dynamic);
1142 mutex_unlock(&mvm->mutex);
1143 return ret;
1144}
1145
1146static void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
1147 struct ieee80211_chanctx_conf *ctx)
1148{
1149 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1150 struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv;
1151
1152 mutex_lock(&mvm->mutex);
1153 iwl_mvm_phy_ctxt_remove(mvm, phy_ctxt);
1154 mutex_unlock(&mvm->mutex);
1155}
1156
1157static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
1158 struct ieee80211_chanctx_conf *ctx,
1159 u32 changed)
1160{
1161 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1162 struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv;
1163
1164 mutex_lock(&mvm->mutex);
1165 iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def,
1166 ctx->rx_chains_static,
1167 ctx->rx_chains_dynamic);
1168 mutex_unlock(&mvm->mutex);
1169}
1170
1171static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
1172 struct ieee80211_vif *vif,
1173 struct ieee80211_chanctx_conf *ctx)
1174{
1175 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1176 struct iwl_mvm_phy_ctxt *phyctx = (void *)ctx->drv_priv;
1177 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1178 int ret;
1179
1180 mutex_lock(&mvm->mutex);
1181
1182 mvmvif->phy_ctxt = phyctx;
1183
1184 switch (vif->type) {
1185 case NL80211_IFTYPE_AP:
1186 /*
1187 * The AP binding flow is handled as part of the start_ap flow
1188 * (in bss_info_changed).
1189 */
1190 ret = 0;
1191 goto out_unlock;
1192 case NL80211_IFTYPE_STATION:
1193 case NL80211_IFTYPE_ADHOC:
1194 case NL80211_IFTYPE_MONITOR:
1195 break;
1196 default:
1197 ret = -EINVAL;
1198 goto out_unlock;
1199 }
1200
1201 ret = iwl_mvm_binding_add_vif(mvm, vif);
1202 if (ret)
1203 goto out_unlock;
1204
1205 /*
1206 * Setting the quota at this stage is only required for monitor
1207 * interfaces. For the other types, the bss_info changed flow
1208 * will handle quota settings.
1209 */
1210 if (vif->type == NL80211_IFTYPE_MONITOR) {
1211 ret = iwl_mvm_update_quotas(mvm, vif);
1212 if (ret)
1213 goto out_remove_binding;
1214 }
1215
1216 goto out_unlock;
1217
1218 out_remove_binding:
1219 iwl_mvm_binding_remove_vif(mvm, vif);
1220 out_unlock:
1221 mutex_unlock(&mvm->mutex);
1222 if (ret)
1223 mvmvif->phy_ctxt = NULL;
1224 return ret;
1225}
1226
1227static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
1228 struct ieee80211_vif *vif,
1229 struct ieee80211_chanctx_conf *ctx)
1230{
1231 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1232 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1233
1234 mutex_lock(&mvm->mutex);
1235
1236 iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data);
1237
1238 if (vif->type == NL80211_IFTYPE_AP)
1239 goto out_unlock;
1240
1241 iwl_mvm_binding_remove_vif(mvm, vif);
1242 switch (vif->type) {
1243 case NL80211_IFTYPE_MONITOR:
1244 iwl_mvm_update_quotas(mvm, vif);
1245 break;
1246 default:
1247 break;
1248 }
1249
1250out_unlock:
1251 mvmvif->phy_ctxt = NULL;
1252 mutex_unlock(&mvm->mutex);
1253}
1254
1255static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
1256 struct ieee80211_sta *sta,
1257 bool set)
1258{
1259 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1260 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
1261
1262 if (!mvm_sta || !mvm_sta->vif) {
1263 IWL_ERR(mvm, "Station is not associated to a vif\n");
1264 return -EINVAL;
1265 }
1266
1267 return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif);
1268}
1269
1270struct ieee80211_ops iwl_mvm_hw_ops = {
1271 .tx = iwl_mvm_mac_tx,
1272 .ampdu_action = iwl_mvm_mac_ampdu_action,
1273 .start = iwl_mvm_mac_start,
1274 .restart_complete = iwl_mvm_mac_restart_complete,
1275 .stop = iwl_mvm_mac_stop,
1276 .add_interface = iwl_mvm_mac_add_interface,
1277 .remove_interface = iwl_mvm_mac_remove_interface,
1278 .config = iwl_mvm_mac_config,
1279 .configure_filter = iwl_mvm_configure_filter,
1280 .bss_info_changed = iwl_mvm_bss_info_changed,
1281 .hw_scan = iwl_mvm_mac_hw_scan,
1282 .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
1283 .sta_state = iwl_mvm_mac_sta_state,
1284 .sta_notify = iwl_mvm_mac_sta_notify,
1285 .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
1286 .set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
1287 .conf_tx = iwl_mvm_mac_conf_tx,
1288 .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
1289 .set_key = iwl_mvm_mac_set_key,
1290 .update_tkip_key = iwl_mvm_mac_update_tkip_key,
1291 .remain_on_channel = iwl_mvm_roc,
1292 .cancel_remain_on_channel = iwl_mvm_cancel_roc,
1293
1294 .add_chanctx = iwl_mvm_add_chanctx,
1295 .remove_chanctx = iwl_mvm_remove_chanctx,
1296 .change_chanctx = iwl_mvm_change_chanctx,
1297 .assign_vif_chanctx = iwl_mvm_assign_vif_chanctx,
1298 .unassign_vif_chanctx = iwl_mvm_unassign_vif_chanctx,
1299
1300 .start_ap = iwl_mvm_start_ap,
1301 .stop_ap = iwl_mvm_stop_ap,
1302
1303 .set_tim = iwl_mvm_set_tim,
1304
1305#ifdef CONFIG_PM_SLEEP
1306 /* look at d3.c */
1307 .suspend = iwl_mvm_suspend,
1308 .resume = iwl_mvm_resume,
1309 .set_wakeup = iwl_mvm_set_wakeup,
1310 .set_rekey_data = iwl_mvm_set_rekey_data,
1311#if IS_ENABLED(CONFIG_IPV6)
1312 .ipv6_addr_change = iwl_mvm_ipv6_addr_change,
1313#endif
1314 .set_default_unicast_key = iwl_mvm_set_default_unicast_key,
1315#endif
1316};
This page took 0.081274 seconds and 5 git commands to generate.