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