.. | .. |
---|
5 | 5 | * |
---|
6 | 6 | * GPL LICENSE SUMMARY |
---|
7 | 7 | * |
---|
8 | | - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
---|
9 | 8 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
---|
10 | 9 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
---|
| 10 | + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation |
---|
11 | 11 | * |
---|
12 | 12 | * This program is free software; you can redistribute it and/or modify |
---|
13 | 13 | * it under the terms of version 2 of the GNU General Public License as |
---|
.. | .. |
---|
18 | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
19 | 19 | * General Public License for more details. |
---|
20 | 20 | * |
---|
21 | | - * You should have received a copy of the GNU General Public License |
---|
22 | | - * along with this program; if not, write to the Free Software |
---|
23 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, |
---|
24 | | - * USA |
---|
25 | | - * |
---|
26 | 21 | * The full GNU General Public License is included in this distribution |
---|
27 | 22 | * in the file called COPYING. |
---|
28 | 23 | * |
---|
.. | .. |
---|
32 | 27 | * |
---|
33 | 28 | * BSD LICENSE |
---|
34 | 29 | * |
---|
35 | | - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
---|
36 | 30 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
---|
37 | 31 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
---|
| 32 | + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation |
---|
38 | 33 | * All rights reserved. |
---|
39 | 34 | * |
---|
40 | 35 | * Redistribution and use in source and binary forms, with or without |
---|
.. | .. |
---|
100 | 95 | bool found_vif; |
---|
101 | 96 | }; |
---|
102 | 97 | |
---|
103 | | -struct iwl_mvm_hw_queues_iface_iterator_data { |
---|
104 | | - struct ieee80211_vif *exclude_vif; |
---|
105 | | - unsigned long used_hw_queues; |
---|
106 | | -}; |
---|
107 | | - |
---|
108 | 98 | static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac, |
---|
109 | 99 | struct ieee80211_vif *vif) |
---|
110 | 100 | { |
---|
.. | .. |
---|
125 | 115 | * client in the system. |
---|
126 | 116 | * |
---|
127 | 117 | * The firmware will decide according to the MAC type which |
---|
128 | | - * will be the master and slave. Clients that need to sync |
---|
129 | | - * with a remote station will be the master, and an AP or GO |
---|
130 | | - * will be the slave. |
---|
| 118 | + * will be the leader and follower. Clients that need to sync |
---|
| 119 | + * with a remote station will be the leader, and an AP or GO |
---|
| 120 | + * will be the follower. |
---|
131 | 121 | * |
---|
132 | | - * Depending on the new interface type it can be slaved to |
---|
133 | | - * or become the master of an existing interface. |
---|
| 122 | + * Depending on the new interface type it can be following |
---|
| 123 | + * or become the leader of an existing interface. |
---|
134 | 124 | */ |
---|
135 | 125 | switch (data->vif->type) { |
---|
136 | 126 | case NL80211_IFTYPE_STATION: |
---|
.. | .. |
---|
211 | 201 | data->preferred_tsf = NUM_TSF_IDS; |
---|
212 | 202 | } |
---|
213 | 203 | |
---|
214 | | -/* |
---|
215 | | - * Get the mask of the queues used by the vif |
---|
216 | | - */ |
---|
217 | | -u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif) |
---|
218 | | -{ |
---|
219 | | - u32 qmask = 0, ac; |
---|
220 | | - |
---|
221 | | - if (vif->type == NL80211_IFTYPE_P2P_DEVICE) |
---|
222 | | - return BIT(IWL_MVM_OFFCHANNEL_QUEUE); |
---|
223 | | - |
---|
224 | | - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
---|
225 | | - if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE) |
---|
226 | | - qmask |= BIT(vif->hw_queue[ac]); |
---|
227 | | - } |
---|
228 | | - |
---|
229 | | - if (vif->type == NL80211_IFTYPE_AP || |
---|
230 | | - vif->type == NL80211_IFTYPE_ADHOC) |
---|
231 | | - qmask |= BIT(vif->cab_queue); |
---|
232 | | - |
---|
233 | | - return qmask; |
---|
234 | | -} |
---|
235 | | - |
---|
236 | | -static void iwl_mvm_iface_hw_queues_iter(void *_data, u8 *mac, |
---|
237 | | - struct ieee80211_vif *vif) |
---|
238 | | -{ |
---|
239 | | - struct iwl_mvm_hw_queues_iface_iterator_data *data = _data; |
---|
240 | | - |
---|
241 | | - /* exclude the given vif */ |
---|
242 | | - if (vif == data->exclude_vif) |
---|
243 | | - return; |
---|
244 | | - |
---|
245 | | - data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif); |
---|
246 | | -} |
---|
247 | | - |
---|
248 | | -unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, |
---|
249 | | - struct ieee80211_vif *exclude_vif) |
---|
250 | | -{ |
---|
251 | | - struct iwl_mvm_hw_queues_iface_iterator_data data = { |
---|
252 | | - .exclude_vif = exclude_vif, |
---|
253 | | - .used_hw_queues = |
---|
254 | | - BIT(IWL_MVM_OFFCHANNEL_QUEUE) | |
---|
255 | | - BIT(mvm->aux_queue) | |
---|
256 | | - BIT(IWL_MVM_DQA_GCAST_QUEUE), |
---|
257 | | - }; |
---|
258 | | - |
---|
259 | | - lockdep_assert_held(&mvm->mutex); |
---|
260 | | - |
---|
261 | | - /* mark all VIF used hw queues */ |
---|
262 | | - ieee80211_iterate_active_interfaces_atomic( |
---|
263 | | - mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
---|
264 | | - iwl_mvm_iface_hw_queues_iter, &data); |
---|
265 | | - |
---|
266 | | - return data.used_hw_queues; |
---|
267 | | -} |
---|
268 | | - |
---|
269 | 204 | static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, |
---|
270 | 205 | struct ieee80211_vif *vif) |
---|
271 | 206 | { |
---|
.. | .. |
---|
325 | 260 | .preferred_tsf = NUM_TSF_IDS, |
---|
326 | 261 | .found_vif = false, |
---|
327 | 262 | }; |
---|
328 | | - u32 ac; |
---|
329 | | - int ret, i, queue_limit; |
---|
330 | | - unsigned long used_hw_queues; |
---|
| 263 | + int ret, i; |
---|
331 | 264 | |
---|
332 | 265 | lockdep_assert_held(&mvm->mutex); |
---|
333 | 266 | |
---|
.. | .. |
---|
362 | 295 | ieee80211_iterate_active_interfaces_atomic( |
---|
363 | 296 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
---|
364 | 297 | iwl_mvm_mac_iface_iterator, &data); |
---|
365 | | - |
---|
366 | | - used_hw_queues = iwl_mvm_get_used_hw_queues(mvm, vif); |
---|
367 | 298 | |
---|
368 | 299 | /* |
---|
369 | 300 | * In the case we're getting here during resume, it's similar to |
---|
.. | .. |
---|
406 | 337 | INIT_LIST_HEAD(&mvmvif->time_event_data.list); |
---|
407 | 338 | mvmvif->time_event_data.id = TE_MAX; |
---|
408 | 339 | |
---|
409 | | - /* No need to allocate data queues to P2P Device MAC.*/ |
---|
410 | | - if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { |
---|
411 | | - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
---|
412 | | - vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE; |
---|
413 | | - |
---|
| 340 | + /* No need to allocate data queues to P2P Device MAC and NAN.*/ |
---|
| 341 | + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) |
---|
414 | 342 | return 0; |
---|
415 | | - } |
---|
416 | | - |
---|
417 | | - /* |
---|
418 | | - * queues in mac80211 almost entirely independent of |
---|
419 | | - * the ones here - no real limit |
---|
420 | | - */ |
---|
421 | | - queue_limit = IEEE80211_MAX_QUEUES; |
---|
422 | | - BUILD_BUG_ON(IEEE80211_MAX_QUEUES > |
---|
423 | | - BITS_PER_BYTE * |
---|
424 | | - sizeof(mvm->hw_queue_to_mac80211[0])); |
---|
425 | | - |
---|
426 | | - /* |
---|
427 | | - * Find available queues, and allocate them to the ACs. When in |
---|
428 | | - * DQA-mode they aren't really used, and this is done only so the |
---|
429 | | - * mac80211 ieee80211_check_queues() function won't fail |
---|
430 | | - */ |
---|
431 | | - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
---|
432 | | - u8 queue = find_first_zero_bit(&used_hw_queues, queue_limit); |
---|
433 | | - |
---|
434 | | - if (queue >= queue_limit) { |
---|
435 | | - IWL_ERR(mvm, "Failed to allocate queue\n"); |
---|
436 | | - ret = -EIO; |
---|
437 | | - goto exit_fail; |
---|
438 | | - } |
---|
439 | | - |
---|
440 | | - __set_bit(queue, &used_hw_queues); |
---|
441 | | - vif->hw_queue[ac] = queue; |
---|
442 | | - } |
---|
443 | 343 | |
---|
444 | 344 | /* Allocate the CAB queue for softAP and GO interfaces */ |
---|
445 | 345 | if (vif->type == NL80211_IFTYPE_AP || |
---|
.. | .. |
---|
449 | 349 | * queue value (when queue is enabled). |
---|
450 | 350 | */ |
---|
451 | 351 | mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; |
---|
452 | | - vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; |
---|
453 | | - } else { |
---|
454 | | - vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; |
---|
455 | 352 | } |
---|
456 | 353 | |
---|
457 | 354 | mvmvif->bcast_sta.sta_id = IWL_MVM_INVALID_STA; |
---|
.. | .. |
---|
465 | 362 | |
---|
466 | 363 | exit_fail: |
---|
467 | 364 | memset(mvmvif, 0, sizeof(struct iwl_mvm_vif)); |
---|
468 | | - memset(vif->hw_queue, IEEE80211_INVAL_HW_QUEUE, sizeof(vif->hw_queue)); |
---|
469 | | - vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; |
---|
470 | 365 | return ret; |
---|
471 | 366 | } |
---|
472 | 367 | |
---|
.. | .. |
---|
657 | 552 | cpu_to_le32(vif->bss_conf.use_short_slot ? |
---|
658 | 553 | MAC_FLG_SHORT_SLOT : 0); |
---|
659 | 554 | |
---|
660 | | - cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP); |
---|
| 555 | + cmd->filter_flags = 0; |
---|
661 | 556 | |
---|
662 | 557 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
---|
663 | 558 | u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i); |
---|
| 559 | + u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i); |
---|
664 | 560 | |
---|
665 | | - cmd->ac[txf].cw_min = |
---|
| 561 | + cmd->ac[ucode_ac].cw_min = |
---|
666 | 562 | cpu_to_le16(mvmvif->queue_params[i].cw_min); |
---|
667 | | - cmd->ac[txf].cw_max = |
---|
| 563 | + cmd->ac[ucode_ac].cw_max = |
---|
668 | 564 | cpu_to_le16(mvmvif->queue_params[i].cw_max); |
---|
669 | | - cmd->ac[txf].edca_txop = |
---|
| 565 | + cmd->ac[ucode_ac].edca_txop = |
---|
670 | 566 | cpu_to_le16(mvmvif->queue_params[i].txop * 32); |
---|
671 | | - cmd->ac[txf].aifsn = mvmvif->queue_params[i].aifs; |
---|
672 | | - cmd->ac[txf].fifos_mask = BIT(txf); |
---|
| 567 | + cmd->ac[ucode_ac].aifsn = mvmvif->queue_params[i].aifs; |
---|
| 568 | + cmd->ac[ucode_ac].fifos_mask = BIT(txf); |
---|
673 | 569 | } |
---|
674 | 570 | |
---|
675 | 571 | if (vif->bss_conf.qos) |
---|
.. | .. |
---|
725 | 621 | /* We need the dtim_period to set the MAC as associated */ |
---|
726 | 622 | if (vif->bss_conf.assoc && vif->bss_conf.dtim_period && |
---|
727 | 623 | !force_assoc_off) { |
---|
| 624 | + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
---|
| 625 | + u8 ap_sta_id = mvmvif->ap_sta_id; |
---|
728 | 626 | u32 dtim_offs; |
---|
729 | 627 | |
---|
730 | 628 | /* |
---|
.. | .. |
---|
760 | 658 | dtim_offs); |
---|
761 | 659 | |
---|
762 | 660 | ctxt_sta->is_assoc = cpu_to_le32(1); |
---|
| 661 | + |
---|
| 662 | + /* |
---|
| 663 | + * allow multicast data frames only as long as the station is |
---|
| 664 | + * authorized, i.e., GTK keys are already installed (if needed) |
---|
| 665 | + */ |
---|
| 666 | + if (ap_sta_id < mvm->fw->ucode_capa.num_stations) { |
---|
| 667 | + struct ieee80211_sta *sta; |
---|
| 668 | + |
---|
| 669 | + rcu_read_lock(); |
---|
| 670 | + |
---|
| 671 | + sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]); |
---|
| 672 | + if (!IS_ERR_OR_NULL(sta)) { |
---|
| 673 | + struct iwl_mvm_sta *mvmsta = |
---|
| 674 | + iwl_mvm_sta_from_mac80211(sta); |
---|
| 675 | + |
---|
| 676 | + if (mvmsta->sta_state == |
---|
| 677 | + IEEE80211_STA_AUTHORIZED) |
---|
| 678 | + cmd.filter_flags |= |
---|
| 679 | + cpu_to_le32(MAC_FILTER_ACCEPT_GRP); |
---|
| 680 | + } |
---|
| 681 | + |
---|
| 682 | + rcu_read_unlock(); |
---|
| 683 | + } |
---|
763 | 684 | } else { |
---|
764 | 685 | ctxt_sta->is_assoc = cpu_to_le32(0); |
---|
765 | 686 | |
---|
.. | .. |
---|
770 | 691 | } |
---|
771 | 692 | |
---|
772 | 693 | ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int); |
---|
773 | | - ctxt_sta->bi_reciprocal = |
---|
774 | | - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int)); |
---|
775 | 694 | ctxt_sta->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int * |
---|
776 | 695 | vif->bss_conf.dtim_period); |
---|
777 | | - ctxt_sta->dtim_reciprocal = |
---|
778 | | - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int * |
---|
779 | | - vif->bss_conf.dtim_period)); |
---|
780 | 696 | |
---|
781 | 697 | ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); |
---|
782 | 698 | ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); |
---|
.. | .. |
---|
784 | 700 | if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p) |
---|
785 | 701 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); |
---|
786 | 702 | |
---|
787 | | - if (vif->bss_conf.assoc && vif->bss_conf.he_support && |
---|
788 | | - !iwlwifi_mod_params.disable_11ax) |
---|
| 703 | + if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) { |
---|
789 | 704 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX); |
---|
| 705 | + if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT) { |
---|
| 706 | + ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED); |
---|
| 707 | + if (vif->bss_conf.twt_protected) |
---|
| 708 | + ctxt_sta->data_policy |= |
---|
| 709 | + cpu_to_le32(PROTECTED_TWT_SUPPORTED); |
---|
| 710 | + } |
---|
| 711 | + } |
---|
| 712 | + |
---|
790 | 713 | |
---|
791 | 714 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
---|
792 | 715 | } |
---|
.. | .. |
---|
807 | 730 | MAC_FILTER_IN_CONTROL_AND_MGMT | |
---|
808 | 731 | MAC_FILTER_IN_BEACON | |
---|
809 | 732 | MAC_FILTER_IN_PROBE_REQUEST | |
---|
810 | | - MAC_FILTER_IN_CRC32); |
---|
| 733 | + MAC_FILTER_IN_CRC32 | |
---|
| 734 | + MAC_FILTER_ACCEPT_GRP); |
---|
811 | 735 | ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS); |
---|
812 | 736 | |
---|
813 | 737 | /* Allocate sniffer station */ |
---|
.. | .. |
---|
831 | 755 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action); |
---|
832 | 756 | |
---|
833 | 757 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON | |
---|
834 | | - MAC_FILTER_IN_PROBE_REQUEST); |
---|
| 758 | + MAC_FILTER_IN_PROBE_REQUEST | |
---|
| 759 | + MAC_FILTER_ACCEPT_GRP); |
---|
835 | 760 | |
---|
836 | 761 | /* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */ |
---|
837 | 762 | cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int); |
---|
838 | | - cmd.ibss.bi_reciprocal = |
---|
839 | | - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int)); |
---|
840 | 763 | |
---|
841 | 764 | /* TODO: Assumes that the beacon id == mac context id */ |
---|
842 | 765 | cmd.ibss.beacon_template = cpu_to_le32(mvmvif->id); |
---|
.. | .. |
---|
869 | 792 | |
---|
870 | 793 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action); |
---|
871 | 794 | |
---|
872 | | - cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); |
---|
873 | | - |
---|
874 | 795 | /* Override the filter flags to accept only probe requests */ |
---|
875 | 796 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); |
---|
876 | 797 | |
---|
.. | .. |
---|
890 | 811 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
---|
891 | 812 | } |
---|
892 | 813 | |
---|
893 | | -static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm, |
---|
894 | | - __le32 *tim_index, __le32 *tim_size, |
---|
895 | | - u8 *beacon, u32 frame_size) |
---|
| 814 | +void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm, |
---|
| 815 | + __le32 *tim_index, __le32 *tim_size, |
---|
| 816 | + u8 *beacon, u32 frame_size) |
---|
896 | 817 | { |
---|
897 | 818 | u32 tim_idx; |
---|
898 | 819 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon; |
---|
.. | .. |
---|
932 | 853 | return ie - beacon; |
---|
933 | 854 | } |
---|
934 | 855 | |
---|
935 | | -static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, |
---|
936 | | - struct ieee80211_vif *vif) |
---|
| 856 | +u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, |
---|
| 857 | + struct ieee80211_vif *vif) |
---|
937 | 858 | { |
---|
938 | 859 | u8 rate; |
---|
939 | | - |
---|
940 | | - if (info->band == NL80211_BAND_5GHZ || vif->p2p) |
---|
941 | | - rate = IWL_FIRST_OFDM_RATE; |
---|
942 | | - else |
---|
| 860 | + if (info->band == NL80211_BAND_2GHZ && !vif->p2p) |
---|
943 | 861 | rate = IWL_FIRST_CCK_RATE; |
---|
| 862 | + else |
---|
| 863 | + rate = IWL_FIRST_OFDM_RATE; |
---|
944 | 864 | |
---|
945 | 865 | return rate; |
---|
946 | 866 | } |
---|
.. | .. |
---|
968 | 888 | tx->tx_flags = cpu_to_le32(tx_flags); |
---|
969 | 889 | |
---|
970 | 890 | if (!fw_has_capa(&mvm->fw->ucode_capa, |
---|
971 | | - IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) { |
---|
972 | | - mvm->mgmt_last_antenna_idx = |
---|
973 | | - iwl_mvm_next_antenna(mvm, iwl_mvm_get_valid_tx_ant(mvm), |
---|
974 | | - mvm->mgmt_last_antenna_idx); |
---|
975 | | - } |
---|
| 891 | + IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) |
---|
| 892 | + iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx); |
---|
976 | 893 | |
---|
977 | 894 | tx->rate_n_flags = |
---|
978 | 895 | cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) << |
---|
.. | .. |
---|
986 | 903 | |
---|
987 | 904 | } |
---|
988 | 905 | |
---|
989 | | -static int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, |
---|
990 | | - struct sk_buff *beacon, |
---|
991 | | - void *data, int len) |
---|
| 906 | +int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, |
---|
| 907 | + struct sk_buff *beacon, |
---|
| 908 | + void *data, int len) |
---|
992 | 909 | { |
---|
993 | 910 | struct iwl_host_cmd cmd = { |
---|
994 | 911 | .id = BEACON_TEMPLATE_CMD, |
---|
.. | .. |
---|
1091 | 1008 | sizeof(beacon_cmd)); |
---|
1092 | 1009 | } |
---|
1093 | 1010 | |
---|
1094 | | -static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, |
---|
1095 | | - struct ieee80211_vif *vif, |
---|
1096 | | - struct sk_buff *beacon) |
---|
| 1011 | +int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, |
---|
| 1012 | + struct ieee80211_vif *vif, |
---|
| 1013 | + struct sk_buff *beacon) |
---|
1097 | 1014 | { |
---|
1098 | 1015 | if (WARN_ON(!beacon)) |
---|
1099 | 1016 | return -EINVAL; |
---|
| 1017 | + |
---|
| 1018 | + if (IWL_MVM_NON_TRANSMITTING_AP) |
---|
| 1019 | + return 0; |
---|
1100 | 1020 | |
---|
1101 | 1021 | if (!fw_has_capa(&mvm->fw->ucode_capa, |
---|
1102 | 1022 | IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD)) |
---|
.. | .. |
---|
1122 | 1042 | beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL); |
---|
1123 | 1043 | if (!beacon) |
---|
1124 | 1044 | return -ENOMEM; |
---|
| 1045 | + |
---|
| 1046 | +#ifdef CONFIG_IWLWIFI_DEBUGFS |
---|
| 1047 | + if (mvm->beacon_inject_active) { |
---|
| 1048 | + dev_kfree_skb(beacon); |
---|
| 1049 | + return -EBUSY; |
---|
| 1050 | + } |
---|
| 1051 | +#endif |
---|
1125 | 1052 | |
---|
1126 | 1053 | ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon); |
---|
1127 | 1054 | dev_kfree_skb(beacon); |
---|
.. | .. |
---|
1186 | 1113 | } |
---|
1187 | 1114 | |
---|
1188 | 1115 | ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int); |
---|
1189 | | - ctxt_ap->bi_reciprocal = |
---|
1190 | | - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int)); |
---|
1191 | 1116 | ctxt_ap->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int * |
---|
1192 | 1117 | vif->bss_conf.dtim_period); |
---|
1193 | | - ctxt_ap->dtim_reciprocal = |
---|
1194 | | - cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int * |
---|
1195 | | - vif->bss_conf.dtim_period)); |
---|
1196 | 1118 | |
---|
1197 | 1119 | if (!fw_has_api(&mvm->fw->ucode_capa, |
---|
1198 | 1120 | IWL_UCODE_TLV_API_STA_TYPE)) |
---|
1199 | | - ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue); |
---|
| 1121 | + ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->cab_queue); |
---|
1200 | 1122 | |
---|
1201 | 1123 | /* |
---|
1202 | 1124 | * Only set the beacon time when the MAC is being added, when we |
---|
.. | .. |
---|
1219 | 1141 | ieee80211_tu_to_usec(data.beacon_int * rand / |
---|
1220 | 1142 | 100); |
---|
1221 | 1143 | } else { |
---|
1222 | | - mvmvif->ap_beacon_time = |
---|
1223 | | - iwl_read_prph(mvm->trans, |
---|
1224 | | - DEVICE_SYSTEM_TIME_REG); |
---|
| 1144 | + mvmvif->ap_beacon_time = iwl_mvm_get_systime(mvm); |
---|
1225 | 1145 | } |
---|
1226 | 1146 | } |
---|
1227 | 1147 | |
---|
.. | .. |
---|
1384 | 1304 | |
---|
1385 | 1305 | mvmvif->csa_countdown = true; |
---|
1386 | 1306 | |
---|
1387 | | - if (!ieee80211_csa_is_complete(csa_vif)) { |
---|
1388 | | - int c = ieee80211_csa_update_counter(csa_vif); |
---|
| 1307 | + if (!ieee80211_beacon_cntdwn_is_complete(csa_vif)) { |
---|
| 1308 | + int c = ieee80211_beacon_update_cntdwn(csa_vif); |
---|
1389 | 1309 | |
---|
1390 | 1310 | iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif); |
---|
1391 | 1311 | if (csa_vif->p2p && |
---|
.. | .. |
---|
1413 | 1333 | { |
---|
1414 | 1334 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
---|
1415 | 1335 | struct iwl_extended_beacon_notif *beacon = (void *)pkt->data; |
---|
1416 | | - struct iwl_mvm_tx_resp *beacon_notify_hdr; |
---|
| 1336 | + struct iwl_extended_beacon_notif_v5 *beacon_v5 = (void *)pkt->data; |
---|
1417 | 1337 | struct ieee80211_vif *csa_vif; |
---|
1418 | 1338 | struct ieee80211_vif *tx_blocked_vif; |
---|
1419 | 1339 | struct agg_tx_status *agg_status; |
---|
.. | .. |
---|
1421 | 1341 | |
---|
1422 | 1342 | lockdep_assert_held(&mvm->mutex); |
---|
1423 | 1343 | |
---|
1424 | | - beacon_notify_hdr = &beacon->beacon_notify_hdr; |
---|
1425 | 1344 | mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2); |
---|
1426 | | - mvm->ibss_manager = beacon->ibss_mgr_status != 0; |
---|
1427 | 1345 | |
---|
1428 | | - agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr); |
---|
1429 | | - status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK; |
---|
1430 | | - IWL_DEBUG_RX(mvm, |
---|
1431 | | - "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n", |
---|
1432 | | - status, beacon_notify_hdr->failure_frame, |
---|
1433 | | - le64_to_cpu(beacon->tsf), |
---|
1434 | | - mvm->ap_last_beacon_gp2, |
---|
1435 | | - le32_to_cpu(beacon_notify_hdr->initial_rate)); |
---|
| 1346 | + if (!iwl_mvm_is_short_beacon_notif_supported(mvm)) { |
---|
| 1347 | + struct iwl_mvm_tx_resp *beacon_notify_hdr = |
---|
| 1348 | + &beacon_v5->beacon_notify_hdr; |
---|
| 1349 | + |
---|
| 1350 | + mvm->ibss_manager = beacon_v5->ibss_mgr_status != 0; |
---|
| 1351 | + agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr); |
---|
| 1352 | + status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK; |
---|
| 1353 | + IWL_DEBUG_RX(mvm, |
---|
| 1354 | + "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n", |
---|
| 1355 | + status, beacon_notify_hdr->failure_frame, |
---|
| 1356 | + le64_to_cpu(beacon->tsf), |
---|
| 1357 | + mvm->ap_last_beacon_gp2, |
---|
| 1358 | + le32_to_cpu(beacon_notify_hdr->initial_rate)); |
---|
| 1359 | + } else { |
---|
| 1360 | + mvm->ibss_manager = beacon->ibss_mgr_status != 0; |
---|
| 1361 | + status = le32_to_cpu(beacon->status) & TX_STATUS_MSK; |
---|
| 1362 | + IWL_DEBUG_RX(mvm, |
---|
| 1363 | + "beacon status %#x tsf:0x%016llX gp2:0x%X\n", |
---|
| 1364 | + status, le64_to_cpu(beacon->tsf), |
---|
| 1365 | + mvm->ap_last_beacon_gp2); |
---|
| 1366 | + } |
---|
1436 | 1367 | |
---|
1437 | 1368 | csa_vif = rcu_dereference_protected(mvm->csa_vif, |
---|
1438 | 1369 | lockdep_is_held(&mvm->mutex)); |
---|
.. | .. |
---|
1465 | 1396 | } |
---|
1466 | 1397 | } |
---|
1467 | 1398 | |
---|
1468 | | -static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac, |
---|
1469 | | - struct ieee80211_vif *vif) |
---|
1470 | | -{ |
---|
1471 | | - struct iwl_missed_beacons_notif *missed_beacons = _data; |
---|
1472 | | - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
---|
1473 | | - struct iwl_mvm *mvm = mvmvif->mvm; |
---|
1474 | | - struct iwl_fw_dbg_trigger_missed_bcon *bcon_trig; |
---|
1475 | | - struct iwl_fw_dbg_trigger_tlv *trigger; |
---|
1476 | | - u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx; |
---|
1477 | | - u32 rx_missed_bcon, rx_missed_bcon_since_rx; |
---|
1478 | | - |
---|
1479 | | - if (mvmvif->id != (u16)le32_to_cpu(missed_beacons->mac_id)) |
---|
1480 | | - return; |
---|
1481 | | - |
---|
1482 | | - rx_missed_bcon = le32_to_cpu(missed_beacons->consec_missed_beacons); |
---|
1483 | | - rx_missed_bcon_since_rx = |
---|
1484 | | - le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx); |
---|
1485 | | - /* |
---|
1486 | | - * TODO: the threshold should be adjusted based on latency conditions, |
---|
1487 | | - * and/or in case of a CS flow on one of the other AP vifs. |
---|
1488 | | - */ |
---|
1489 | | - if (le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx) > |
---|
1490 | | - IWL_MVM_MISSED_BEACONS_THRESHOLD) |
---|
1491 | | - ieee80211_beacon_loss(vif); |
---|
1492 | | - |
---|
1493 | | - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, |
---|
1494 | | - FW_DBG_TRIGGER_MISSED_BEACONS)) |
---|
1495 | | - return; |
---|
1496 | | - |
---|
1497 | | - trigger = iwl_fw_dbg_get_trigger(mvm->fw, |
---|
1498 | | - FW_DBG_TRIGGER_MISSED_BEACONS); |
---|
1499 | | - bcon_trig = (void *)trigger->data; |
---|
1500 | | - stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon); |
---|
1501 | | - stop_trig_missed_bcon_since_rx = |
---|
1502 | | - le32_to_cpu(bcon_trig->stop_consec_missed_bcon_since_rx); |
---|
1503 | | - |
---|
1504 | | - /* TODO: implement start trigger */ |
---|
1505 | | - |
---|
1506 | | - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, |
---|
1507 | | - ieee80211_vif_to_wdev(vif), |
---|
1508 | | - trigger)) |
---|
1509 | | - return; |
---|
1510 | | - |
---|
1511 | | - if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx || |
---|
1512 | | - rx_missed_bcon >= stop_trig_missed_bcon) |
---|
1513 | | - iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL); |
---|
1514 | | -} |
---|
1515 | | - |
---|
1516 | 1399 | void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, |
---|
1517 | 1400 | struct iwl_rx_cmd_buffer *rxb) |
---|
1518 | 1401 | { |
---|
1519 | 1402 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
---|
1520 | 1403 | struct iwl_missed_beacons_notif *mb = (void *)pkt->data; |
---|
| 1404 | + struct iwl_fw_dbg_trigger_missed_bcon *bcon_trig; |
---|
| 1405 | + struct iwl_fw_dbg_trigger_tlv *trigger; |
---|
| 1406 | + u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx; |
---|
| 1407 | + u32 rx_missed_bcon, rx_missed_bcon_since_rx; |
---|
| 1408 | + struct ieee80211_vif *vif; |
---|
| 1409 | + u32 id = le32_to_cpu(mb->mac_id); |
---|
| 1410 | + union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt }; |
---|
1521 | 1411 | |
---|
1522 | 1412 | IWL_DEBUG_INFO(mvm, |
---|
1523 | 1413 | "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n", |
---|
.. | .. |
---|
1527 | 1417 | le32_to_cpu(mb->num_recvd_beacons), |
---|
1528 | 1418 | le32_to_cpu(mb->num_expected_beacons)); |
---|
1529 | 1419 | |
---|
1530 | | - ieee80211_iterate_active_interfaces_atomic(mvm->hw, |
---|
1531 | | - IEEE80211_IFACE_ITER_NORMAL, |
---|
1532 | | - iwl_mvm_beacon_loss_iterator, |
---|
1533 | | - mb); |
---|
| 1420 | + rcu_read_lock(); |
---|
| 1421 | + |
---|
| 1422 | + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); |
---|
| 1423 | + if (!vif) |
---|
| 1424 | + goto out; |
---|
| 1425 | + |
---|
| 1426 | + rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons); |
---|
| 1427 | + rx_missed_bcon_since_rx = |
---|
| 1428 | + le32_to_cpu(mb->consec_missed_beacons_since_last_rx); |
---|
| 1429 | + /* |
---|
| 1430 | + * TODO: the threshold should be adjusted based on latency conditions, |
---|
| 1431 | + * and/or in case of a CS flow on one of the other AP vifs. |
---|
| 1432 | + */ |
---|
| 1433 | + if (rx_missed_bcon > IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG) |
---|
| 1434 | + iwl_mvm_connection_loss(mvm, vif, "missed beacons"); |
---|
| 1435 | + else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD) |
---|
| 1436 | + ieee80211_beacon_loss(vif); |
---|
| 1437 | + |
---|
| 1438 | + iwl_dbg_tlv_time_point(&mvm->fwrt, |
---|
| 1439 | + IWL_FW_INI_TIME_POINT_MISSED_BEACONS, &tp_data); |
---|
| 1440 | + |
---|
| 1441 | + trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), |
---|
| 1442 | + FW_DBG_TRIGGER_MISSED_BEACONS); |
---|
| 1443 | + if (!trigger) |
---|
| 1444 | + goto out; |
---|
| 1445 | + |
---|
| 1446 | + bcon_trig = (void *)trigger->data; |
---|
| 1447 | + stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon); |
---|
| 1448 | + stop_trig_missed_bcon_since_rx = |
---|
| 1449 | + le32_to_cpu(bcon_trig->stop_consec_missed_bcon_since_rx); |
---|
| 1450 | + |
---|
| 1451 | + /* TODO: implement start trigger */ |
---|
| 1452 | + |
---|
| 1453 | + if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx || |
---|
| 1454 | + rx_missed_bcon >= stop_trig_missed_bcon) |
---|
| 1455 | + iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL); |
---|
| 1456 | + |
---|
| 1457 | +out: |
---|
| 1458 | + rcu_read_unlock(); |
---|
1534 | 1459 | } |
---|
1535 | 1460 | |
---|
1536 | 1461 | void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, |
---|
.. | .. |
---|
1572 | 1497 | ieee80211_rx_napi(mvm->hw, NULL, skb, NULL); |
---|
1573 | 1498 | } |
---|
1574 | 1499 | |
---|
| 1500 | +void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm, |
---|
| 1501 | + struct iwl_rx_cmd_buffer *rxb) |
---|
| 1502 | +{ |
---|
| 1503 | + struct iwl_rx_packet *pkt = rxb_addr(rxb); |
---|
| 1504 | + struct iwl_probe_resp_data_notif *notif = (void *)pkt->data; |
---|
| 1505 | + struct iwl_probe_resp_data *old_data, *new_data; |
---|
| 1506 | + int len = iwl_rx_packet_payload_len(pkt); |
---|
| 1507 | + u32 id = le32_to_cpu(notif->mac_id); |
---|
| 1508 | + struct ieee80211_vif *vif; |
---|
| 1509 | + struct iwl_mvm_vif *mvmvif; |
---|
| 1510 | + |
---|
| 1511 | + if (WARN_ON_ONCE(len < sizeof(*notif))) |
---|
| 1512 | + return; |
---|
| 1513 | + |
---|
| 1514 | + IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n", |
---|
| 1515 | + notif->noa_active, notif->csa_counter); |
---|
| 1516 | + |
---|
| 1517 | + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false); |
---|
| 1518 | + if (!vif) |
---|
| 1519 | + return; |
---|
| 1520 | + |
---|
| 1521 | + mvmvif = iwl_mvm_vif_from_mac80211(vif); |
---|
| 1522 | + |
---|
| 1523 | + new_data = kzalloc(sizeof(*new_data), GFP_KERNEL); |
---|
| 1524 | + if (!new_data) |
---|
| 1525 | + return; |
---|
| 1526 | + |
---|
| 1527 | + memcpy(&new_data->notif, notif, sizeof(new_data->notif)); |
---|
| 1528 | + |
---|
| 1529 | + /* noa_attr contains 1 reserved byte, need to substruct it */ |
---|
| 1530 | + new_data->noa_len = sizeof(struct ieee80211_vendor_ie) + |
---|
| 1531 | + sizeof(new_data->notif.noa_attr) - 1; |
---|
| 1532 | + |
---|
| 1533 | + /* |
---|
| 1534 | + * If it's a one time NoA, only one descriptor is needed, |
---|
| 1535 | + * adjust the length according to len_low. |
---|
| 1536 | + */ |
---|
| 1537 | + if (new_data->notif.noa_attr.len_low == |
---|
| 1538 | + sizeof(struct ieee80211_p2p_noa_desc) + 2) |
---|
| 1539 | + new_data->noa_len -= sizeof(struct ieee80211_p2p_noa_desc); |
---|
| 1540 | + |
---|
| 1541 | + old_data = rcu_dereference_protected(mvmvif->probe_resp_data, |
---|
| 1542 | + lockdep_is_held(&mvmvif->mvm->mutex)); |
---|
| 1543 | + rcu_assign_pointer(mvmvif->probe_resp_data, new_data); |
---|
| 1544 | + |
---|
| 1545 | + if (old_data) |
---|
| 1546 | + kfree_rcu(old_data, rcu_head); |
---|
| 1547 | + |
---|
| 1548 | + if (notif->csa_counter != IWL_PROBE_RESP_DATA_NO_CSA && |
---|
| 1549 | + notif->csa_counter >= 1) |
---|
| 1550 | + ieee80211_beacon_set_cntdwn(vif, notif->csa_counter); |
---|
| 1551 | +} |
---|
| 1552 | + |
---|
1575 | 1553 | void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, |
---|
1576 | 1554 | struct iwl_rx_cmd_buffer *rxb) |
---|
1577 | 1555 | { |
---|
1578 | 1556 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
---|
1579 | 1557 | struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data; |
---|
1580 | | - struct ieee80211_vif *csa_vif; |
---|
| 1558 | + struct ieee80211_vif *csa_vif, *vif; |
---|
1581 | 1559 | struct iwl_mvm_vif *mvmvif; |
---|
1582 | 1560 | int len = iwl_rx_packet_payload_len(pkt); |
---|
1583 | | - u32 id_n_color; |
---|
| 1561 | + u32 id_n_color, csa_id, mac_id; |
---|
1584 | 1562 | |
---|
1585 | 1563 | if (WARN_ON_ONCE(len < sizeof(*notif))) |
---|
1586 | 1564 | return; |
---|
1587 | 1565 | |
---|
| 1566 | + id_n_color = le32_to_cpu(notif->id_and_color); |
---|
| 1567 | + mac_id = id_n_color & FW_CTXT_ID_MSK; |
---|
| 1568 | + |
---|
| 1569 | + if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER)) |
---|
| 1570 | + return; |
---|
| 1571 | + |
---|
| 1572 | + rcu_read_lock(); |
---|
| 1573 | + vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]); |
---|
| 1574 | + mvmvif = iwl_mvm_vif_from_mac80211(vif); |
---|
| 1575 | + |
---|
| 1576 | + switch (vif->type) { |
---|
| 1577 | + case NL80211_IFTYPE_AP: |
---|
| 1578 | + csa_vif = rcu_dereference(mvm->csa_vif); |
---|
| 1579 | + if (WARN_ON(!csa_vif || !csa_vif->csa_active || |
---|
| 1580 | + csa_vif != vif)) |
---|
| 1581 | + goto out_unlock; |
---|
| 1582 | + |
---|
| 1583 | + csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); |
---|
| 1584 | + if (WARN(csa_id != id_n_color, |
---|
| 1585 | + "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", |
---|
| 1586 | + csa_id, id_n_color)) |
---|
| 1587 | + goto out_unlock; |
---|
| 1588 | + |
---|
| 1589 | + IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n"); |
---|
| 1590 | + |
---|
| 1591 | + schedule_delayed_work(&mvm->cs_tx_unblock_dwork, |
---|
| 1592 | + msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT * |
---|
| 1593 | + csa_vif->bss_conf.beacon_int)); |
---|
| 1594 | + |
---|
| 1595 | + ieee80211_csa_finish(csa_vif); |
---|
| 1596 | + |
---|
| 1597 | + rcu_read_unlock(); |
---|
| 1598 | + |
---|
| 1599 | + RCU_INIT_POINTER(mvm->csa_vif, NULL); |
---|
| 1600 | + return; |
---|
| 1601 | + case NL80211_IFTYPE_STATION: |
---|
| 1602 | + iwl_mvm_csa_client_absent(mvm, vif); |
---|
| 1603 | + cancel_delayed_work(&mvmvif->csa_work); |
---|
| 1604 | + ieee80211_chswitch_done(vif, true); |
---|
| 1605 | + break; |
---|
| 1606 | + default: |
---|
| 1607 | + /* should never happen */ |
---|
| 1608 | + WARN_ON_ONCE(1); |
---|
| 1609 | + break; |
---|
| 1610 | + } |
---|
| 1611 | +out_unlock: |
---|
| 1612 | + rcu_read_unlock(); |
---|
| 1613 | +} |
---|
| 1614 | + |
---|
| 1615 | +void iwl_mvm_rx_missed_vap_notif(struct iwl_mvm *mvm, |
---|
| 1616 | + struct iwl_rx_cmd_buffer *rxb) |
---|
| 1617 | +{ |
---|
| 1618 | + struct iwl_rx_packet *pkt = rxb_addr(rxb); |
---|
| 1619 | + struct iwl_missed_vap_notif *mb = (void *)pkt->data; |
---|
| 1620 | + struct ieee80211_vif *vif; |
---|
| 1621 | + u32 id = le32_to_cpu(mb->mac_id); |
---|
| 1622 | + |
---|
| 1623 | + IWL_DEBUG_INFO(mvm, |
---|
| 1624 | + "missed_vap notify mac_id=%u, num_beacon_intervals_elapsed=%u, profile_periodicity=%u\n", |
---|
| 1625 | + le32_to_cpu(mb->mac_id), |
---|
| 1626 | + mb->num_beacon_intervals_elapsed, |
---|
| 1627 | + mb->profile_periodicity); |
---|
| 1628 | + |
---|
1588 | 1629 | rcu_read_lock(); |
---|
1589 | 1630 | |
---|
1590 | | - csa_vif = rcu_dereference(mvm->csa_vif); |
---|
1591 | | - if (WARN_ON(!csa_vif || !csa_vif->csa_active)) |
---|
1592 | | - goto out_unlock; |
---|
| 1631 | + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); |
---|
| 1632 | + if (vif) |
---|
| 1633 | + iwl_mvm_connection_loss(mvm, vif, "missed vap beacon"); |
---|
1593 | 1634 | |
---|
1594 | | - id_n_color = le32_to_cpu(notif->id_and_color); |
---|
1595 | | - |
---|
1596 | | - mvmvif = iwl_mvm_vif_from_mac80211(csa_vif); |
---|
1597 | | - if (WARN(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color) != id_n_color, |
---|
1598 | | - "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", |
---|
1599 | | - FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color), id_n_color)) |
---|
1600 | | - goto out_unlock; |
---|
1601 | | - |
---|
1602 | | - IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n"); |
---|
1603 | | - |
---|
1604 | | - schedule_delayed_work(&mvm->cs_tx_unblock_dwork, |
---|
1605 | | - msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT * |
---|
1606 | | - csa_vif->bss_conf.beacon_int)); |
---|
1607 | | - |
---|
1608 | | - ieee80211_csa_finish(csa_vif); |
---|
1609 | | - |
---|
1610 | | - rcu_read_unlock(); |
---|
1611 | | - |
---|
1612 | | - RCU_INIT_POINTER(mvm->csa_vif, NULL); |
---|
1613 | | - |
---|
1614 | | - return; |
---|
1615 | | - |
---|
1616 | | -out_unlock: |
---|
1617 | 1635 | rcu_read_unlock(); |
---|
1618 | 1636 | } |
---|