Lines Matching +full:local +full:- +full:cap +full:- +full:size

1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
8 * Copyright 2015 - 2016 Intel Deutschland GmbH
17 #include "driver-ops.h"
27 struct ieee80211_local *local; in ieee80211_tdls_peer_del_work() local
31 local = sdata->local; in ieee80211_tdls_peer_del_work()
33 mutex_lock(&local->mtx); in ieee80211_tdls_peer_del_work()
34 if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer)) { in ieee80211_tdls_peer_del_work()
35 tdls_dbg(sdata, "TDLS del peer %pM\n", sdata->u.mgd.tdls_peer); in ieee80211_tdls_peer_del_work()
36 sta_info_destroy_addr(sdata, sdata->u.mgd.tdls_peer); in ieee80211_tdls_peer_del_work()
37 eth_zero_addr(sdata->u.mgd.tdls_peer); in ieee80211_tdls_peer_del_work()
39 mutex_unlock(&local->mtx); in ieee80211_tdls_peer_del_work()
45 struct ieee80211_local *local = sdata->local; in ieee80211_tdls_add_ext_capab() local
46 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; in ieee80211_tdls_add_ext_capab()
47 bool chan_switch = local->hw.wiphy->features & in ieee80211_tdls_add_ext_capab()
49 bool wider_band = ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) && in ieee80211_tdls_add_ext_capab()
50 !ifmgd->tdls_wider_bw_prohibited; in ieee80211_tdls_add_ext_capab()
51 bool buffer_sta = ieee80211_hw_check(&local->hw, in ieee80211_tdls_add_ext_capab()
54 bool vht = sband && sband->vht_cap.vht_supported; in ieee80211_tdls_add_ext_capab()
79 struct wiphy *wiphy = sdata->local->hw.wiphy; in ieee80211_tdls_add_subband()
85 ch = ieee80211_get_channel(sdata->local->hw.wiphy, i); in ieee80211_tdls_add_subband()
91 sdata->wdev.iftype)) { in ieee80211_tdls_add_subband()
115 /* all channels in the requested range are allowed - add them here */ in ieee80211_tdls_add_subband()
161 if (!ieee80211_chandef_to_operating_class(&sdata->vif.bss_conf.chandef, in ieee80211_tdls_add_oper_classes()
193 if (sband && sband->band == NL80211_BAND_2GHZ) { in ieee80211_get_tdls_sta_capab()
209 init_addr = sdata->vif.addr; in ieee80211_tdls_add_link_ie()
213 rsp_addr = sdata->vif.addr; in ieee80211_tdls_add_link_ie()
218 lnkid->ie_type = WLAN_EID_LINK_ID; in ieee80211_tdls_add_link_ie()
219 lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; in ieee80211_tdls_add_link_ie()
221 memcpy(lnkid->bssid, sdata->u.mgd.bssid, ETH_ALEN); in ieee80211_tdls_add_link_ie()
222 memcpy(lnkid->init_sta, init_addr, ETH_ALEN); in ieee80211_tdls_add_link_ie()
223 memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN); in ieee80211_tdls_add_link_ie()
233 put_unaligned_le16(sdata->vif.bss_conf.aid, pos); in ieee80211_tdls_add_aid()
280 wmm->element_id = WLAN_EID_VENDOR_SPECIFIC; in ieee80211_tdls_add_wmm_param_ie()
281 wmm->len = sizeof(*wmm) - 2; in ieee80211_tdls_add_wmm_param_ie()
283 wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */ in ieee80211_tdls_add_wmm_param_ie()
284 wmm->oui[1] = 0x50; in ieee80211_tdls_add_wmm_param_ie()
285 wmm->oui[2] = 0xf2; in ieee80211_tdls_add_wmm_param_ie()
286 wmm->oui_type = 2; /* WME */ in ieee80211_tdls_add_wmm_param_ie()
287 wmm->oui_subtype = 1; /* WME param */ in ieee80211_tdls_add_wmm_param_ie()
288 wmm->version = 1; /* WME ver */ in ieee80211_tdls_add_wmm_param_ie()
289 wmm->qos_info = 0; /* U-APSD not in use */ in ieee80211_tdls_add_wmm_param_ie()
293 * doesn't support it, as mandated by 802.11-2012 section 10.22.4 in ieee80211_tdls_add_wmm_param_ie()
296 txq = &sdata->tx_conf[ieee80211_ac_from_wmm(i)]; in ieee80211_tdls_add_wmm_param_ie()
297 wmm->ac[i].aci_aifsn = ieee80211_wmm_aci_aifsn(txq->aifs, in ieee80211_tdls_add_wmm_param_ie()
298 txq->acm, i); in ieee80211_tdls_add_wmm_param_ie()
299 wmm->ac[i].cw = ieee80211_wmm_ecw(txq->cw_min, txq->cw_max); in ieee80211_tdls_add_wmm_param_ie()
300 wmm->ac[i].txop_limit = cpu_to_le16(txq->txop); in ieee80211_tdls_add_wmm_param_ie()
308 /* IEEE802.11ac-2013 Table E-4 */ in ieee80211_tdls_chandef_vht_upgrade()
310 struct cfg80211_chan_def uc = sta->tdls_chandef; in ieee80211_tdls_chandef_vht_upgrade()
314 /* only support upgrading non-narrow channels up to 80Mhz */ in ieee80211_tdls_chandef_vht_upgrade()
325 * Channel usage constrains in the IEEE802.11ac-2013 specification only in ieee80211_tdls_chandef_vht_upgrade()
331 if (abs(uc.chan->center_freq - centers_80mhz[i]) <= 30) { in ieee80211_tdls_chandef_vht_upgrade()
343 (uc.width > sta->tdls_chandef.width && in ieee80211_tdls_chandef_vht_upgrade()
344 !cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &uc, in ieee80211_tdls_chandef_vht_upgrade()
345 sdata->wdev.iftype))) in ieee80211_tdls_chandef_vht_upgrade()
348 if (!cfg80211_chandef_identical(&uc, &sta->tdls_chandef)) { in ieee80211_tdls_chandef_vht_upgrade()
349 tdls_dbg(sdata, "TDLS ch width upgraded %d -> %d\n", in ieee80211_tdls_chandef_vht_upgrade()
350 sta->tdls_chandef.width, uc.width); in ieee80211_tdls_chandef_vht_upgrade()
356 sta->tdls_chandef = uc; in ieee80211_tdls_chandef_vht_upgrade()
367 struct ieee80211_local *local = sdata->local; in ieee80211_tdls_add_setup_start_ies() local
378 ieee80211_add_srates_ie(sdata, skb, false, sband->band); in ieee80211_tdls_add_setup_start_ies()
379 ieee80211_add_ext_srates_ie(sdata, skb, false, sband->band); in ieee80211_tdls_add_setup_start_ies()
395 skb_put_data(skb, extra_ies + offset, noffset - offset); in ieee80211_tdls_add_setup_start_ies()
402 if (local->hw.queues >= IEEE80211_NUM_ACS && in ieee80211_tdls_add_setup_start_ies()
404 ieee80211_add_wmm_info_ie(skb_put(skb, 9), 0); /* no U-APSD */ in ieee80211_tdls_add_setup_start_ies()
424 skb_put_data(skb, extra_ies + offset, noffset - offset); in ieee80211_tdls_add_setup_start_ies()
428 mutex_lock(&local->sta_mtx); in ieee80211_tdls_add_setup_start_ies()
434 mutex_unlock(&local->sta_mtx); in ieee80211_tdls_add_setup_start_ies()
438 sta->tdls_chandef = sdata->vif.bss_conf.chandef; in ieee80211_tdls_add_setup_start_ies()
444 * with TDLS we can switch channels, and HT-caps are not necessarily in ieee80211_tdls_add_setup_start_ies()
446 * single HT-cap, so use the current band for now. in ieee80211_tdls_add_setup_start_ies()
448 memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); in ieee80211_tdls_add_setup_start_ies()
456 ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED in ieee80211_tdls_add_setup_start_ies()
460 ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap); in ieee80211_tdls_add_setup_start_ies()
462 ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) { in ieee80211_tdls_add_setup_start_ies()
464 memcpy(&ht_cap, &sta->sta.ht_cap, sizeof(ht_cap)); in ieee80211_tdls_add_setup_start_ies()
467 ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap); in ieee80211_tdls_add_setup_start_ies()
471 (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) in ieee80211_tdls_add_setup_start_ies()
495 skb_put_data(skb, extra_ies + offset, noffset - offset); in ieee80211_tdls_add_setup_start_ies()
499 /* build the VHT-cap similarly to the HT-cap */ in ieee80211_tdls_add_setup_start_ies()
500 memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); in ieee80211_tdls_add_setup_start_ies()
511 ieee80211_ie_build_vht_cap(pos, &vht_cap, vht_cap.cap); in ieee80211_tdls_add_setup_start_ies()
513 vht_cap.vht_supported && sta->sta.vht_cap.vht_supported) { in ieee80211_tdls_add_setup_start_ies()
515 memcpy(&vht_cap, &sta->sta.vht_cap, sizeof(vht_cap)); in ieee80211_tdls_add_setup_start_ies()
521 ieee80211_ie_build_vht_cap(pos, &vht_cap, vht_cap.cap); in ieee80211_tdls_add_setup_start_ies()
531 mutex_unlock(&local->sta_mtx); in ieee80211_tdls_add_setup_start_ies()
536 skb_put_data(skb, extra_ies + offset, noffset - offset); in ieee80211_tdls_add_setup_start_ies()
547 struct ieee80211_local *local = sdata->local; in ieee80211_tdls_add_setup_cfm_ies() local
548 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; in ieee80211_tdls_add_setup_cfm_ies()
558 mutex_lock(&local->sta_mtx); in ieee80211_tdls_add_setup_cfm_ies()
561 ap_sta = sta_info_get(sdata, ifmgd->bssid); in ieee80211_tdls_add_setup_cfm_ies()
563 mutex_unlock(&local->sta_mtx); in ieee80211_tdls_add_setup_cfm_ies()
567 sta->tdls_chandef = sdata->vif.bss_conf.chandef; in ieee80211_tdls_add_setup_cfm_ies()
578 skb_put_data(skb, extra_ies + offset, noffset - offset); in ieee80211_tdls_add_setup_cfm_ies()
583 if (local->hw.queues >= IEEE80211_NUM_ACS && sta->sta.wme) in ieee80211_tdls_add_setup_cfm_ies()
598 skb_put_data(skb, extra_ies + offset, noffset - offset); in ieee80211_tdls_add_setup_cfm_ies()
603 * if HT support is only added in TDLS, we need an HT-operation IE. in ieee80211_tdls_add_setup_cfm_ies()
604 * add the IE as required by IEEE802.11-2012 9.23.3.2. in ieee80211_tdls_add_setup_cfm_ies()
606 if (!ap_sta->sta.ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) { in ieee80211_tdls_add_setup_cfm_ies()
612 ieee80211_ie_build_ht_oper(pos, &sta->sta.ht_cap, in ieee80211_tdls_add_setup_cfm_ies()
613 &sdata->vif.bss_conf.chandef, prot, in ieee80211_tdls_add_setup_cfm_ies()
619 /* only include VHT-operation if not on the 2.4GHz band */ in ieee80211_tdls_add_setup_cfm_ies()
620 if (sband->band != NL80211_BAND_2GHZ && in ieee80211_tdls_add_setup_cfm_ies()
621 sta->sta.vht_cap.vht_supported) { in ieee80211_tdls_add_setup_cfm_ies()
630 ieee80211_ie_build_vht_oper(pos, &sta->sta.vht_cap, in ieee80211_tdls_add_setup_cfm_ies()
631 &sta->tdls_chandef); in ieee80211_tdls_add_setup_cfm_ies()
634 mutex_unlock(&local->sta_mtx); in ieee80211_tdls_add_setup_cfm_ies()
639 skb_put_data(skb, extra_ies + offset, noffset - offset); in ieee80211_tdls_add_setup_cfm_ies()
656 tf = (void *)skb->data; in ieee80211_tdls_add_chan_switch_req_ies()
657 tf->u.chan_switch_req.target_channel = in ieee80211_tdls_add_chan_switch_req_ies()
658 ieee80211_frequency_to_channel(chandef->chan->center_freq); in ieee80211_tdls_add_chan_switch_req_ies()
659 tf->u.chan_switch_req.oper_class = oper_class; in ieee80211_tdls_add_chan_switch_req_ies()
669 skb_put_data(skb, extra_ies + offset, noffset - offset); in ieee80211_tdls_add_chan_switch_req_ies()
678 skb_put_data(skb, extra_ies + offset, noffset - offset); in ieee80211_tdls_add_chan_switch_req_ies()
753 memcpy(tf->da, peer, ETH_ALEN); in ieee80211_prep_tdls_encap_data()
754 memcpy(tf->sa, sdata->vif.addr, ETH_ALEN); in ieee80211_prep_tdls_encap_data()
755 tf->ether_type = cpu_to_be16(ETH_P_TDLS); in ieee80211_prep_tdls_encap_data()
756 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; in ieee80211_prep_tdls_encap_data()
763 tf->category = WLAN_CATEGORY_TDLS; in ieee80211_prep_tdls_encap_data()
764 tf->action_code = WLAN_TDLS_SETUP_REQUEST; in ieee80211_prep_tdls_encap_data()
766 skb_put(skb, sizeof(tf->u.setup_req)); in ieee80211_prep_tdls_encap_data()
767 tf->u.setup_req.dialog_token = dialog_token; in ieee80211_prep_tdls_encap_data()
768 tf->u.setup_req.capability = in ieee80211_prep_tdls_encap_data()
773 tf->category = WLAN_CATEGORY_TDLS; in ieee80211_prep_tdls_encap_data()
774 tf->action_code = WLAN_TDLS_SETUP_RESPONSE; in ieee80211_prep_tdls_encap_data()
776 skb_put(skb, sizeof(tf->u.setup_resp)); in ieee80211_prep_tdls_encap_data()
777 tf->u.setup_resp.status_code = cpu_to_le16(status_code); in ieee80211_prep_tdls_encap_data()
778 tf->u.setup_resp.dialog_token = dialog_token; in ieee80211_prep_tdls_encap_data()
779 tf->u.setup_resp.capability = in ieee80211_prep_tdls_encap_data()
784 tf->category = WLAN_CATEGORY_TDLS; in ieee80211_prep_tdls_encap_data()
785 tf->action_code = WLAN_TDLS_SETUP_CONFIRM; in ieee80211_prep_tdls_encap_data()
787 skb_put(skb, sizeof(tf->u.setup_cfm)); in ieee80211_prep_tdls_encap_data()
788 tf->u.setup_cfm.status_code = cpu_to_le16(status_code); in ieee80211_prep_tdls_encap_data()
789 tf->u.setup_cfm.dialog_token = dialog_token; in ieee80211_prep_tdls_encap_data()
792 tf->category = WLAN_CATEGORY_TDLS; in ieee80211_prep_tdls_encap_data()
793 tf->action_code = WLAN_TDLS_TEARDOWN; in ieee80211_prep_tdls_encap_data()
795 skb_put(skb, sizeof(tf->u.teardown)); in ieee80211_prep_tdls_encap_data()
796 tf->u.teardown.reason_code = cpu_to_le16(status_code); in ieee80211_prep_tdls_encap_data()
799 tf->category = WLAN_CATEGORY_TDLS; in ieee80211_prep_tdls_encap_data()
800 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; in ieee80211_prep_tdls_encap_data()
802 skb_put(skb, sizeof(tf->u.discover_req)); in ieee80211_prep_tdls_encap_data()
803 tf->u.discover_req.dialog_token = dialog_token; in ieee80211_prep_tdls_encap_data()
806 tf->category = WLAN_CATEGORY_TDLS; in ieee80211_prep_tdls_encap_data()
807 tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_REQUEST; in ieee80211_prep_tdls_encap_data()
809 skb_put(skb, sizeof(tf->u.chan_switch_req)); in ieee80211_prep_tdls_encap_data()
812 tf->category = WLAN_CATEGORY_TDLS; in ieee80211_prep_tdls_encap_data()
813 tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_RESPONSE; in ieee80211_prep_tdls_encap_data()
815 skb_put(skb, sizeof(tf->u.chan_switch_resp)); in ieee80211_prep_tdls_encap_data()
816 tf->u.chan_switch_resp.status_code = cpu_to_le16(status_code); in ieee80211_prep_tdls_encap_data()
819 return -EINVAL; in ieee80211_prep_tdls_encap_data()
834 memcpy(mgmt->da, peer, ETH_ALEN); in ieee80211_prep_tdls_direct()
835 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); in ieee80211_prep_tdls_direct()
836 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); in ieee80211_prep_tdls_direct()
838 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | in ieee80211_prep_tdls_direct()
843 skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); in ieee80211_prep_tdls_direct()
844 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; in ieee80211_prep_tdls_direct()
845 mgmt->u.action.u.tdls_discover_resp.action_code = in ieee80211_prep_tdls_direct()
847 mgmt->u.action.u.tdls_discover_resp.dialog_token = in ieee80211_prep_tdls_direct()
849 mgmt->u.action.u.tdls_discover_resp.capability = in ieee80211_prep_tdls_direct()
854 return -EINVAL; in ieee80211_prep_tdls_direct()
868 struct ieee80211_local *local = sdata->local; in ieee80211_tdls_build_mgmt_packet_data() local
872 skb = netdev_alloc_skb(sdata->dev, in ieee80211_tdls_build_mgmt_packet_data()
873 local->hw.extra_tx_headroom + in ieee80211_tdls_build_mgmt_packet_data()
878 26 + /* max(WMM-info, WMM-param) */ in ieee80211_tdls_build_mgmt_packet_data()
892 skb_reserve(skb, local->hw.extra_tx_headroom); in ieee80211_tdls_build_mgmt_packet_data()
902 ret = ieee80211_prep_tdls_encap_data(local->hw.wiphy, in ieee80211_tdls_build_mgmt_packet_data()
903 sdata->dev, peer, in ieee80211_tdls_build_mgmt_packet_data()
908 ret = ieee80211_prep_tdls_direct(local->hw.wiphy, sdata->dev, in ieee80211_tdls_build_mgmt_packet_data()
914 ret = -ENOTSUPP; in ieee80211_tdls_build_mgmt_packet_data()
953 sta->sta.tdls_initiator = false; in ieee80211_tdls_prep_mgmt_packet()
968 sta->sta.tdls_initiator = true; in ieee80211_tdls_prep_mgmt_packet()
980 ret = -ENOTSUPP; in ieee80211_tdls_prep_mgmt_packet()
997 ret = -EINVAL; in ieee80211_tdls_prep_mgmt_packet()
1013 skb->priority = 256 + 2; in ieee80211_tdls_prep_mgmt_packet()
1016 skb->priority = 256 + 5; in ieee80211_tdls_prep_mgmt_packet()
1023 * Later, if no ACK is returned from peer, we will re-send the teardown in ieee80211_tdls_prep_mgmt_packet()
1027 ieee80211_hw_check(&sdata->local->hw, REPORTS_TX_ACK_STATUS)) { in ieee80211_tdls_prep_mgmt_packet()
1030 /* If not sending directly to peer - no point in keeping skb */ in ieee80211_tdls_prep_mgmt_packet()
1036 spin_lock_bh(&sdata->u.mgd.teardown_lock); in ieee80211_tdls_prep_mgmt_packet()
1037 if (try_resend && !sdata->u.mgd.teardown_skb) { in ieee80211_tdls_prep_mgmt_packet()
1049 sdata->u.mgd.teardown_skb = skb_copy(skb, GFP_ATOMIC); in ieee80211_tdls_prep_mgmt_packet()
1050 sdata->u.mgd.orig_teardown_skb = skb; in ieee80211_tdls_prep_mgmt_packet()
1052 spin_unlock_bh(&sdata->u.mgd.teardown_lock); in ieee80211_tdls_prep_mgmt_packet()
1074 struct ieee80211_local *local = sdata->local; in ieee80211_tdls_mgmt_setup() local
1075 enum ieee80211_smps_mode smps_mode = sdata->u.mgd.driver_smps_mode; in ieee80211_tdls_mgmt_setup()
1083 return -ENOTSUPP; in ieee80211_tdls_mgmt_setup()
1086 mutex_lock(&local->mtx); in ieee80211_tdls_mgmt_setup()
1089 if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer) && in ieee80211_tdls_mgmt_setup()
1090 !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) { in ieee80211_tdls_mgmt_setup()
1091 ret = -EBUSY; in ieee80211_tdls_mgmt_setup()
1097 * non-TDLS-setup frames to the peer. We can't send other packets in ieee80211_tdls_mgmt_setup()
1099 * Allow error packets to be sent - sometimes we don't even add a STA in ieee80211_tdls_mgmt_setup()
1106 ret = -ENOLINK; in ieee80211_tdls_mgmt_setup()
1112 ieee80211_flush_queues(local, sdata, false); in ieee80211_tdls_mgmt_setup()
1113 memcpy(sdata->u.mgd.tdls_peer, peer, ETH_ALEN); in ieee80211_tdls_mgmt_setup()
1114 mutex_unlock(&local->mtx); in ieee80211_tdls_mgmt_setup()
1123 mutex_lock(&local->mtx); in ieee80211_tdls_mgmt_setup()
1124 eth_zero_addr(sdata->u.mgd.tdls_peer); in ieee80211_tdls_mgmt_setup()
1125 mutex_unlock(&local->mtx); in ieee80211_tdls_mgmt_setup()
1129 ieee80211_queue_delayed_work(&sdata->local->hw, in ieee80211_tdls_mgmt_setup()
1130 &sdata->u.mgd.tdls_peer_del_work, in ieee80211_tdls_mgmt_setup()
1135 mutex_unlock(&local->mtx); in ieee80211_tdls_mgmt_setup()
1147 struct ieee80211_local *local = sdata->local; in ieee80211_tdls_mgmt_teardown() local
1152 * No packets can be transmitted to the peer via the AP during setup - in ieee80211_tdls_mgmt_teardown()
1157 ieee80211_stop_vif_queues(local, sdata, in ieee80211_tdls_mgmt_teardown()
1159 ieee80211_flush_queues(local, sdata, false); in ieee80211_tdls_mgmt_teardown()
1180 ieee80211_wake_vif_queues(local, sdata, in ieee80211_tdls_mgmt_teardown()
1195 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) in ieee80211_tdls_mgmt()
1196 return -ENOTSUPP; in ieee80211_tdls_mgmt()
1199 if (sdata->vif.type != NL80211_IFTYPE_STATION || in ieee80211_tdls_mgmt()
1200 !sdata->u.mgd.associated) in ieee80211_tdls_mgmt()
1201 return -EINVAL; in ieee80211_tdls_mgmt()
1224 drv_mgd_protect_tdls_discover(sdata->local, sdata); in ieee80211_tdls_mgmt()
1238 ret = -EOPNOTSUPP; in ieee80211_tdls_mgmt()
1250 struct ieee80211_local *local = sdata->local; in iee80211_tdls_recalc_chanctx() local
1256 mutex_lock(&local->chanctx_mtx); in iee80211_tdls_recalc_chanctx()
1257 conf = rcu_dereference_protected(sdata->vif.chanctx_conf, in iee80211_tdls_recalc_chanctx()
1258 lockdep_is_held(&local->chanctx_mtx)); in iee80211_tdls_recalc_chanctx()
1260 width = conf->def.width; in iee80211_tdls_recalc_chanctx()
1261 sband = local->hw.wiphy->bands[conf->def.chan->band]; in iee80211_tdls_recalc_chanctx()
1263 ieee80211_recalc_chanctx_chantype(local, ctx); in iee80211_tdls_recalc_chanctx()
1266 if (width != conf->def.width && sta && in iee80211_tdls_recalc_chanctx()
1270 bw = ieee80211_chan_width_to_rx_bw(conf->def.width); in iee80211_tdls_recalc_chanctx()
1272 if (bw != sta->sta.bandwidth) { in iee80211_tdls_recalc_chanctx()
1273 sta->sta.bandwidth = bw; in iee80211_tdls_recalc_chanctx()
1274 rate_control_rate_update(local, sband, sta, in iee80211_tdls_recalc_chanctx()
1281 ieee80211_recalc_chanctx_chantype(local, ctx); in iee80211_tdls_recalc_chanctx()
1286 mutex_unlock(&local->chanctx_mtx); in iee80211_tdls_recalc_chanctx()
1295 list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) { in iee80211_tdls_have_ht_peers()
1296 if (!sta->sta.tdls || sta->sdata != sdata || !sta->uploaded || in iee80211_tdls_have_ht_peers()
1299 !sta->sta.ht_cap.ht_supported) in iee80211_tdls_have_ht_peers()
1313 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; in iee80211_tdls_recalc_ht_protection()
1321 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) in iee80211_tdls_recalc_ht_protection()
1324 tdls_ht = (sta && sta->sta.ht_cap.ht_supported) || in iee80211_tdls_recalc_ht_protection()
1327 opmode = sdata->vif.bss_conf.ht_operation_mode; in iee80211_tdls_recalc_ht_protection()
1334 if (opmode == sdata->vif.bss_conf.ht_operation_mode) in iee80211_tdls_recalc_ht_protection()
1337 sdata->vif.bss_conf.ht_operation_mode = opmode; in iee80211_tdls_recalc_ht_protection()
1346 struct ieee80211_local *local = sdata->local; in ieee80211_tdls_oper() local
1349 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) in ieee80211_tdls_oper()
1350 return -ENOTSUPP; in ieee80211_tdls_oper()
1352 if (sdata->vif.type != NL80211_IFTYPE_STATION) in ieee80211_tdls_oper()
1353 return -EINVAL; in ieee80211_tdls_oper()
1362 /* We don't support in-driver setup/teardown/discovery */ in ieee80211_tdls_oper()
1363 return -ENOTSUPP; in ieee80211_tdls_oper()
1370 mutex_lock(&local->mtx); in ieee80211_tdls_oper()
1375 if (sdata->vif.csa_active) { in ieee80211_tdls_oper()
1377 ret = -EBUSY; in ieee80211_tdls_oper()
1381 mutex_lock(&local->sta_mtx); in ieee80211_tdls_oper()
1384 mutex_unlock(&local->sta_mtx); in ieee80211_tdls_oper()
1385 ret = -ENOLINK; in ieee80211_tdls_oper()
1393 mutex_unlock(&local->sta_mtx); in ieee80211_tdls_oper()
1395 WARN_ON_ONCE(is_zero_ether_addr(sdata->u.mgd.tdls_peer) || in ieee80211_tdls_oper()
1396 !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)); in ieee80211_tdls_oper()
1407 * Note that this only forces the tasklet to flush pendings - in ieee80211_tdls_oper()
1410 tasklet_kill(&local->tx_pending_tasklet); in ieee80211_tdls_oper()
1412 ieee80211_flush_queues(local, sdata, false); in ieee80211_tdls_oper()
1416 mutex_lock(&local->sta_mtx); in ieee80211_tdls_oper()
1418 mutex_unlock(&local->sta_mtx); in ieee80211_tdls_oper()
1423 ret = -ENOTSUPP; in ieee80211_tdls_oper()
1427 if (ret == 0 && ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) { in ieee80211_tdls_oper()
1428 cancel_delayed_work(&sdata->u.mgd.tdls_peer_del_work); in ieee80211_tdls_oper()
1429 eth_zero_addr(sdata->u.mgd.tdls_peer); in ieee80211_tdls_oper()
1433 ieee80211_queue_work(&sdata->local->hw, in ieee80211_tdls_oper()
1434 &sdata->u.mgd.request_smps_work); in ieee80211_tdls_oper()
1436 mutex_unlock(&local->mtx); in ieee80211_tdls_oper()
1447 if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc) { in ieee80211_tdls_oper_request()
1448 sdata_err(sdata, "Discarding TDLS oper %d - not STA or disconnected\n", in ieee80211_tdls_oper_request()
1453 cfg80211_tdls_oper_request(sdata->dev, peer, oper, reason_code, gfp); in ieee80211_tdls_oper_request()
1466 ch_sw->switch_time = cpu_to_le16(switch_time); in iee80211_tdls_add_ch_switch_timing()
1467 ch_sw->switch_timeout = cpu_to_le16(switch_timeout); in iee80211_tdls_add_ch_switch_timing()
1481 tf = container_of(skb->data + skb_network_offset(skb), in ieee80211_tdls_find_sw_timing_ie()
1483 ie_start = tf->u.chan_switch_req.variable; in ieee80211_tdls_find_sw_timing_ie()
1485 skb->len - (ie_start - skb->data)); in ieee80211_tdls_find_sw_timing_ie()
1493 struct ieee80211_sub_if_data *sdata = sta->sdata; in ieee80211_tdls_ch_sw_tmpl_get()
1501 * if chandef points to a wide channel add a Secondary-Channel in ieee80211_tdls_ch_sw_tmpl_get()
1504 if (chandef->width == NL80211_CHAN_WIDTH_40) { in ieee80211_tdls_ch_sw_tmpl_get()
1514 sec_chan_ie->sec_chan_offs = ht40plus ? in ieee80211_tdls_ch_sw_tmpl_get()
1525 skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr, in ieee80211_tdls_ch_sw_tmpl_get()
1527 0, 0, !sta->sta.tdls_initiator, in ieee80211_tdls_ch_sw_tmpl_get()
1548 *ch_sw_tm_ie_offset = tm_ie - skb->data; in ieee80211_tdls_ch_sw_tmpl_get()
1553 sta->sta.addr, chandef->chan->center_freq, chandef->width); in ieee80211_tdls_ch_sw_tmpl_get()
1563 struct ieee80211_local *local = sdata->local; in ieee80211_tdls_channel_switch() local
1569 if (chandef->chan->freq_offset) in ieee80211_tdls_channel_switch()
1571 return -EOPNOTSUPP; in ieee80211_tdls_channel_switch()
1573 mutex_lock(&local->sta_mtx); in ieee80211_tdls_channel_switch()
1579 ret = -ENOENT; in ieee80211_tdls_channel_switch()
1586 ret = -ENOTSUPP; in ieee80211_tdls_channel_switch()
1593 ret = -ENOENT; in ieee80211_tdls_channel_switch()
1597 ret = drv_tdls_channel_switch(local, sdata, &sta->sta, oper_class, in ieee80211_tdls_channel_switch()
1603 mutex_unlock(&local->sta_mtx); in ieee80211_tdls_channel_switch()
1614 struct ieee80211_local *local = sdata->local; in ieee80211_tdls_cancel_channel_switch() local
1617 mutex_lock(&local->sta_mtx); in ieee80211_tdls_cancel_channel_switch()
1632 drv_tdls_cancel_channel_switch(local, sdata, &sta->sta); in ieee80211_tdls_cancel_channel_switch()
1636 mutex_unlock(&local->sta_mtx); in ieee80211_tdls_cancel_channel_switch()
1643 struct ieee80211_sub_if_data *sdata = sta->sdata; in ieee80211_tdls_ch_sw_resp_tmpl_get()
1650 skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr, in ieee80211_tdls_ch_sw_resp_tmpl_get()
1652 0, 0, !sta->sta.tdls_initiator, in ieee80211_tdls_ch_sw_resp_tmpl_get()
1674 *ch_sw_tm_ie_offset = tm_ie - skb->data; in ieee80211_tdls_ch_sw_resp_tmpl_get()
1678 sta->sta.addr); in ieee80211_tdls_ch_sw_resp_tmpl_get()
1686 struct ieee80211_local *local = sdata->local; in ieee80211_process_tdls_channel_switch_resp() local
1689 struct ieee80211_tdls_data *tf = (void *)skb->data; in ieee80211_process_tdls_channel_switch_resp()
1697 params.timestamp = rx_status->device_timestamp; in ieee80211_process_tdls_channel_switch_resp()
1699 if (skb->len < baselen) { in ieee80211_process_tdls_channel_switch_resp()
1701 skb->len); in ieee80211_process_tdls_channel_switch_resp()
1702 return -EINVAL; in ieee80211_process_tdls_channel_switch_resp()
1705 mutex_lock(&local->sta_mtx); in ieee80211_process_tdls_channel_switch_resp()
1706 sta = sta_info_get(sdata, tf->sa); in ieee80211_process_tdls_channel_switch_resp()
1708 tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n", in ieee80211_process_tdls_channel_switch_resp()
1709 tf->sa); in ieee80211_process_tdls_channel_switch_resp()
1710 ret = -EINVAL; in ieee80211_process_tdls_channel_switch_resp()
1714 params.sta = &sta->sta; in ieee80211_process_tdls_channel_switch_resp()
1715 params.status = le16_to_cpu(tf->u.chan_switch_resp.status_code); in ieee80211_process_tdls_channel_switch_resp()
1721 ieee802_11_parse_elems(tf->u.chan_switch_resp.variable, in ieee80211_process_tdls_channel_switch_resp()
1722 skb->len - baselen, false, &elems, in ieee80211_process_tdls_channel_switch_resp()
1726 ret = -EINVAL; in ieee80211_process_tdls_channel_switch_resp()
1731 tdls_dbg(sdata, "TDLS channel switch resp - missing IEs\n"); in ieee80211_process_tdls_channel_switch_resp()
1732 ret = -EINVAL; in ieee80211_process_tdls_channel_switch_resp()
1738 !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN); in ieee80211_process_tdls_channel_switch_resp()
1739 if (local_initiator == sta->sta.tdls_initiator) { in ieee80211_process_tdls_channel_switch_resp()
1740 tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n"); in ieee80211_process_tdls_channel_switch_resp()
1741 ret = -EINVAL; in ieee80211_process_tdls_channel_switch_resp()
1745 params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time); in ieee80211_process_tdls_channel_switch_resp()
1746 params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout); in ieee80211_process_tdls_channel_switch_resp()
1751 ret = -ENOENT; in ieee80211_process_tdls_channel_switch_resp()
1757 drv_tdls_recv_channel_switch(sdata->local, sdata, &params); in ieee80211_process_tdls_channel_switch_resp()
1761 tf->sa, params.status); in ieee80211_process_tdls_channel_switch_resp()
1764 mutex_unlock(&local->sta_mtx); in ieee80211_process_tdls_channel_switch_resp()
1773 struct ieee80211_local *local = sdata->local; in ieee80211_process_tdls_channel_switch_req() local
1783 struct ieee80211_tdls_data *tf = (void *)skb->data; in ieee80211_process_tdls_channel_switch_req()
1790 params.timestamp = rx_status->device_timestamp; in ieee80211_process_tdls_channel_switch_req()
1792 if (skb->len < baselen) { in ieee80211_process_tdls_channel_switch_req()
1794 skb->len); in ieee80211_process_tdls_channel_switch_req()
1795 return -EINVAL; in ieee80211_process_tdls_channel_switch_req()
1798 target_channel = tf->u.chan_switch_req.target_channel; in ieee80211_process_tdls_channel_switch_req()
1799 oper_class = tf->u.chan_switch_req.oper_class; in ieee80211_process_tdls_channel_switch_req()
1803 * ambiguous - there are multiple tables (US/Europe/JP/Global). The in ieee80211_process_tdls_channel_switch_req()
1807 * IEEE802.11-2012. in ieee80211_process_tdls_channel_switch_req()
1823 return -EINVAL; in ieee80211_process_tdls_channel_switch_req()
1826 chan = ieee80211_get_channel(sdata->local->hw.wiphy, freq); in ieee80211_process_tdls_channel_switch_req()
1831 return -EINVAL; in ieee80211_process_tdls_channel_switch_req()
1834 ieee802_11_parse_elems(tf->u.chan_switch_req.variable, in ieee80211_process_tdls_channel_switch_req()
1835 skb->len - baselen, false, &elems, NULL, NULL); in ieee80211_process_tdls_channel_switch_req()
1838 return -EINVAL; in ieee80211_process_tdls_channel_switch_req()
1842 tdls_dbg(sdata, "TDLS channel switch req - missing IEs\n"); in ieee80211_process_tdls_channel_switch_req()
1843 return -EINVAL; in ieee80211_process_tdls_channel_switch_req()
1849 switch (elems.sec_chan_offs->sec_chan_offs) { in ieee80211_process_tdls_channel_switch_req()
1865 if (!cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &chandef, in ieee80211_process_tdls_channel_switch_req()
1866 sdata->wdev.iftype)) { in ieee80211_process_tdls_channel_switch_req()
1868 return -EINVAL; in ieee80211_process_tdls_channel_switch_req()
1871 mutex_lock(&local->sta_mtx); in ieee80211_process_tdls_channel_switch_req()
1872 sta = sta_info_get(sdata, tf->sa); in ieee80211_process_tdls_channel_switch_req()
1874 tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n", in ieee80211_process_tdls_channel_switch_req()
1875 tf->sa); in ieee80211_process_tdls_channel_switch_req()
1876 ret = -EINVAL; in ieee80211_process_tdls_channel_switch_req()
1880 params.sta = &sta->sta; in ieee80211_process_tdls_channel_switch_req()
1884 !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN); in ieee80211_process_tdls_channel_switch_req()
1885 if (local_initiator == sta->sta.tdls_initiator) { in ieee80211_process_tdls_channel_switch_req()
1886 tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n"); in ieee80211_process_tdls_channel_switch_req()
1887 ret = -EINVAL; in ieee80211_process_tdls_channel_switch_req()
1892 if (!sta->sta.ht_cap.ht_supported && elems.sec_chan_offs && in ieee80211_process_tdls_channel_switch_req()
1893 elems.sec_chan_offs->sec_chan_offs) { in ieee80211_process_tdls_channel_switch_req()
1894 tdls_dbg(sdata, "TDLS chan switch - wide chan unsupported\n"); in ieee80211_process_tdls_channel_switch_req()
1895 ret = -ENOTSUPP; in ieee80211_process_tdls_channel_switch_req()
1900 params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time); in ieee80211_process_tdls_channel_switch_req()
1901 params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout); in ieee80211_process_tdls_channel_switch_req()
1907 ret = -ENOENT; in ieee80211_process_tdls_channel_switch_req()
1911 drv_tdls_recv_channel_switch(sdata->local, sdata, &params); in ieee80211_process_tdls_channel_switch_req()
1915 tf->sa, params.chandef->chan->center_freq, in ieee80211_process_tdls_channel_switch_req()
1916 params.chandef->width); in ieee80211_process_tdls_channel_switch_req()
1918 mutex_unlock(&local->sta_mtx); in ieee80211_process_tdls_channel_switch_req()
1927 struct ieee80211_tdls_data *tf = (void *)skb->data; in ieee80211_process_tdls_channel_switch()
1928 struct wiphy *wiphy = sdata->local->hw.wiphy; in ieee80211_process_tdls_channel_switch()
1933 if (!(wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH)) in ieee80211_process_tdls_channel_switch()
1940 * The packet/size was already validated by mac80211 Rx path, only look in ieee80211_process_tdls_channel_switch()
1943 switch (tf->action_code) { in ieee80211_process_tdls_channel_switch()
1962 list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) { in ieee80211_teardown_tdls_peers()
1963 if (!sta->sta.tdls || sta->sdata != sdata || !sta->uploaded || in ieee80211_teardown_tdls_peers()
1967 ieee80211_tdls_oper_request(&sdata->vif, sta->sta.addr, in ieee80211_teardown_tdls_peers()
1976 struct ieee80211_local *local = in ieee80211_tdls_chsw_work() local
1983 while ((skb = skb_dequeue(&local->skb_queue_tdls_chsw))) { in ieee80211_tdls_chsw_work()
1984 tf = (struct ieee80211_tdls_data *)skb->data; in ieee80211_tdls_chsw_work()
1985 list_for_each_entry(sdata, &local->interfaces, list) { in ieee80211_tdls_chsw_work()
1987 sdata->vif.type != NL80211_IFTYPE_STATION || in ieee80211_tdls_chsw_work()
1988 !ether_addr_equal(tf->da, sdata->vif.addr)) in ieee80211_tdls_chsw_work()
2006 sta = ieee80211_find_sta(&sdata->vif, peer); in ieee80211_tdls_handle_disconnect()
2007 if (!sta || !sta->tdls) { in ieee80211_tdls_handle_disconnect()
2017 ieee80211_tdls_oper_request(&sdata->vif, peer, in ieee80211_tdls_handle_disconnect()