diff options
author | David S. Miller <davem@davemloft.net> | 2018-03-29 16:23:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-03-29 16:23:26 -0400 |
commit | e15f20ea33b8e5074145abe464b4b48acea505d9 (patch) | |
tree | ad173bb9facf7b0673a2cc313c2d52778b8f18ff | |
parent | e3e67a4f07433d0159dcbd2abe7d6bdf6e1268c8 (diff) | |
parent | c470bdc1aaf36669e04ba65faf1092b2d1c6cabe (diff) |
Merge tag 'mac80211-next-for-davem-2018-03-29' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says:
====================
We have a fair number of patches, but many of them are from the
first bullet here:
* EAPoL-over-nl80211 from Denis - this will let us fix
some long-standing issues with bridging, races with
encryption and more
* DFS offload support from the qtnfmac folks
* regulatory database changes for the new ETSI adaptivity
requirements
* various other fixes and small enhancements
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 10 | ||||
-rw-r--r-- | include/net/cfg80211.h | 76 | ||||
-rw-r--r-- | include/net/mac80211.h | 3 | ||||
-rw-r--r-- | include/net/regulatory.h | 28 | ||||
-rw-r--r-- | include/uapi/linux/nl80211.h | 46 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 12 | ||||
-rw-r--r-- | net/mac80211/ht.c | 15 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 12 | ||||
-rw-r--r-- | net/mac80211/iface.c | 2 | ||||
-rw-r--r-- | net/mac80211/key.c | 8 | ||||
-rw-r--r-- | net/mac80211/main.c | 10 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 168 | ||||
-rw-r--r-- | net/mac80211/rx.c | 45 | ||||
-rw-r--r-- | net/mac80211/scan.c | 4 | ||||
-rw-r--r-- | net/mac80211/tx.c | 46 | ||||
-rw-r--r-- | net/mac80211/util.c | 47 | ||||
-rw-r--r-- | net/mac80211/vht.c | 32 | ||||
-rw-r--r-- | net/wireless/ap.c | 1 | ||||
-rw-r--r-- | net/wireless/chan.c | 9 | ||||
-rw-r--r-- | net/wireless/core.h | 12 | ||||
-rw-r--r-- | net/wireless/ibss.c | 27 | ||||
-rw-r--r-- | net/wireless/mesh.c | 16 | ||||
-rw-r--r-- | net/wireless/mlme.c | 9 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 205 | ||||
-rw-r--r-- | net/wireless/rdev-ops.h | 15 | ||||
-rw-r--r-- | net/wireless/reg.c | 206 | ||||
-rw-r--r-- | net/wireless/sme.c | 43 | ||||
-rw-r--r-- | net/wireless/trace.h | 47 |
30 files changed, 979 insertions, 181 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index a37f4b1d9d30..6afe896e5cb8 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -2584,8 +2584,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, | |||
2584 | addr[4] = idx; | 2584 | addr[4] = idx; |
2585 | memcpy(data->addresses[0].addr, addr, ETH_ALEN); | 2585 | memcpy(data->addresses[0].addr, addr, ETH_ALEN); |
2586 | /* Why need here second address ? */ | 2586 | /* Why need here second address ? */ |
2587 | data->addresses[1].addr[0] |= 0x40; | ||
2588 | memcpy(data->addresses[1].addr, addr, ETH_ALEN); | 2587 | memcpy(data->addresses[1].addr, addr, ETH_ALEN); |
2588 | data->addresses[1].addr[0] |= 0x40; | ||
2589 | hw->wiphy->n_addresses = 2; | 2589 | hw->wiphy->n_addresses = 2; |
2590 | hw->wiphy->addresses = data->addresses; | 2590 | hw->wiphy->addresses = data->addresses; |
2591 | /* possible address clash is checked at hash table insertion */ | 2591 | /* possible address clash is checked at hash table insertion */ |
@@ -3529,8 +3529,12 @@ static void __net_exit hwsim_exit_net(struct net *net) | |||
3529 | list_del(&data->list); | 3529 | list_del(&data->list); |
3530 | rhashtable_remove_fast(&hwsim_radios_rht, &data->rht, | 3530 | rhashtable_remove_fast(&hwsim_radios_rht, &data->rht, |
3531 | hwsim_rht_params); | 3531 | hwsim_rht_params); |
3532 | INIT_WORK(&data->destroy_work, destroy_radio); | 3532 | hwsim_radios_generation++; |
3533 | queue_work(hwsim_wq, &data->destroy_work); | 3533 | spin_unlock_bh(&hwsim_radio_lock); |
3534 | mac80211_hwsim_del_radio(data, | ||
3535 | wiphy_name(data->hw->wiphy), | ||
3536 | NULL); | ||
3537 | spin_lock_bh(&hwsim_radio_lock); | ||
3534 | } | 3538 | } |
3535 | spin_unlock_bh(&hwsim_radio_lock); | 3539 | spin_unlock_bh(&hwsim_radio_lock); |
3536 | 3540 | ||
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index fc40843baed3..250dac390806 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -6,6 +6,7 @@ | |||
6 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> | 6 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
7 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 7 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
8 | * Copyright 2015-2017 Intel Deutschland GmbH | 8 | * Copyright 2015-2017 Intel Deutschland GmbH |
9 | * Copyright (C) 2018 Intel Corporation | ||
9 | * | 10 | * |
10 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -646,6 +647,8 @@ struct survey_info { | |||
646 | * allowed through even on unauthorized ports | 647 | * allowed through even on unauthorized ports |
647 | * @control_port_no_encrypt: TRUE to prevent encryption of control port | 648 | * @control_port_no_encrypt: TRUE to prevent encryption of control port |
648 | * protocol frames. | 649 | * protocol frames. |
650 | * @control_port_over_nl80211: TRUE if userspace expects to exchange control | ||
651 | * port frames over NL80211 instead of the network interface. | ||
649 | * @wep_keys: static WEP keys, if not NULL points to an array of | 652 | * @wep_keys: static WEP keys, if not NULL points to an array of |
650 | * CFG80211_MAX_WEP_KEYS WEP keys | 653 | * CFG80211_MAX_WEP_KEYS WEP keys |
651 | * @wep_tx_key: key index (0..3) of the default TX static WEP key | 654 | * @wep_tx_key: key index (0..3) of the default TX static WEP key |
@@ -661,6 +664,7 @@ struct cfg80211_crypto_settings { | |||
661 | bool control_port; | 664 | bool control_port; |
662 | __be16 control_port_ethertype; | 665 | __be16 control_port_ethertype; |
663 | bool control_port_no_encrypt; | 666 | bool control_port_no_encrypt; |
667 | bool control_port_over_nl80211; | ||
664 | struct key_params *wep_keys; | 668 | struct key_params *wep_keys; |
665 | int wep_tx_key; | 669 | int wep_tx_key; |
666 | const u8 *psk; | 670 | const u8 *psk; |
@@ -1450,6 +1454,8 @@ struct mesh_config { | |||
1450 | * @userspace_handles_dfs: whether user space controls DFS operation, i.e. | 1454 | * @userspace_handles_dfs: whether user space controls DFS operation, i.e. |
1451 | * changes the channel when a radar is detected. This is required | 1455 | * changes the channel when a radar is detected. This is required |
1452 | * to operate on DFS channels. | 1456 | * to operate on DFS channels. |
1457 | * @control_port_over_nl80211: TRUE if userspace expects to exchange control | ||
1458 | * port frames over NL80211 instead of the network interface. | ||
1453 | * | 1459 | * |
1454 | * These parameters are fixed when the mesh is created. | 1460 | * These parameters are fixed when the mesh is created. |
1455 | */ | 1461 | */ |
@@ -1472,6 +1478,7 @@ struct mesh_setup { | |||
1472 | u32 basic_rates; | 1478 | u32 basic_rates; |
1473 | struct cfg80211_bitrate_mask beacon_rate; | 1479 | struct cfg80211_bitrate_mask beacon_rate; |
1474 | bool userspace_handles_dfs; | 1480 | bool userspace_handles_dfs; |
1481 | bool control_port_over_nl80211; | ||
1475 | }; | 1482 | }; |
1476 | 1483 | ||
1477 | /** | 1484 | /** |
@@ -2030,6 +2037,8 @@ struct cfg80211_disassoc_request { | |||
2030 | * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is | 2037 | * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is |
2031 | * required to assume that the port is unauthorized until authorized by | 2038 | * required to assume that the port is unauthorized until authorized by |
2032 | * user space. Otherwise, port is marked authorized by default. | 2039 | * user space. Otherwise, port is marked authorized by default. |
2040 | * @control_port_over_nl80211: TRUE if userspace expects to exchange control | ||
2041 | * port frames over NL80211 instead of the network interface. | ||
2033 | * @userspace_handles_dfs: whether user space controls DFS operation, i.e. | 2042 | * @userspace_handles_dfs: whether user space controls DFS operation, i.e. |
2034 | * changes the channel when a radar is detected. This is required | 2043 | * changes the channel when a radar is detected. This is required |
2035 | * to operate on DFS channels. | 2044 | * to operate on DFS channels. |
@@ -2053,6 +2062,7 @@ struct cfg80211_ibss_params { | |||
2053 | bool channel_fixed; | 2062 | bool channel_fixed; |
2054 | bool privacy; | 2063 | bool privacy; |
2055 | bool control_port; | 2064 | bool control_port; |
2065 | bool control_port_over_nl80211; | ||
2056 | bool userspace_handles_dfs; | 2066 | bool userspace_handles_dfs; |
2057 | int mcast_rate[NUM_NL80211_BANDS]; | 2067 | int mcast_rate[NUM_NL80211_BANDS]; |
2058 | struct ieee80211_ht_cap ht_capa; | 2068 | struct ieee80211_ht_cap ht_capa; |
@@ -2960,6 +2970,9 @@ struct cfg80211_external_auth_params { | |||
2960 | * | 2970 | * |
2961 | * @external_auth: indicates result of offloaded authentication processing from | 2971 | * @external_auth: indicates result of offloaded authentication processing from |
2962 | * user space | 2972 | * user space |
2973 | * | ||
2974 | * @tx_control_port: TX a control port frame (EAPoL). The noencrypt parameter | ||
2975 | * tells the driver that the frame should not be encrypted. | ||
2963 | */ | 2976 | */ |
2964 | struct cfg80211_ops { | 2977 | struct cfg80211_ops { |
2965 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); | 2978 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); |
@@ -3255,6 +3268,12 @@ struct cfg80211_ops { | |||
3255 | const u8 *aa); | 3268 | const u8 *aa); |
3256 | int (*external_auth)(struct wiphy *wiphy, struct net_device *dev, | 3269 | int (*external_auth)(struct wiphy *wiphy, struct net_device *dev, |
3257 | struct cfg80211_external_auth_params *params); | 3270 | struct cfg80211_external_auth_params *params); |
3271 | |||
3272 | int (*tx_control_port)(struct wiphy *wiphy, | ||
3273 | struct net_device *dev, | ||
3274 | const u8 *buf, size_t len, | ||
3275 | const u8 *dest, const __be16 proto, | ||
3276 | const bool noencrypt); | ||
3258 | }; | 3277 | }; |
3259 | 3278 | ||
3260 | /* | 3279 | /* |
@@ -3572,15 +3591,15 @@ enum wiphy_opmode_flag { | |||
3572 | /** | 3591 | /** |
3573 | * struct sta_opmode_info - Station's ht/vht operation mode information | 3592 | * struct sta_opmode_info - Station's ht/vht operation mode information |
3574 | * @changed: contains value from &enum wiphy_opmode_flag | 3593 | * @changed: contains value from &enum wiphy_opmode_flag |
3575 | * @smps_mode: New SMPS mode of a station | 3594 | * @smps_mode: New SMPS mode value from &enum nl80211_smps_mode of a station |
3576 | * @bw: new max bandwidth value of a station | 3595 | * @bw: new max bandwidth value from &enum nl80211_chan_width of a station |
3577 | * @rx_nss: new rx_nss value of a station | 3596 | * @rx_nss: new rx_nss value of a station |
3578 | */ | 3597 | */ |
3579 | 3598 | ||
3580 | struct sta_opmode_info { | 3599 | struct sta_opmode_info { |
3581 | u32 changed; | 3600 | u32 changed; |
3582 | u8 smps_mode; | 3601 | enum nl80211_smps_mode smps_mode; |
3583 | u8 bw; | 3602 | enum nl80211_chan_width bw; |
3584 | u8 rx_nss; | 3603 | u8 rx_nss; |
3585 | }; | 3604 | }; |
3586 | 3605 | ||
@@ -4657,6 +4676,33 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy, | |||
4657 | */ | 4676 | */ |
4658 | const char *reg_initiator_name(enum nl80211_reg_initiator initiator); | 4677 | const char *reg_initiator_name(enum nl80211_reg_initiator initiator); |
4659 | 4678 | ||
4679 | /** | ||
4680 | * DOC: Internal regulatory db functions | ||
4681 | * | ||
4682 | */ | ||
4683 | |||
4684 | /** | ||
4685 | * reg_query_regdb_wmm - Query internal regulatory db for wmm rule | ||
4686 | * Regulatory self-managed driver can use it to proactively | ||
4687 | * | ||
4688 | * @alpha2: the ISO/IEC 3166 alpha2 wmm rule to be queried. | ||
4689 | * @freq: the freqency(in MHz) to be queried. | ||
4690 | * @ptr: pointer where the regdb wmm data is to be stored (or %NULL if | ||
4691 | * irrelevant). This can be used later for deduplication. | ||
4692 | * @rule: pointer to store the wmm rule from the regulatory db. | ||
4693 | * | ||
4694 | * Self-managed wireless drivers can use this function to query | ||
4695 | * the internal regulatory database to check whether the given | ||
4696 | * ISO/IEC 3166 alpha2 country and freq have wmm rule limitations. | ||
4697 | * | ||
4698 | * Drivers should check the return value, its possible you can get | ||
4699 | * an -ENODATA. | ||
4700 | * | ||
4701 | * Return: 0 on success. -ENODATA. | ||
4702 | */ | ||
4703 | int reg_query_regdb_wmm(char *alpha2, int freq, u32 *ptr, | ||
4704 | struct ieee80211_wmm_rule *rule); | ||
4705 | |||
4660 | /* | 4706 | /* |
4661 | * callbacks for asynchronous cfg80211 methods, notification | 4707 | * callbacks for asynchronous cfg80211 methods, notification |
4662 | * functions and BSS handling helpers | 4708 | * functions and BSS handling helpers |
@@ -5694,6 +5740,28 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, | |||
5694 | 5740 | ||
5695 | 5741 | ||
5696 | /** | 5742 | /** |
5743 | * cfg80211_rx_control_port - notification about a received control port frame | ||
5744 | * @dev: The device the frame matched to | ||
5745 | * @buf: control port frame | ||
5746 | * @len: length of the frame data | ||
5747 | * @addr: The peer from which the frame was received | ||
5748 | * @proto: frame protocol, typically PAE or Pre-authentication | ||
5749 | * @unencrypted: Whether the frame was received unencrypted | ||
5750 | * | ||
5751 | * This function is used to inform userspace about a received control port | ||
5752 | * frame. It should only be used if userspace indicated it wants to receive | ||
5753 | * control port frames over nl80211. | ||
5754 | * | ||
5755 | * The frame is the data portion of the 802.3 or 802.11 data frame with all | ||
5756 | * network layer headers removed (e.g. the raw EAPoL frame). | ||
5757 | * | ||
5758 | * Return: %true if the frame was passed to userspace | ||
5759 | */ | ||
5760 | bool cfg80211_rx_control_port(struct net_device *dev, | ||
5761 | const u8 *buf, size_t len, | ||
5762 | const u8 *addr, u16 proto, bool unencrypted); | ||
5763 | |||
5764 | /** | ||
5697 | * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event | 5765 | * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event |
5698 | * @dev: network device | 5766 | * @dev: network device |
5699 | * @rssi_event: the triggered RSSI event | 5767 | * @rssi_event: the triggered RSSI event |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2449982daf75..d2279b2d61aa 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -302,6 +302,8 @@ struct ieee80211_vif_chanctx_switch { | |||
302 | * @BSS_CHANGED_MU_GROUPS: VHT MU-MIMO group id or user position changed | 302 | * @BSS_CHANGED_MU_GROUPS: VHT MU-MIMO group id or user position changed |
303 | * @BSS_CHANGED_KEEP_ALIVE: keep alive options (idle period or protected | 303 | * @BSS_CHANGED_KEEP_ALIVE: keep alive options (idle period or protected |
304 | * keep alive) changed. | 304 | * keep alive) changed. |
305 | * @BSS_CHANGED_MCAST_RATE: Multicast Rate setting changed for this interface | ||
306 | * | ||
305 | */ | 307 | */ |
306 | enum ieee80211_bss_change { | 308 | enum ieee80211_bss_change { |
307 | BSS_CHANGED_ASSOC = 1<<0, | 309 | BSS_CHANGED_ASSOC = 1<<0, |
@@ -329,6 +331,7 @@ enum ieee80211_bss_change { | |||
329 | BSS_CHANGED_OCB = 1<<22, | 331 | BSS_CHANGED_OCB = 1<<22, |
330 | BSS_CHANGED_MU_GROUPS = 1<<23, | 332 | BSS_CHANGED_MU_GROUPS = 1<<23, |
331 | BSS_CHANGED_KEEP_ALIVE = 1<<24, | 333 | BSS_CHANGED_KEEP_ALIVE = 1<<24, |
334 | BSS_CHANGED_MCAST_RATE = 1<<25, | ||
332 | 335 | ||
333 | /* when adding here, make sure to change ieee80211_reconfig */ | 336 | /* when adding here, make sure to change ieee80211_reconfig */ |
334 | }; | 337 | }; |
diff --git a/include/net/regulatory.h b/include/net/regulatory.h index f83cacce3308..60f8cc86a447 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h | |||
@@ -4,6 +4,7 @@ | |||
4 | * regulatory support structures | 4 | * regulatory support structures |
5 | * | 5 | * |
6 | * Copyright 2008-2009 Luis R. Rodriguez <mcgrof@qca.qualcomm.com> | 6 | * Copyright 2008-2009 Luis R. Rodriguez <mcgrof@qca.qualcomm.com> |
7 | * Copyright (C) 2018 Intel Corporation | ||
7 | * | 8 | * |
8 | * Permission to use, copy, modify, and/or distribute this software for any | 9 | * Permission to use, copy, modify, and/or distribute this software for any |
9 | * purpose with or without fee is hereby granted, provided that the above | 10 | * purpose with or without fee is hereby granted, provided that the above |
@@ -188,9 +189,35 @@ struct ieee80211_power_rule { | |||
188 | u32 max_eirp; | 189 | u32 max_eirp; |
189 | }; | 190 | }; |
190 | 191 | ||
192 | /** | ||
193 | * struct ieee80211_wmm_ac - used to store per ac wmm regulatory limitation | ||
194 | * | ||
195 | * The information provided in this structure is required for QoS | ||
196 | * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29. | ||
197 | * | ||
198 | * @cw_min: minimum contention window [a value of the form | ||
199 | * 2^n-1 in the range 1..32767] | ||
200 | * @cw_max: maximum contention window [like @cw_min] | ||
201 | * @cot: maximum burst time in units of 32 usecs, 0 meaning disabled | ||
202 | * @aifsn: arbitration interframe space [0..255] | ||
203 | * | ||
204 | */ | ||
205 | struct ieee80211_wmm_ac { | ||
206 | u16 cw_min; | ||
207 | u16 cw_max; | ||
208 | u16 cot; | ||
209 | u8 aifsn; | ||
210 | }; | ||
211 | |||
212 | struct ieee80211_wmm_rule { | ||
213 | struct ieee80211_wmm_ac client[IEEE80211_NUM_ACS]; | ||
214 | struct ieee80211_wmm_ac ap[IEEE80211_NUM_ACS]; | ||
215 | }; | ||
216 | |||
191 | struct ieee80211_reg_rule { | 217 | struct ieee80211_reg_rule { |
192 | struct ieee80211_freq_range freq_range; | 218 | struct ieee80211_freq_range freq_range; |
193 | struct ieee80211_power_rule power_rule; | 219 | struct ieee80211_power_rule power_rule; |
220 | struct ieee80211_wmm_rule *wmm_rule; | ||
194 | u32 flags; | 221 | u32 flags; |
195 | u32 dfs_cac_ms; | 222 | u32 dfs_cac_ms; |
196 | }; | 223 | }; |
@@ -198,6 +225,7 @@ struct ieee80211_reg_rule { | |||
198 | struct ieee80211_regdomain { | 225 | struct ieee80211_regdomain { |
199 | struct rcu_head rcu_head; | 226 | struct rcu_head rcu_head; |
200 | u32 n_reg_rules; | 227 | u32 n_reg_rules; |
228 | u32 n_wmm_rules; | ||
201 | char alpha2[3]; | 229 | char alpha2[3]; |
202 | enum nl80211_dfs_regions dfs_region; | 230 | enum nl80211_dfs_regions dfs_region; |
203 | struct ieee80211_reg_rule reg_rules[]; | 231 | struct ieee80211_reg_rule reg_rules[]; |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index c13c84304be3..15daf5e2638d 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -542,7 +542,8 @@ | |||
542 | * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, | 542 | * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, |
543 | * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, | 543 | * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, |
544 | * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, | 544 | * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, |
545 | * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, %NL80211_ATTR_MAC_HINT, and | 545 | * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, |
546 | * %NL80211_ATTR_CONTROL_PORT_OVER_NL80211, %NL80211_ATTR_MAC_HINT, and | ||
546 | * %NL80211_ATTR_WIPHY_FREQ_HINT. | 547 | * %NL80211_ATTR_WIPHY_FREQ_HINT. |
547 | * If included, %NL80211_ATTR_MAC and %NL80211_ATTR_WIPHY_FREQ are | 548 | * If included, %NL80211_ATTR_MAC and %NL80211_ATTR_WIPHY_FREQ are |
548 | * restrictions on BSS selection, i.e., they effectively prevent roaming | 549 | * restrictions on BSS selection, i.e., they effectively prevent roaming |
@@ -990,6 +991,17 @@ | |||
990 | * &NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed | 991 | * &NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed |
991 | * &NL80211_CMD_DISCONNECT should be indicated instead. | 992 | * &NL80211_CMD_DISCONNECT should be indicated instead. |
992 | * | 993 | * |
994 | * @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request | ||
995 | * and RX notification. This command is used both as a request to transmit | ||
996 | * a control port frame and as a notification that a control port frame | ||
997 | * has been received. %NL80211_ATTR_FRAME is used to specify the | ||
998 | * frame contents. The frame is the raw EAPoL data, without ethernet or | ||
999 | * 802.11 headers. | ||
1000 | * When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, | ||
1001 | * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added | ||
1002 | * indicating the protocol type of the received frame; whether the frame | ||
1003 | * was received unencrypted and the MAC address of the peer respectively. | ||
1004 | * | ||
993 | * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. | 1005 | * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. |
994 | * | 1006 | * |
995 | * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host | 1007 | * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host |
@@ -1228,6 +1240,8 @@ enum nl80211_commands { | |||
1228 | 1240 | ||
1229 | NL80211_CMD_STA_OPMODE_CHANGED, | 1241 | NL80211_CMD_STA_OPMODE_CHANGED, |
1230 | 1242 | ||
1243 | NL80211_CMD_CONTROL_PORT_FRAME, | ||
1244 | |||
1231 | /* add new commands above here */ | 1245 | /* add new commands above here */ |
1232 | 1246 | ||
1233 | /* used to define NL80211_CMD_MAX below */ | 1247 | /* used to define NL80211_CMD_MAX below */ |
@@ -1475,6 +1489,15 @@ enum nl80211_commands { | |||
1475 | * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with | 1489 | * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with |
1476 | * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom | 1490 | * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom |
1477 | * ethertype frames used for key negotiation must not be encrypted. | 1491 | * ethertype frames used for key negotiation must not be encrypted. |
1492 | * @NL80211_ATTR_CONTROL_PORT_OVER_NL80211: A flag indicating whether control | ||
1493 | * port frames (e.g. of type given in %NL80211_ATTR_CONTROL_PORT_ETHERTYPE) | ||
1494 | * will be sent directly to the network interface or sent via the NL80211 | ||
1495 | * socket. If this attribute is missing, then legacy behavior of sending | ||
1496 | * control port frames directly to the network interface is used. If the | ||
1497 | * flag is included, then control port frames are sent over NL80211 instead | ||
1498 | * using %CMD_CONTROL_PORT_FRAME. If control port routing over NL80211 is | ||
1499 | * to be used then userspace must also use the %NL80211_ATTR_SOCKET_OWNER | ||
1500 | * flag. | ||
1478 | * | 1501 | * |
1479 | * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. | 1502 | * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. |
1480 | * We recommend using nested, driver-specific attributes within this. | 1503 | * We recommend using nested, driver-specific attributes within this. |
@@ -1962,6 +1985,12 @@ enum nl80211_commands { | |||
1962 | * multicast group. | 1985 | * multicast group. |
1963 | * If set during %NL80211_CMD_ASSOCIATE or %NL80211_CMD_CONNECT the | 1986 | * If set during %NL80211_CMD_ASSOCIATE or %NL80211_CMD_CONNECT the |
1964 | * station will deauthenticate when the socket is closed. | 1987 | * station will deauthenticate when the socket is closed. |
1988 | * If set during %NL80211_CMD_JOIN_IBSS the IBSS will be automatically | ||
1989 | * torn down when the socket is closed. | ||
1990 | * If set during %NL80211_CMD_JOIN_MESH the mesh setup will be | ||
1991 | * automatically torn down when the socket is closed. | ||
1992 | * If set during %NL80211_CMD_START_AP the AP will be automatically | ||
1993 | * disabled when the socket is closed. | ||
1965 | * | 1994 | * |
1966 | * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is | 1995 | * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is |
1967 | * the TDLS link initiator. | 1996 | * the TDLS link initiator. |
@@ -2628,6 +2657,8 @@ enum nl80211_attrs { | |||
2628 | NL80211_ATTR_NSS, | 2657 | NL80211_ATTR_NSS, |
2629 | NL80211_ATTR_ACK_SIGNAL, | 2658 | NL80211_ATTR_ACK_SIGNAL, |
2630 | 2659 | ||
2660 | NL80211_ATTR_CONTROL_PORT_OVER_NL80211, | ||
2661 | |||
2631 | /* add attributes here, update the policy in nl80211.c */ | 2662 | /* add attributes here, update the policy in nl80211.c */ |
2632 | 2663 | ||
2633 | __NL80211_ATTR_AFTER_LAST, | 2664 | __NL80211_ATTR_AFTER_LAST, |
@@ -4999,6 +5030,14 @@ enum nl80211_feature_flags { | |||
4999 | * @NL80211_EXT_FEATURE_LOW_SPAN_SCAN: Driver supports low span scan. | 5030 | * @NL80211_EXT_FEATURE_LOW_SPAN_SCAN: Driver supports low span scan. |
5000 | * @NL80211_EXT_FEATURE_LOW_POWER_SCAN: Driver supports low power scan. | 5031 | * @NL80211_EXT_FEATURE_LOW_POWER_SCAN: Driver supports low power scan. |
5001 | * @NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN: Driver supports high accuracy scan. | 5032 | * @NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN: Driver supports high accuracy scan. |
5033 | * @NL80211_EXT_FEATURE_DFS_OFFLOAD: HW/driver will offload DFS actions. | ||
5034 | * Device or driver will do all DFS-related actions by itself, | ||
5035 | * informing user-space about CAC progress, radar detection event, | ||
5036 | * channel change triggered by radar detection event. | ||
5037 | * No need to start CAC from user-space, no need to react to | ||
5038 | * "radar detected" event. | ||
5039 | * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211: Driver supports sending and | ||
5040 | * receiving control port frames over nl80211 instead of the netdevice. | ||
5002 | * | 5041 | * |
5003 | * @NUM_NL80211_EXT_FEATURES: number of extended features. | 5042 | * @NUM_NL80211_EXT_FEATURES: number of extended features. |
5004 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. | 5043 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. |
@@ -5029,6 +5068,8 @@ enum nl80211_ext_feature_index { | |||
5029 | NL80211_EXT_FEATURE_LOW_SPAN_SCAN, | 5068 | NL80211_EXT_FEATURE_LOW_SPAN_SCAN, |
5030 | NL80211_EXT_FEATURE_LOW_POWER_SCAN, | 5069 | NL80211_EXT_FEATURE_LOW_POWER_SCAN, |
5031 | NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN, | 5070 | NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN, |
5071 | NL80211_EXT_FEATURE_DFS_OFFLOAD, | ||
5072 | NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211, | ||
5032 | 5073 | ||
5033 | /* add new features before the definition below */ | 5074 | /* add new features before the definition below */ |
5034 | NUM_NL80211_EXT_FEATURES, | 5075 | NUM_NL80211_EXT_FEATURES, |
@@ -5204,6 +5245,8 @@ enum nl80211_smps_mode { | |||
5204 | * non-operating channel is expired and no longer valid. New CAC must | 5245 | * non-operating channel is expired and no longer valid. New CAC must |
5205 | * be done on this channel before starting the operation. This is not | 5246 | * be done on this channel before starting the operation. This is not |
5206 | * applicable for ETSI dfs domain where pre-CAC is valid for ever. | 5247 | * applicable for ETSI dfs domain where pre-CAC is valid for ever. |
5248 | * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started, | ||
5249 | * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled. | ||
5207 | */ | 5250 | */ |
5208 | enum nl80211_radar_event { | 5251 | enum nl80211_radar_event { |
5209 | NL80211_RADAR_DETECTED, | 5252 | NL80211_RADAR_DETECTED, |
@@ -5211,6 +5254,7 @@ enum nl80211_radar_event { | |||
5211 | NL80211_RADAR_CAC_ABORTED, | 5254 | NL80211_RADAR_CAC_ABORTED, |
5212 | NL80211_RADAR_NOP_FINISHED, | 5255 | NL80211_RADAR_NOP_FINISHED, |
5213 | NL80211_RADAR_PRE_CAC_EXPIRED, | 5256 | NL80211_RADAR_PRE_CAC_EXPIRED, |
5257 | NL80211_RADAR_CAC_STARTED, | ||
5214 | }; | 5258 | }; |
5215 | 5259 | ||
5216 | /** | 5260 | /** |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index fd68f6fb02d7..85dbaa891059 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
5 | * Copyright 2013-2015 Intel Mobile Communications GmbH | 5 | * Copyright 2013-2015 Intel Mobile Communications GmbH |
6 | * Copyright (C) 2015-2017 Intel Deutschland GmbH | 6 | * Copyright (C) 2015-2017 Intel Deutschland GmbH |
7 | * Copyright (C) 2018 Intel Corporation | ||
7 | * | 8 | * |
8 | * This file is GPLv2 as found in COPYING. | 9 | * This file is GPLv2 as found in COPYING. |
9 | */ | 10 | */ |
@@ -925,6 +926,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
925 | */ | 926 | */ |
926 | sdata->control_port_protocol = params->crypto.control_port_ethertype; | 927 | sdata->control_port_protocol = params->crypto.control_port_ethertype; |
927 | sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; | 928 | sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; |
929 | sdata->control_port_over_nl80211 = | ||
930 | params->crypto.control_port_over_nl80211; | ||
928 | sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local, | 931 | sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local, |
929 | ¶ms->crypto, | 932 | ¶ms->crypto, |
930 | sdata->vif.type); | 933 | sdata->vif.type); |
@@ -934,6 +937,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
934 | params->crypto.control_port_ethertype; | 937 | params->crypto.control_port_ethertype; |
935 | vlan->control_port_no_encrypt = | 938 | vlan->control_port_no_encrypt = |
936 | params->crypto.control_port_no_encrypt; | 939 | params->crypto.control_port_no_encrypt; |
940 | vlan->control_port_over_nl80211 = | ||
941 | params->crypto.control_port_over_nl80211; | ||
937 | vlan->encrypt_headroom = | 942 | vlan->encrypt_headroom = |
938 | ieee80211_cs_headroom(sdata->local, | 943 | ieee80211_cs_headroom(sdata->local, |
939 | ¶ms->crypto, | 944 | ¶ms->crypto, |
@@ -2019,6 +2024,8 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
2019 | if (err) | 2024 | if (err) |
2020 | return err; | 2025 | return err; |
2021 | 2026 | ||
2027 | sdata->control_port_over_nl80211 = setup->control_port_over_nl80211; | ||
2028 | |||
2022 | /* can mesh use other SMPS modes? */ | 2029 | /* can mesh use other SMPS modes? */ |
2023 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 2030 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
2024 | sdata->needed_rx_chains = sdata->local->rx_chains; | 2031 | sdata->needed_rx_chains = sdata->local->rx_chains; |
@@ -2156,6 +2163,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
2156 | */ | 2163 | */ |
2157 | p.uapsd = false; | 2164 | p.uapsd = false; |
2158 | 2165 | ||
2166 | ieee80211_regulatory_limit_wmm_params(sdata, &p, params->ac); | ||
2167 | |||
2159 | sdata->tx_conf[params->ac] = p; | 2168 | sdata->tx_conf[params->ac] = p; |
2160 | if (drv_conf_tx(local, sdata, params->ac, &p)) { | 2169 | if (drv_conf_tx(local, sdata, params->ac, &p)) { |
2161 | wiphy_debug(local->hw.wiphy, | 2170 | wiphy_debug(local->hw.wiphy, |
@@ -2313,6 +2322,8 @@ static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev, | |||
2313 | memcpy(sdata->vif.bss_conf.mcast_rate, rate, | 2322 | memcpy(sdata->vif.bss_conf.mcast_rate, rate, |
2314 | sizeof(int) * NUM_NL80211_BANDS); | 2323 | sizeof(int) * NUM_NL80211_BANDS); |
2315 | 2324 | ||
2325 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MCAST_RATE); | ||
2326 | |||
2316 | return 0; | 2327 | return 0; |
2317 | } | 2328 | } |
2318 | 2329 | ||
@@ -3786,4 +3797,5 @@ const struct cfg80211_ops mac80211_config_ops = { | |||
3786 | .add_nan_func = ieee80211_add_nan_func, | 3797 | .add_nan_func = ieee80211_add_nan_func, |
3787 | .del_nan_func = ieee80211_del_nan_func, | 3798 | .del_nan_func = ieee80211_del_nan_func, |
3788 | .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast, | 3799 | .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast, |
3800 | .tx_control_port = ieee80211_tx_control_port, | ||
3789 | }; | 3801 | }; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index d7523530d3f8..c78036a0ac94 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -466,6 +466,21 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
466 | __ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_PEER_REQUEST); | 466 | __ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_PEER_REQUEST); |
467 | } | 467 | } |
468 | 468 | ||
469 | enum nl80211_smps_mode | ||
470 | ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps) | ||
471 | { | ||
472 | switch (smps) { | ||
473 | case IEEE80211_SMPS_OFF: | ||
474 | return NL80211_SMPS_OFF; | ||
475 | case IEEE80211_SMPS_STATIC: | ||
476 | return NL80211_SMPS_STATIC; | ||
477 | case IEEE80211_SMPS_DYNAMIC: | ||
478 | return NL80211_SMPS_DYNAMIC; | ||
479 | default: | ||
480 | return NL80211_SMPS_OFF; | ||
481 | } | ||
482 | } | ||
483 | |||
469 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | 484 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, |
470 | enum ieee80211_smps_mode smps, const u8 *da, | 485 | enum ieee80211_smps_mode smps, const u8 *da, |
471 | const u8 *bssid) | 486 | const u8 *bssid) |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index db07e0de9a03..6449a1c2283b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -1839,11 +1839,12 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1839 | IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED | 1839 | IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED |
1840 | | IEEE80211_HT_PARAM_RIFS_MODE; | 1840 | | IEEE80211_HT_PARAM_RIFS_MODE; |
1841 | 1841 | ||
1842 | changed |= BSS_CHANGED_HT; | 1842 | changed |= BSS_CHANGED_HT | BSS_CHANGED_MCAST_RATE; |
1843 | ieee80211_bss_info_change_notify(sdata, changed); | 1843 | ieee80211_bss_info_change_notify(sdata, changed); |
1844 | 1844 | ||
1845 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 1845 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
1846 | sdata->needed_rx_chains = local->rx_chains; | 1846 | sdata->needed_rx_chains = local->rx_chains; |
1847 | sdata->control_port_over_nl80211 = params->control_port_over_nl80211; | ||
1847 | 1848 | ||
1848 | ieee80211_queue_work(&local->hw, &sdata->work); | 1849 | ieee80211_queue_work(&local->hw, &sdata->work); |
1849 | 1850 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ae9c33cd8ada..6372dbdadf53 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> |
6 | * Copyright 2013-2015 Intel Mobile Communications GmbH | 6 | * Copyright 2013-2015 Intel Mobile Communications GmbH |
7 | * Copyright (C) 2018 Intel Corporation | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
@@ -899,6 +900,7 @@ struct ieee80211_sub_if_data { | |||
899 | u16 sequence_number; | 900 | u16 sequence_number; |
900 | __be16 control_port_protocol; | 901 | __be16 control_port_protocol; |
901 | bool control_port_no_encrypt; | 902 | bool control_port_no_encrypt; |
903 | bool control_port_over_nl80211; | ||
902 | int encrypt_headroom; | 904 | int encrypt_headroom; |
903 | 905 | ||
904 | atomic_t num_tx_queued; | 906 | atomic_t num_tx_queued; |
@@ -1734,6 +1736,9 @@ void ieee80211_check_fast_xmit(struct sta_info *sta); | |||
1734 | void ieee80211_check_fast_xmit_all(struct ieee80211_local *local); | 1736 | void ieee80211_check_fast_xmit_all(struct ieee80211_local *local); |
1735 | void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata); | 1737 | void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata); |
1736 | void ieee80211_clear_fast_xmit(struct sta_info *sta); | 1738 | void ieee80211_clear_fast_xmit(struct sta_info *sta); |
1739 | int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, | ||
1740 | const u8 *buf, size_t len, | ||
1741 | const u8 *dest, __be16 proto, bool unencrypted); | ||
1737 | 1742 | ||
1738 | /* HT */ | 1743 | /* HT */ |
1739 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | 1744 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, |
@@ -1788,6 +1793,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); | |||
1788 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid); | 1793 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid); |
1789 | 1794 | ||
1790 | u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs); | 1795 | u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs); |
1796 | enum nl80211_smps_mode | ||
1797 | ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps); | ||
1791 | 1798 | ||
1792 | /* VHT */ | 1799 | /* VHT */ |
1793 | void | 1800 | void |
@@ -1814,6 +1821,8 @@ void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, | |||
1814 | struct ieee80211_sta_vht_cap *vht_cap); | 1821 | struct ieee80211_sta_vht_cap *vht_cap); |
1815 | void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, | 1822 | void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, |
1816 | u16 vht_mask[NL80211_VHT_NSS_MAX]); | 1823 | u16 vht_mask[NL80211_VHT_NSS_MAX]); |
1824 | enum nl80211_chan_width | ||
1825 | ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta); | ||
1817 | 1826 | ||
1818 | /* Spectrum management */ | 1827 | /* Spectrum management */ |
1819 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 1828 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
@@ -1865,6 +1874,9 @@ extern const void *const mac80211_wiphy_privid; /* for wiphy privid */ | |||
1865 | int ieee80211_frame_duration(enum nl80211_band band, size_t len, | 1874 | int ieee80211_frame_duration(enum nl80211_band band, size_t len, |
1866 | int rate, int erp, int short_preamble, | 1875 | int rate, int erp, int short_preamble, |
1867 | int shift); | 1876 | int shift); |
1877 | void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata, | ||
1878 | struct ieee80211_tx_queue_params *qparam, | ||
1879 | int ac); | ||
1868 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | 1880 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, |
1869 | bool bss_notify, bool enable_qos); | 1881 | bool bss_notify, bool enable_qos); |
1870 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | 1882 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d13ba064951f..555e389b7dfa 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -519,6 +519,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
519 | master->control_port_protocol; | 519 | master->control_port_protocol; |
520 | sdata->control_port_no_encrypt = | 520 | sdata->control_port_no_encrypt = |
521 | master->control_port_no_encrypt; | 521 | master->control_port_no_encrypt; |
522 | sdata->control_port_over_nl80211 = | ||
523 | master->control_port_over_nl80211; | ||
522 | sdata->vif.cab_queue = master->vif.cab_queue; | 524 | sdata->vif.cab_queue = master->vif.cab_queue; |
523 | memcpy(sdata->vif.hw_queue, master->vif.hw_queue, | 525 | memcpy(sdata->vif.hw_queue, master->vif.hw_queue, |
524 | sizeof(sdata->vif.hw_queue)); | 526 | sizeof(sdata->vif.hw_queue)); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index aee05ec3f7ea..ee0d0cc8dc3b 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -126,7 +126,7 @@ static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata, | |||
126 | 126 | ||
127 | static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | 127 | static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) |
128 | { | 128 | { |
129 | struct ieee80211_sub_if_data *sdata; | 129 | struct ieee80211_sub_if_data *sdata = key->sdata; |
130 | struct sta_info *sta; | 130 | struct sta_info *sta; |
131 | int ret = -EOPNOTSUPP; | 131 | int ret = -EOPNOTSUPP; |
132 | 132 | ||
@@ -162,7 +162,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
162 | if (sta && !sta->uploaded) | 162 | if (sta && !sta->uploaded) |
163 | goto out_unsupported; | 163 | goto out_unsupported; |
164 | 164 | ||
165 | sdata = key->sdata; | ||
166 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { | 165 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { |
167 | /* | 166 | /* |
168 | * The driver doesn't know anything about VLAN interfaces. | 167 | * The driver doesn't know anything about VLAN interfaces. |
@@ -214,8 +213,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
214 | /* all of these we can do in software - if driver can */ | 213 | /* all of these we can do in software - if driver can */ |
215 | if (ret == 1) | 214 | if (ret == 1) |
216 | return 0; | 215 | return 0; |
217 | if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL)) | 216 | if (ieee80211_hw_check(&key->local->hw, SW_CRYPTO_CONTROL)) { |
217 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
218 | return 0; | ||
218 | return -EINVAL; | 219 | return -EINVAL; |
220 | } | ||
219 | return 0; | 221 | return 0; |
220 | default: | 222 | default: |
221 | return -EINVAL; | 223 | return -EINVAL; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0785d04a80bc..9ea17afaa237 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -554,6 +554,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, | |||
554 | NL80211_FEATURE_USERSPACE_MPM | | 554 | NL80211_FEATURE_USERSPACE_MPM | |
555 | NL80211_FEATURE_FULL_AP_CLIENT_STATE; | 555 | NL80211_FEATURE_FULL_AP_CLIENT_STATE; |
556 | wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA); | 556 | wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA); |
557 | wiphy_ext_feature_set(wiphy, | ||
558 | NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211); | ||
557 | 559 | ||
558 | if (!ops->hw_scan) | 560 | if (!ops->hw_scan) |
559 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | | 561 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | |
@@ -930,8 +932,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
930 | IEEE80211_HT_CAP_SM_PS_SHIFT; | 932 | IEEE80211_HT_CAP_SM_PS_SHIFT; |
931 | } | 933 | } |
932 | 934 | ||
933 | /* if low-level driver supports AP, we also support VLAN */ | 935 | /* if low-level driver supports AP, we also support VLAN. |
934 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { | 936 | * drivers advertising SW_CRYPTO_CONTROL should enable AP_VLAN |
937 | * based on their support to transmit SW encrypted packets. | ||
938 | */ | ||
939 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP) && | ||
940 | !ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL)) { | ||
935 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | 941 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); |
936 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); | 942 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); |
937 | } | 943 | } |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6a381cbe1e33..d51da26e9c18 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -880,7 +880,8 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
880 | BSS_CHANGED_BEACON_ENABLED | | 880 | BSS_CHANGED_BEACON_ENABLED | |
881 | BSS_CHANGED_HT | | 881 | BSS_CHANGED_HT | |
882 | BSS_CHANGED_BASIC_RATES | | 882 | BSS_CHANGED_BASIC_RATES | |
883 | BSS_CHANGED_BEACON_INT; | 883 | BSS_CHANGED_BEACON_INT | |
884 | BSS_CHANGED_MCAST_RATE; | ||
884 | 885 | ||
885 | local->fif_other_bss++; | 886 | local->fif_other_bss++; |
886 | /* mesh ifaces must set allmulti to forward mcast traffic */ | 887 | /* mesh ifaces must set allmulti to forward mcast traffic */ |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fe4aefb06d9f..69449db7e283 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1787,12 +1787,14 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1787 | params[ac].acm = acm; | 1787 | params[ac].acm = acm; |
1788 | params[ac].uapsd = uapsd; | 1788 | params[ac].uapsd = uapsd; |
1789 | 1789 | ||
1790 | if (params[ac].cw_min > params[ac].cw_max) { | 1790 | if (params->cw_min == 0 || |
1791 | params[ac].cw_min > params[ac].cw_max) { | ||
1791 | sdata_info(sdata, | 1792 | sdata_info(sdata, |
1792 | "AP has invalid WMM params (CWmin/max=%d/%d for ACI %d), using defaults\n", | 1793 | "AP has invalid WMM params (CWmin/max=%d/%d for ACI %d), using defaults\n", |
1793 | params[ac].cw_min, params[ac].cw_max, aci); | 1794 | params[ac].cw_min, params[ac].cw_max, aci); |
1794 | return false; | 1795 | return false; |
1795 | } | 1796 | } |
1797 | ieee80211_regulatory_limit_wmm_params(sdata, ¶ms[ac], ac); | ||
1796 | } | 1798 | } |
1797 | 1799 | ||
1798 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 1800 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
@@ -2011,8 +2013,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2011 | 2013 | ||
2012 | /* deauthenticate/disassociate now */ | 2014 | /* deauthenticate/disassociate now */ |
2013 | if (tx || frame_buf) { | 2015 | if (tx || frame_buf) { |
2014 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2015 | |||
2016 | /* | 2016 | /* |
2017 | * In multi channel scenarios guarantee that the virtual | 2017 | * In multi channel scenarios guarantee that the virtual |
2018 | * interface is granted immediate airtime to transmit the | 2018 | * interface is granted immediate airtime to transmit the |
@@ -3307,82 +3307,14 @@ static const u64 care_about_ies = | |||
3307 | (1ULL << WLAN_EID_HT_OPERATION) | | 3307 | (1ULL << WLAN_EID_HT_OPERATION) | |
3308 | (1ULL << WLAN_EID_EXT_CHANSWITCH_ANN); | 3308 | (1ULL << WLAN_EID_EXT_CHANSWITCH_ANN); |
3309 | 3309 | ||
3310 | static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | 3310 | static void ieee80211_handle_beacon_sig(struct ieee80211_sub_if_data *sdata, |
3311 | struct ieee80211_mgmt *mgmt, size_t len, | 3311 | struct ieee80211_if_managed *ifmgd, |
3312 | struct ieee80211_rx_status *rx_status) | 3312 | struct ieee80211_bss_conf *bss_conf, |
3313 | struct ieee80211_local *local, | ||
3314 | struct ieee80211_rx_status *rx_status) | ||
3313 | { | 3315 | { |
3314 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3315 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | ||
3316 | size_t baselen; | ||
3317 | struct ieee802_11_elems elems; | ||
3318 | struct ieee80211_local *local = sdata->local; | ||
3319 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3320 | struct ieee80211_channel *chan; | ||
3321 | struct sta_info *sta; | ||
3322 | u32 changed = 0; | ||
3323 | bool erp_valid; | ||
3324 | u8 erp_value = 0; | ||
3325 | u32 ncrc; | ||
3326 | u8 *bssid; | ||
3327 | u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN]; | ||
3328 | |||
3329 | sdata_assert_lock(sdata); | ||
3330 | |||
3331 | /* Process beacon from the current BSS */ | ||
3332 | baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; | ||
3333 | if (baselen > len) | ||
3334 | return; | ||
3335 | |||
3336 | rcu_read_lock(); | ||
3337 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3338 | if (!chanctx_conf) { | ||
3339 | rcu_read_unlock(); | ||
3340 | return; | ||
3341 | } | ||
3342 | |||
3343 | if (rx_status->freq != chanctx_conf->def.chan->center_freq) { | ||
3344 | rcu_read_unlock(); | ||
3345 | return; | ||
3346 | } | ||
3347 | chan = chanctx_conf->def.chan; | ||
3348 | rcu_read_unlock(); | ||
3349 | |||
3350 | if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && | ||
3351 | ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { | ||
3352 | ieee802_11_parse_elems(mgmt->u.beacon.variable, | ||
3353 | len - baselen, false, &elems); | ||
3354 | |||
3355 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); | ||
3356 | if (elems.tim && !elems.parse_error) { | ||
3357 | const struct ieee80211_tim_ie *tim_ie = elems.tim; | ||
3358 | ifmgd->dtim_period = tim_ie->dtim_period; | ||
3359 | } | ||
3360 | ifmgd->have_beacon = true; | ||
3361 | ifmgd->assoc_data->need_beacon = false; | ||
3362 | if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) { | ||
3363 | sdata->vif.bss_conf.sync_tsf = | ||
3364 | le64_to_cpu(mgmt->u.beacon.timestamp); | ||
3365 | sdata->vif.bss_conf.sync_device_ts = | ||
3366 | rx_status->device_timestamp; | ||
3367 | if (elems.tim) | ||
3368 | sdata->vif.bss_conf.sync_dtim_count = | ||
3369 | elems.tim->dtim_count; | ||
3370 | else | ||
3371 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
3372 | } | ||
3373 | /* continue assoc process */ | ||
3374 | ifmgd->assoc_data->timeout = jiffies; | ||
3375 | ifmgd->assoc_data->timeout_started = true; | ||
3376 | run_again(sdata, ifmgd->assoc_data->timeout); | ||
3377 | return; | ||
3378 | } | ||
3379 | |||
3380 | if (!ifmgd->associated || | ||
3381 | !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) | ||
3382 | return; | ||
3383 | bssid = ifmgd->associated->bssid; | ||
3384 | |||
3385 | /* Track average RSSI from the Beacon frames of the current AP */ | 3316 | /* Track average RSSI from the Beacon frames of the current AP */ |
3317 | |||
3386 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { | 3318 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { |
3387 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; | 3319 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; |
3388 | ewma_beacon_signal_init(&ifmgd->ave_beacon_signal); | 3320 | ewma_beacon_signal_init(&ifmgd->ave_beacon_signal); |
@@ -3469,6 +3401,86 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3469 | sig, GFP_KERNEL); | 3401 | sig, GFP_KERNEL); |
3470 | } | 3402 | } |
3471 | } | 3403 | } |
3404 | } | ||
3405 | |||
3406 | static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | ||
3407 | struct ieee80211_mgmt *mgmt, size_t len, | ||
3408 | struct ieee80211_rx_status *rx_status) | ||
3409 | { | ||
3410 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3411 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | ||
3412 | size_t baselen; | ||
3413 | struct ieee802_11_elems elems; | ||
3414 | struct ieee80211_local *local = sdata->local; | ||
3415 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3416 | struct ieee80211_channel *chan; | ||
3417 | struct sta_info *sta; | ||
3418 | u32 changed = 0; | ||
3419 | bool erp_valid; | ||
3420 | u8 erp_value = 0; | ||
3421 | u32 ncrc; | ||
3422 | u8 *bssid; | ||
3423 | u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN]; | ||
3424 | |||
3425 | sdata_assert_lock(sdata); | ||
3426 | |||
3427 | /* Process beacon from the current BSS */ | ||
3428 | baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; | ||
3429 | if (baselen > len) | ||
3430 | return; | ||
3431 | |||
3432 | rcu_read_lock(); | ||
3433 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3434 | if (!chanctx_conf) { | ||
3435 | rcu_read_unlock(); | ||
3436 | return; | ||
3437 | } | ||
3438 | |||
3439 | if (rx_status->freq != chanctx_conf->def.chan->center_freq) { | ||
3440 | rcu_read_unlock(); | ||
3441 | return; | ||
3442 | } | ||
3443 | chan = chanctx_conf->def.chan; | ||
3444 | rcu_read_unlock(); | ||
3445 | |||
3446 | if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && | ||
3447 | ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { | ||
3448 | ieee802_11_parse_elems(mgmt->u.beacon.variable, | ||
3449 | len - baselen, false, &elems); | ||
3450 | |||
3451 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); | ||
3452 | if (elems.tim && !elems.parse_error) { | ||
3453 | const struct ieee80211_tim_ie *tim_ie = elems.tim; | ||
3454 | ifmgd->dtim_period = tim_ie->dtim_period; | ||
3455 | } | ||
3456 | ifmgd->have_beacon = true; | ||
3457 | ifmgd->assoc_data->need_beacon = false; | ||
3458 | if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) { | ||
3459 | sdata->vif.bss_conf.sync_tsf = | ||
3460 | le64_to_cpu(mgmt->u.beacon.timestamp); | ||
3461 | sdata->vif.bss_conf.sync_device_ts = | ||
3462 | rx_status->device_timestamp; | ||
3463 | if (elems.tim) | ||
3464 | sdata->vif.bss_conf.sync_dtim_count = | ||
3465 | elems.tim->dtim_count; | ||
3466 | else | ||
3467 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
3468 | } | ||
3469 | /* continue assoc process */ | ||
3470 | ifmgd->assoc_data->timeout = jiffies; | ||
3471 | ifmgd->assoc_data->timeout_started = true; | ||
3472 | run_again(sdata, ifmgd->assoc_data->timeout); | ||
3473 | return; | ||
3474 | } | ||
3475 | |||
3476 | if (!ifmgd->associated || | ||
3477 | !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) | ||
3478 | return; | ||
3479 | bssid = ifmgd->associated->bssid; | ||
3480 | |||
3481 | if (!(rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)) | ||
3482 | ieee80211_handle_beacon_sig(sdata, ifmgd, bss_conf, | ||
3483 | local, rx_status); | ||
3472 | 3484 | ||
3473 | if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) { | 3485 | if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) { |
3474 | mlme_dbg_ratelimited(sdata, | 3486 | mlme_dbg_ratelimited(sdata, |
@@ -4845,6 +4857,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4845 | 4857 | ||
4846 | sdata->control_port_protocol = req->crypto.control_port_ethertype; | 4858 | sdata->control_port_protocol = req->crypto.control_port_ethertype; |
4847 | sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; | 4859 | sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; |
4860 | sdata->control_port_over_nl80211 = | ||
4861 | req->crypto.control_port_over_nl80211; | ||
4848 | sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto, | 4862 | sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto, |
4849 | sdata->vif.type); | 4863 | sdata->vif.type); |
4850 | 4864 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9c898a3688c6..03102aff0953 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2245,6 +2245,32 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) | |||
2245 | return true; | 2245 | return true; |
2246 | } | 2246 | } |
2247 | 2247 | ||
2248 | static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb, | ||
2249 | struct ieee80211_rx_data *rx) | ||
2250 | { | ||
2251 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
2252 | struct net_device *dev = sdata->dev; | ||
2253 | |||
2254 | if (unlikely((skb->protocol == sdata->control_port_protocol || | ||
2255 | skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) && | ||
2256 | sdata->control_port_over_nl80211)) { | ||
2257 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
2258 | bool noencrypt = status->flag & RX_FLAG_DECRYPTED; | ||
2259 | struct ethhdr *ehdr = eth_hdr(skb); | ||
2260 | |||
2261 | cfg80211_rx_control_port(dev, skb->data, skb->len, | ||
2262 | ehdr->h_source, | ||
2263 | be16_to_cpu(skb->protocol), noencrypt); | ||
2264 | dev_kfree_skb(skb); | ||
2265 | } else { | ||
2266 | /* deliver to local stack */ | ||
2267 | if (rx->napi) | ||
2268 | napi_gro_receive(rx->napi, skb); | ||
2269 | else | ||
2270 | netif_receive_skb(skb); | ||
2271 | } | ||
2272 | } | ||
2273 | |||
2248 | /* | 2274 | /* |
2249 | * requires that rx->skb is a frame with ethernet header | 2275 | * requires that rx->skb is a frame with ethernet header |
2250 | */ | 2276 | */ |
@@ -2329,13 +2355,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
2329 | #endif | 2355 | #endif |
2330 | 2356 | ||
2331 | if (skb) { | 2357 | if (skb) { |
2332 | /* deliver to local stack */ | ||
2333 | skb->protocol = eth_type_trans(skb, dev); | 2358 | skb->protocol = eth_type_trans(skb, dev); |
2334 | memset(skb->cb, 0, sizeof(skb->cb)); | 2359 | memset(skb->cb, 0, sizeof(skb->cb)); |
2335 | if (rx->napi) | 2360 | |
2336 | napi_gro_receive(rx->napi, skb); | 2361 | ieee80211_deliver_skb_to_local_stack(skb, rx); |
2337 | else | ||
2338 | netif_receive_skb(skb); | ||
2339 | } | 2362 | } |
2340 | 2363 | ||
2341 | if (xmit_skb) { | 2364 | if (xmit_skb) { |
@@ -2804,7 +2827,8 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | |||
2804 | !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { | 2827 | !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { |
2805 | int sig = 0; | 2828 | int sig = 0; |
2806 | 2829 | ||
2807 | if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM)) | 2830 | if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM) && |
2831 | !(status->flag & RX_FLAG_NO_SIGNAL_VAL)) | ||
2808 | sig = status->signal; | 2832 | sig = status->signal; |
2809 | 2833 | ||
2810 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, | 2834 | cfg80211_report_obss_beacon(rx->local->hw.wiphy, |
@@ -2882,7 +2906,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2882 | if (rx->sta->sta.smps_mode == smps_mode) | 2906 | if (rx->sta->sta.smps_mode == smps_mode) |
2883 | goto handled; | 2907 | goto handled; |
2884 | rx->sta->sta.smps_mode = smps_mode; | 2908 | rx->sta->sta.smps_mode = smps_mode; |
2885 | sta_opmode.smps_mode = smps_mode; | 2909 | sta_opmode.smps_mode = |
2910 | ieee80211_smps_mode_to_smps_mode(smps_mode); | ||
2886 | sta_opmode.changed = STA_OPMODE_SMPS_MODE_CHANGED; | 2911 | sta_opmode.changed = STA_OPMODE_SMPS_MODE_CHANGED; |
2887 | 2912 | ||
2888 | sband = rx->local->hw.wiphy->bands[status->band]; | 2913 | sband = rx->local->hw.wiphy->bands[status->band]; |
@@ -2920,7 +2945,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2920 | 2945 | ||
2921 | rx->sta->sta.bandwidth = new_bw; | 2946 | rx->sta->sta.bandwidth = new_bw; |
2922 | sband = rx->local->hw.wiphy->bands[status->band]; | 2947 | sband = rx->local->hw.wiphy->bands[status->band]; |
2923 | sta_opmode.bw = new_bw; | 2948 | sta_opmode.bw = |
2949 | ieee80211_sta_rx_bw_to_chan_width(rx->sta); | ||
2924 | sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; | 2950 | sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; |
2925 | 2951 | ||
2926 | rate_control_rate_update(local, sband, rx->sta, | 2952 | rate_control_rate_update(local, sband, rx->sta, |
@@ -3145,7 +3171,8 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) | |||
3145 | * it transmitted were processed or returned. | 3171 | * it transmitted were processed or returned. |
3146 | */ | 3172 | */ |
3147 | 3173 | ||
3148 | if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM)) | 3174 | if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM) && |
3175 | !(status->flag & RX_FLAG_NO_SIGNAL_VAL)) | ||
3149 | sig = status->signal; | 3176 | sig = status->signal; |
3150 | 3177 | ||
3151 | if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig, | 3178 | if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig, |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index ef2becaade50..a3b1bcc2b461 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -73,7 +73,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
73 | bool signal_valid; | 73 | bool signal_valid; |
74 | struct ieee80211_sub_if_data *scan_sdata; | 74 | struct ieee80211_sub_if_data *scan_sdata; |
75 | 75 | ||
76 | if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) | 76 | if (rx_status->flag & RX_FLAG_NO_SIGNAL_VAL) |
77 | bss_meta.signal = 0; /* invalid signal indication */ | ||
78 | else if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) | ||
77 | bss_meta.signal = rx_status->signal * 100; | 79 | bss_meta.signal = rx_status->signal * 100; |
78 | else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC)) | 80 | else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC)) |
79 | bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal; | 81 | bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 933c67b5f845..535de3161a78 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -4757,3 +4757,49 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, | |||
4757 | ieee80211_xmit(sdata, NULL, skb); | 4757 | ieee80211_xmit(sdata, NULL, skb); |
4758 | local_bh_enable(); | 4758 | local_bh_enable(); |
4759 | } | 4759 | } |
4760 | |||
4761 | int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, | ||
4762 | const u8 *buf, size_t len, | ||
4763 | const u8 *dest, __be16 proto, bool unencrypted) | ||
4764 | { | ||
4765 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4766 | struct ieee80211_local *local = sdata->local; | ||
4767 | struct sk_buff *skb; | ||
4768 | struct ethhdr *ehdr; | ||
4769 | u32 flags; | ||
4770 | |||
4771 | /* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE | ||
4772 | * or Pre-Authentication | ||
4773 | */ | ||
4774 | if (proto != sdata->control_port_protocol && | ||
4775 | proto != cpu_to_be16(ETH_P_PREAUTH)) | ||
4776 | return -EINVAL; | ||
4777 | |||
4778 | if (unencrypted) | ||
4779 | flags = IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
4780 | else | ||
4781 | flags = 0; | ||
4782 | |||
4783 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
4784 | sizeof(struct ethhdr) + len); | ||
4785 | if (!skb) | ||
4786 | return -ENOMEM; | ||
4787 | |||
4788 | skb_reserve(skb, local->hw.extra_tx_headroom + sizeof(struct ethhdr)); | ||
4789 | |||
4790 | skb_put_data(skb, buf, len); | ||
4791 | |||
4792 | ehdr = skb_push(skb, sizeof(struct ethhdr)); | ||
4793 | memcpy(ehdr->h_dest, dest, ETH_ALEN); | ||
4794 | memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN); | ||
4795 | ehdr->h_proto = proto; | ||
4796 | |||
4797 | skb->dev = dev; | ||
4798 | skb->protocol = htons(ETH_P_802_3); | ||
4799 | skb_reset_network_header(skb); | ||
4800 | skb_reset_mac_header(skb); | ||
4801 | |||
4802 | __ieee80211_subif_start_xmit(skb, skb->dev, flags); | ||
4803 | |||
4804 | return 0; | ||
4805 | } | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1f82191ce601..11f9cfc016d9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> |
6 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 6 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
7 | * Copyright (C) 2015-2017 Intel Deutschland GmbH | 7 | * Copyright (C) 2015-2017 Intel Deutschland GmbH |
8 | * Copyright (C) 2018 Intel Corporation | ||
8 | * | 9 | * |
9 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
@@ -1113,6 +1114,48 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | |||
1113 | return crc; | 1114 | return crc; |
1114 | } | 1115 | } |
1115 | 1116 | ||
1117 | void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata, | ||
1118 | struct ieee80211_tx_queue_params | ||
1119 | *qparam, int ac) | ||
1120 | { | ||
1121 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
1122 | const struct ieee80211_reg_rule *rrule; | ||
1123 | struct ieee80211_wmm_ac *wmm_ac; | ||
1124 | u16 center_freq = 0; | ||
1125 | |||
1126 | if (sdata->vif.type != NL80211_IFTYPE_AP && | ||
1127 | sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1128 | return; | ||
1129 | |||
1130 | rcu_read_lock(); | ||
1131 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1132 | if (chanctx_conf) | ||
1133 | center_freq = chanctx_conf->def.chan->center_freq; | ||
1134 | |||
1135 | if (!center_freq) { | ||
1136 | rcu_read_unlock(); | ||
1137 | return; | ||
1138 | } | ||
1139 | |||
1140 | rrule = freq_reg_info(sdata->wdev.wiphy, MHZ_TO_KHZ(center_freq)); | ||
1141 | |||
1142 | if (IS_ERR_OR_NULL(rrule) || !rrule->wmm_rule) { | ||
1143 | rcu_read_unlock(); | ||
1144 | return; | ||
1145 | } | ||
1146 | |||
1147 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
1148 | wmm_ac = &rrule->wmm_rule->ap[ac]; | ||
1149 | else | ||
1150 | wmm_ac = &rrule->wmm_rule->client[ac]; | ||
1151 | qparam->cw_min = max_t(u16, qparam->cw_min, wmm_ac->cw_min); | ||
1152 | qparam->cw_max = max_t(u16, qparam->cw_max, wmm_ac->cw_max); | ||
1153 | qparam->aifs = max_t(u8, qparam->aifs, wmm_ac->aifsn); | ||
1154 | qparam->txop = !qparam->txop ? wmm_ac->cot / 32 : | ||
1155 | min_t(u16, qparam->txop, wmm_ac->cot / 32); | ||
1156 | rcu_read_unlock(); | ||
1157 | } | ||
1158 | |||
1116 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | 1159 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, |
1117 | bool bss_notify, bool enable_qos) | 1160 | bool bss_notify, bool enable_qos) |
1118 | { | 1161 | { |
@@ -1206,6 +1249,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
1206 | break; | 1249 | break; |
1207 | } | 1250 | } |
1208 | } | 1251 | } |
1252 | ieee80211_regulatory_limit_wmm_params(sdata, &qparam, ac); | ||
1209 | 1253 | ||
1210 | qparam.uapsd = false; | 1254 | qparam.uapsd = false; |
1211 | 1255 | ||
@@ -1968,7 +2012,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1968 | BSS_CHANGED_CQM | | 2012 | BSS_CHANGED_CQM | |
1969 | BSS_CHANGED_QOS | | 2013 | BSS_CHANGED_QOS | |
1970 | BSS_CHANGED_IDLE | | 2014 | BSS_CHANGED_IDLE | |
1971 | BSS_CHANGED_TXPOWER; | 2015 | BSS_CHANGED_TXPOWER | |
2016 | BSS_CHANGED_MCAST_RATE; | ||
1972 | 2017 | ||
1973 | if (sdata->vif.mu_mimo_owner) | 2018 | if (sdata->vif.mu_mimo_owner) |
1974 | changed |= BSS_CHANGED_MU_GROUPS; | 2019 | changed |= BSS_CHANGED_MU_GROUPS; |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index 5714dee76b12..259325cbcc31 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -358,6 +358,36 @@ enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta) | |||
358 | return NL80211_CHAN_WIDTH_80; | 358 | return NL80211_CHAN_WIDTH_80; |
359 | } | 359 | } |
360 | 360 | ||
361 | enum nl80211_chan_width | ||
362 | ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta) | ||
363 | { | ||
364 | enum ieee80211_sta_rx_bandwidth cur_bw = sta->sta.bandwidth; | ||
365 | struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; | ||
366 | u32 cap_width; | ||
367 | |||
368 | switch (cur_bw) { | ||
369 | case IEEE80211_STA_RX_BW_20: | ||
370 | if (!sta->sta.ht_cap.ht_supported) | ||
371 | return NL80211_CHAN_WIDTH_20_NOHT; | ||
372 | else | ||
373 | return NL80211_CHAN_WIDTH_20; | ||
374 | case IEEE80211_STA_RX_BW_40: | ||
375 | return NL80211_CHAN_WIDTH_40; | ||
376 | case IEEE80211_STA_RX_BW_80: | ||
377 | return NL80211_CHAN_WIDTH_80; | ||
378 | case IEEE80211_STA_RX_BW_160: | ||
379 | cap_width = | ||
380 | vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; | ||
381 | |||
382 | if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ) | ||
383 | return NL80211_CHAN_WIDTH_160; | ||
384 | |||
385 | return NL80211_CHAN_WIDTH_80P80; | ||
386 | default: | ||
387 | return NL80211_CHAN_WIDTH_20; | ||
388 | } | ||
389 | } | ||
390 | |||
361 | enum ieee80211_sta_rx_bandwidth | 391 | enum ieee80211_sta_rx_bandwidth |
362 | ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width) | 392 | ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width) |
363 | { | 393 | { |
@@ -484,7 +514,7 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
484 | new_bw = ieee80211_sta_cur_vht_bw(sta); | 514 | new_bw = ieee80211_sta_cur_vht_bw(sta); |
485 | if (new_bw != sta->sta.bandwidth) { | 515 | if (new_bw != sta->sta.bandwidth) { |
486 | sta->sta.bandwidth = new_bw; | 516 | sta->sta.bandwidth = new_bw; |
487 | sta_opmode.bw = new_bw; | 517 | sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta); |
488 | changed |= IEEE80211_RC_BW_CHANGED; | 518 | changed |= IEEE80211_RC_BW_CHANGED; |
489 | sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED; | 519 | sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED; |
490 | } | 520 | } |
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 63682176c96c..882d97bdc6bf 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
@@ -27,6 +27,7 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
27 | 27 | ||
28 | err = rdev_stop_ap(rdev, dev); | 28 | err = rdev_stop_ap(rdev, dev); |
29 | if (!err) { | 29 | if (!err) { |
30 | wdev->conn_owner_nlportid = 0; | ||
30 | wdev->beacon_interval = 0; | 31 | wdev->beacon_interval = 0; |
31 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); | 32 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); |
32 | wdev->ssid_len = 0; | 33 | wdev->ssid_len = 0; |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index a48859982a32..2db713d18f71 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -579,6 +579,10 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, | |||
579 | { | 579 | { |
580 | struct ieee80211_channel *c; | 580 | struct ieee80211_channel *c; |
581 | u32 freq, start_freq, end_freq; | 581 | u32 freq, start_freq, end_freq; |
582 | bool dfs_offload; | ||
583 | |||
584 | dfs_offload = wiphy_ext_feature_isset(wiphy, | ||
585 | NL80211_EXT_FEATURE_DFS_OFFLOAD); | ||
582 | 586 | ||
583 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); | 587 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); |
584 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); | 588 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); |
@@ -596,8 +600,9 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, | |||
596 | if (c->flags & IEEE80211_CHAN_DISABLED) | 600 | if (c->flags & IEEE80211_CHAN_DISABLED) |
597 | return false; | 601 | return false; |
598 | 602 | ||
599 | if ((c->flags & IEEE80211_CHAN_RADAR) && | 603 | if ((c->flags & IEEE80211_CHAN_RADAR) && |
600 | (c->dfs_state != NL80211_DFS_AVAILABLE)) | 604 | (c->dfs_state != NL80211_DFS_AVAILABLE) && |
605 | !(c->dfs_state == NL80211_DFS_USABLE && dfs_offload)) | ||
601 | return false; | 606 | return false; |
602 | } | 607 | } |
603 | 608 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index eaff636169c2..63eb1b5fdd04 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -282,10 +282,10 @@ void cfg80211_bss_age(struct cfg80211_registered_device *rdev, | |||
282 | unsigned long age_secs); | 282 | unsigned long age_secs); |
283 | 283 | ||
284 | /* IBSS */ | 284 | /* IBSS */ |
285 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 285 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
286 | struct net_device *dev, | 286 | struct net_device *dev, |
287 | struct cfg80211_ibss_params *params, | 287 | struct cfg80211_ibss_params *params, |
288 | struct cfg80211_cached_keys *connkeys); | 288 | struct cfg80211_cached_keys *connkeys); |
289 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); | 289 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); |
290 | int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 290 | int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, |
291 | struct net_device *dev, bool nowext); | 291 | struct net_device *dev, bool nowext); |
@@ -303,10 +303,6 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
303 | struct net_device *dev, | 303 | struct net_device *dev, |
304 | struct mesh_setup *setup, | 304 | struct mesh_setup *setup, |
305 | const struct mesh_config *conf); | 305 | const struct mesh_config *conf); |
306 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | ||
307 | struct net_device *dev, | ||
308 | struct mesh_setup *setup, | ||
309 | const struct mesh_config *conf); | ||
310 | int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 306 | int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
311 | struct net_device *dev); | 307 | struct net_device *dev); |
312 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 308 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index a1d10993d08a..d1743e6abc34 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -84,14 +84,15 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, | |||
84 | } | 84 | } |
85 | EXPORT_SYMBOL(cfg80211_ibss_joined); | 85 | EXPORT_SYMBOL(cfg80211_ibss_joined); |
86 | 86 | ||
87 | static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 87 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
88 | struct net_device *dev, | 88 | struct net_device *dev, |
89 | struct cfg80211_ibss_params *params, | 89 | struct cfg80211_ibss_params *params, |
90 | struct cfg80211_cached_keys *connkeys) | 90 | struct cfg80211_cached_keys *connkeys) |
91 | { | 91 | { |
92 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 92 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
93 | int err; | 93 | int err; |
94 | 94 | ||
95 | ASSERT_RTNL(); | ||
95 | ASSERT_WDEV_LOCK(wdev); | 96 | ASSERT_WDEV_LOCK(wdev); |
96 | 97 | ||
97 | if (wdev->ssid_len) | 98 | if (wdev->ssid_len) |
@@ -146,23 +147,6 @@ static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
146 | return 0; | 147 | return 0; |
147 | } | 148 | } |
148 | 149 | ||
149 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | ||
150 | struct net_device *dev, | ||
151 | struct cfg80211_ibss_params *params, | ||
152 | struct cfg80211_cached_keys *connkeys) | ||
153 | { | ||
154 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
155 | int err; | ||
156 | |||
157 | ASSERT_RTNL(); | ||
158 | |||
159 | wdev_lock(wdev); | ||
160 | err = __cfg80211_join_ibss(rdev, dev, params, connkeys); | ||
161 | wdev_unlock(wdev); | ||
162 | |||
163 | return err; | ||
164 | } | ||
165 | |||
166 | static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | 150 | static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) |
167 | { | 151 | { |
168 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 152 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -224,6 +208,7 @@ int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | |||
224 | if (err) | 208 | if (err) |
225 | return err; | 209 | return err; |
226 | 210 | ||
211 | wdev->conn_owner_nlportid = 0; | ||
227 | __cfg80211_clear_ibss(dev, nowext); | 212 | __cfg80211_clear_ibss(dev, nowext); |
228 | 213 | ||
229 | return 0; | 214 | return 0; |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index b12da6ef3c12..eac5aa1419fc 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -217,21 +217,6 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
217 | return err; | 217 | return err; |
218 | } | 218 | } |
219 | 219 | ||
220 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | ||
221 | struct net_device *dev, | ||
222 | struct mesh_setup *setup, | ||
223 | const struct mesh_config *conf) | ||
224 | { | ||
225 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
226 | int err; | ||
227 | |||
228 | wdev_lock(wdev); | ||
229 | err = __cfg80211_join_mesh(rdev, dev, setup, conf); | ||
230 | wdev_unlock(wdev); | ||
231 | |||
232 | return err; | ||
233 | } | ||
234 | |||
235 | int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | 220 | int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, |
236 | struct wireless_dev *wdev, | 221 | struct wireless_dev *wdev, |
237 | struct cfg80211_chan_def *chandef) | 222 | struct cfg80211_chan_def *chandef) |
@@ -286,6 +271,7 @@ int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | |||
286 | 271 | ||
287 | err = rdev_leave_mesh(rdev, dev); | 272 | err = rdev_leave_mesh(rdev, dev); |
288 | if (!err) { | 273 | if (!err) { |
274 | wdev->conn_owner_nlportid = 0; | ||
289 | wdev->mesh_id_len = 0; | 275 | wdev->mesh_id_len = 0; |
290 | wdev->beacon_interval = 0; | 276 | wdev->beacon_interval = 0; |
291 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); | 277 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index bbb9907bfa86..12b3edf70a7b 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -872,7 +872,7 @@ void cfg80211_cac_event(struct net_device *netdev, | |||
872 | 872 | ||
873 | trace_cfg80211_cac_event(netdev, event); | 873 | trace_cfg80211_cac_event(netdev, event); |
874 | 874 | ||
875 | if (WARN_ON(!wdev->cac_started)) | 875 | if (WARN_ON(!wdev->cac_started && event != NL80211_RADAR_CAC_STARTED)) |
876 | return; | 876 | return; |
877 | 877 | ||
878 | if (WARN_ON(!wdev->chandef.chan)) | 878 | if (WARN_ON(!wdev->chandef.chan)) |
@@ -888,14 +888,17 @@ void cfg80211_cac_event(struct net_device *netdev, | |||
888 | sizeof(struct cfg80211_chan_def)); | 888 | sizeof(struct cfg80211_chan_def)); |
889 | queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk); | 889 | queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk); |
890 | cfg80211_sched_dfs_chan_update(rdev); | 890 | cfg80211_sched_dfs_chan_update(rdev); |
891 | break; | 891 | /* fall through */ |
892 | case NL80211_RADAR_CAC_ABORTED: | 892 | case NL80211_RADAR_CAC_ABORTED: |
893 | wdev->cac_started = false; | ||
894 | break; | ||
895 | case NL80211_RADAR_CAC_STARTED: | ||
896 | wdev->cac_started = true; | ||
893 | break; | 897 | break; |
894 | default: | 898 | default: |
895 | WARN_ON(1); | 899 | WARN_ON(1); |
896 | return; | 900 | return; |
897 | } | 901 | } |
898 | wdev->cac_started = false; | ||
899 | 902 | ||
900 | nl80211_radar_notify(rdev, chandef, event, netdev, gfp); | 903 | nl80211_radar_notify(rdev, chandef, event, netdev, gfp); |
901 | } | 904 | } |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a910150f8169..ff28f8feeb09 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -287,6 +287,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { | |||
287 | [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG }, | 287 | [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG }, |
288 | [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 }, | 288 | [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 }, |
289 | [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG }, | 289 | [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG }, |
290 | [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG }, | ||
290 | [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, | 291 | [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, |
291 | [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, | 292 | [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, |
292 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, | 293 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, |
@@ -4134,6 +4135,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
4134 | wdev->chandef = params.chandef; | 4135 | wdev->chandef = params.chandef; |
4135 | wdev->ssid_len = params.ssid_len; | 4136 | wdev->ssid_len = params.ssid_len; |
4136 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); | 4137 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); |
4138 | |||
4139 | if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) | ||
4140 | wdev->conn_owner_nlportid = info->snd_portid; | ||
4137 | } | 4141 | } |
4138 | wdev_unlock(wdev); | 4142 | wdev_unlock(wdev); |
4139 | 4143 | ||
@@ -7551,12 +7555,13 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
7551 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 7555 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
7552 | struct net_device *dev = info->user_ptr[1]; | 7556 | struct net_device *dev = info->user_ptr[1]; |
7553 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 7557 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
7558 | struct wiphy *wiphy = wdev->wiphy; | ||
7554 | struct cfg80211_chan_def chandef; | 7559 | struct cfg80211_chan_def chandef; |
7555 | enum nl80211_dfs_regions dfs_region; | 7560 | enum nl80211_dfs_regions dfs_region; |
7556 | unsigned int cac_time_ms; | 7561 | unsigned int cac_time_ms; |
7557 | int err; | 7562 | int err; |
7558 | 7563 | ||
7559 | dfs_region = reg_get_dfs_region(wdev->wiphy); | 7564 | dfs_region = reg_get_dfs_region(wiphy); |
7560 | if (dfs_region == NL80211_DFS_UNSET) | 7565 | if (dfs_region == NL80211_DFS_UNSET) |
7561 | return -EINVAL; | 7566 | return -EINVAL; |
7562 | 7567 | ||
@@ -7570,17 +7575,20 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
7570 | if (wdev->cac_started) | 7575 | if (wdev->cac_started) |
7571 | return -EBUSY; | 7576 | return -EBUSY; |
7572 | 7577 | ||
7573 | err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, | 7578 | err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype); |
7574 | wdev->iftype); | ||
7575 | if (err < 0) | 7579 | if (err < 0) |
7576 | return err; | 7580 | return err; |
7577 | 7581 | ||
7578 | if (err == 0) | 7582 | if (err == 0) |
7579 | return -EINVAL; | 7583 | return -EINVAL; |
7580 | 7584 | ||
7581 | if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef)) | 7585 | if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) |
7582 | return -EINVAL; | 7586 | return -EINVAL; |
7583 | 7587 | ||
7588 | /* CAC start is offloaded to HW and can't be started manually */ | ||
7589 | if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) | ||
7590 | return -EOPNOTSUPP; | ||
7591 | |||
7584 | if (!rdev->ops->start_radar_detection) | 7592 | if (!rdev->ops->start_radar_detection) |
7585 | return -EOPNOTSUPP; | 7593 | return -EOPNOTSUPP; |
7586 | 7594 | ||
@@ -8204,6 +8212,22 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
8204 | return err; | 8212 | return err; |
8205 | } | 8213 | } |
8206 | 8214 | ||
8215 | static int validate_pae_over_nl80211(struct cfg80211_registered_device *rdev, | ||
8216 | struct genl_info *info) | ||
8217 | { | ||
8218 | if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) { | ||
8219 | GENL_SET_ERR_MSG(info, "SOCKET_OWNER not set"); | ||
8220 | return -EINVAL; | ||
8221 | } | ||
8222 | |||
8223 | if (!rdev->ops->tx_control_port || | ||
8224 | !wiphy_ext_feature_isset(&rdev->wiphy, | ||
8225 | NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211)) | ||
8226 | return -EOPNOTSUPP; | ||
8227 | |||
8228 | return 0; | ||
8229 | } | ||
8230 | |||
8207 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | 8231 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, |
8208 | struct genl_info *info, | 8232 | struct genl_info *info, |
8209 | struct cfg80211_crypto_settings *settings, | 8233 | struct cfg80211_crypto_settings *settings, |
@@ -8227,6 +8251,15 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
8227 | } else | 8251 | } else |
8228 | settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE); | 8252 | settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE); |
8229 | 8253 | ||
8254 | if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) { | ||
8255 | int r = validate_pae_over_nl80211(rdev, info); | ||
8256 | |||
8257 | if (r < 0) | ||
8258 | return r; | ||
8259 | |||
8260 | settings->control_port_over_nl80211 = true; | ||
8261 | } | ||
8262 | |||
8230 | if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) { | 8263 | if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) { |
8231 | void *data; | 8264 | void *data; |
8232 | int len, i; | 8265 | int len, i; |
@@ -8672,12 +8705,26 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
8672 | ibss.control_port = | 8705 | ibss.control_port = |
8673 | nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]); | 8706 | nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]); |
8674 | 8707 | ||
8708 | if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) { | ||
8709 | int r = validate_pae_over_nl80211(rdev, info); | ||
8710 | |||
8711 | if (r < 0) | ||
8712 | return r; | ||
8713 | |||
8714 | ibss.control_port_over_nl80211 = true; | ||
8715 | } | ||
8716 | |||
8675 | ibss.userspace_handles_dfs = | 8717 | ibss.userspace_handles_dfs = |
8676 | nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]); | 8718 | nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]); |
8677 | 8719 | ||
8678 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); | 8720 | wdev_lock(dev->ieee80211_ptr); |
8721 | err = __cfg80211_join_ibss(rdev, dev, &ibss, connkeys); | ||
8679 | if (err) | 8722 | if (err) |
8680 | kzfree(connkeys); | 8723 | kzfree(connkeys); |
8724 | else if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) | ||
8725 | dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid; | ||
8726 | wdev_unlock(dev->ieee80211_ptr); | ||
8727 | |||
8681 | return err; | 8728 | return err; |
8682 | } | 8729 | } |
8683 | 8730 | ||
@@ -10083,7 +10130,7 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
10083 | if (err) | 10130 | if (err) |
10084 | return err; | 10131 | return err; |
10085 | } else { | 10132 | } else { |
10086 | /* cfg80211_join_mesh() will sort it out */ | 10133 | /* __cfg80211_join_mesh() will sort it out */ |
10087 | setup.chandef.chan = NULL; | 10134 | setup.chandef.chan = NULL; |
10088 | } | 10135 | } |
10089 | 10136 | ||
@@ -10121,7 +10168,22 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
10121 | setup.userspace_handles_dfs = | 10168 | setup.userspace_handles_dfs = |
10122 | nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]); | 10169 | nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]); |
10123 | 10170 | ||
10124 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | 10171 | if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211]) { |
10172 | int r = validate_pae_over_nl80211(rdev, info); | ||
10173 | |||
10174 | if (r < 0) | ||
10175 | return r; | ||
10176 | |||
10177 | setup.control_port_over_nl80211 = true; | ||
10178 | } | ||
10179 | |||
10180 | wdev_lock(dev->ieee80211_ptr); | ||
10181 | err = __cfg80211_join_mesh(rdev, dev, &setup, &cfg); | ||
10182 | if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) | ||
10183 | dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid; | ||
10184 | wdev_unlock(dev->ieee80211_ptr); | ||
10185 | |||
10186 | return err; | ||
10125 | } | 10187 | } |
10126 | 10188 | ||
10127 | static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) | 10189 | static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) |
@@ -12517,6 +12579,68 @@ static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info) | |||
12517 | return rdev_external_auth(rdev, dev, ¶ms); | 12579 | return rdev_external_auth(rdev, dev, ¶ms); |
12518 | } | 12580 | } |
12519 | 12581 | ||
12582 | static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info) | ||
12583 | { | ||
12584 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
12585 | struct net_device *dev = info->user_ptr[1]; | ||
12586 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
12587 | const u8 *buf; | ||
12588 | size_t len; | ||
12589 | u8 *dest; | ||
12590 | u16 proto; | ||
12591 | bool noencrypt; | ||
12592 | int err; | ||
12593 | |||
12594 | if (!wiphy_ext_feature_isset(&rdev->wiphy, | ||
12595 | NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211)) | ||
12596 | return -EOPNOTSUPP; | ||
12597 | |||
12598 | if (!rdev->ops->tx_control_port) | ||
12599 | return -EOPNOTSUPP; | ||
12600 | |||
12601 | if (!info->attrs[NL80211_ATTR_FRAME] || | ||
12602 | !info->attrs[NL80211_ATTR_MAC] || | ||
12603 | !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) { | ||
12604 | GENL_SET_ERR_MSG(info, "Frame, MAC or ethertype missing"); | ||
12605 | return -EINVAL; | ||
12606 | } | ||
12607 | |||
12608 | wdev_lock(wdev); | ||
12609 | |||
12610 | switch (wdev->iftype) { | ||
12611 | case NL80211_IFTYPE_AP: | ||
12612 | case NL80211_IFTYPE_P2P_GO: | ||
12613 | case NL80211_IFTYPE_MESH_POINT: | ||
12614 | break; | ||
12615 | case NL80211_IFTYPE_ADHOC: | ||
12616 | case NL80211_IFTYPE_STATION: | ||
12617 | case NL80211_IFTYPE_P2P_CLIENT: | ||
12618 | if (wdev->current_bss) | ||
12619 | break; | ||
12620 | err = -ENOTCONN; | ||
12621 | goto out; | ||
12622 | default: | ||
12623 | err = -EOPNOTSUPP; | ||
12624 | goto out; | ||
12625 | } | ||
12626 | |||
12627 | wdev_unlock(wdev); | ||
12628 | |||
12629 | buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); | ||
12630 | len = nla_len(info->attrs[NL80211_ATTR_FRAME]); | ||
12631 | dest = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
12632 | proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]); | ||
12633 | noencrypt = | ||
12634 | nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]); | ||
12635 | |||
12636 | return rdev_tx_control_port(rdev, dev, buf, len, | ||
12637 | dest, cpu_to_be16(proto), noencrypt); | ||
12638 | |||
12639 | out: | ||
12640 | wdev_unlock(wdev); | ||
12641 | return err; | ||
12642 | } | ||
12643 | |||
12520 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 12644 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
12521 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 12645 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
12522 | #define NL80211_FLAG_NEED_RTNL 0x04 | 12646 | #define NL80211_FLAG_NEED_RTNL 0x04 |
@@ -13420,7 +13544,14 @@ static const struct genl_ops nl80211_ops[] = { | |||
13420 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 13544 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
13421 | NL80211_FLAG_NEED_RTNL, | 13545 | NL80211_FLAG_NEED_RTNL, |
13422 | }, | 13546 | }, |
13423 | 13547 | { | |
13548 | .cmd = NL80211_CMD_CONTROL_PORT_FRAME, | ||
13549 | .doit = nl80211_tx_control_port, | ||
13550 | .policy = nl80211_policy, | ||
13551 | .flags = GENL_UNS_ADMIN_PERM, | ||
13552 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
13553 | NL80211_FLAG_NEED_RTNL, | ||
13554 | }, | ||
13424 | }; | 13555 | }; |
13425 | 13556 | ||
13426 | static struct genl_family nl80211_fam __ro_after_init = { | 13557 | static struct genl_family nl80211_fam __ro_after_init = { |
@@ -14535,6 +14666,64 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, | |||
14535 | } | 14666 | } |
14536 | EXPORT_SYMBOL(cfg80211_mgmt_tx_status); | 14667 | EXPORT_SYMBOL(cfg80211_mgmt_tx_status); |
14537 | 14668 | ||
14669 | static int __nl80211_rx_control_port(struct net_device *dev, | ||
14670 | const u8 *buf, size_t len, | ||
14671 | const u8 *addr, u16 proto, | ||
14672 | bool unencrypted, gfp_t gfp) | ||
14673 | { | ||
14674 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
14675 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | ||
14676 | struct sk_buff *msg; | ||
14677 | void *hdr; | ||
14678 | u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid); | ||
14679 | |||
14680 | if (!nlportid) | ||
14681 | return -ENOENT; | ||
14682 | |||
14683 | msg = nlmsg_new(100 + len, gfp); | ||
14684 | if (!msg) | ||
14685 | return -ENOMEM; | ||
14686 | |||
14687 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME); | ||
14688 | if (!hdr) { | ||
14689 | nlmsg_free(msg); | ||
14690 | return -ENOBUFS; | ||
14691 | } | ||
14692 | |||
14693 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
14694 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | ||
14695 | nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), | ||
14696 | NL80211_ATTR_PAD) || | ||
14697 | nla_put(msg, NL80211_ATTR_FRAME, len, buf) || | ||
14698 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || | ||
14699 | nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) || | ||
14700 | (unencrypted && nla_put_flag(msg, | ||
14701 | NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))) | ||
14702 | goto nla_put_failure; | ||
14703 | |||
14704 | genlmsg_end(msg, hdr); | ||
14705 | |||
14706 | return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); | ||
14707 | |||
14708 | nla_put_failure: | ||
14709 | nlmsg_free(msg); | ||
14710 | return -ENOBUFS; | ||
14711 | } | ||
14712 | |||
14713 | bool cfg80211_rx_control_port(struct net_device *dev, | ||
14714 | const u8 *buf, size_t len, | ||
14715 | const u8 *addr, u16 proto, bool unencrypted) | ||
14716 | { | ||
14717 | int ret; | ||
14718 | |||
14719 | trace_cfg80211_rx_control_port(dev, buf, len, addr, proto, unencrypted); | ||
14720 | ret = __nl80211_rx_control_port(dev, buf, len, addr, proto, | ||
14721 | unencrypted, GFP_ATOMIC); | ||
14722 | trace_cfg80211_return_bool(ret == 0); | ||
14723 | return ret == 0; | ||
14724 | } | ||
14725 | EXPORT_SYMBOL(cfg80211_rx_control_port); | ||
14726 | |||
14538 | static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev, | 14727 | static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev, |
14539 | const char *mac, gfp_t gfp) | 14728 | const char *mac, gfp_t gfp) |
14540 | { | 14729 | { |
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 84f23ae015fc..87479a53411b 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -714,6 +714,21 @@ static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
714 | return ret; | 714 | return ret; |
715 | } | 715 | } |
716 | 716 | ||
717 | static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev, | ||
718 | struct net_device *dev, | ||
719 | const void *buf, size_t len, | ||
720 | const u8 *dest, __be16 proto, | ||
721 | const bool noencrypt) | ||
722 | { | ||
723 | int ret; | ||
724 | trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len, | ||
725 | dest, proto, noencrypt); | ||
726 | ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len, | ||
727 | dest, proto, noencrypt); | ||
728 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
729 | return ret; | ||
730 | } | ||
731 | |||
717 | static inline int | 732 | static inline int |
718 | rdev_mgmt_tx_cancel_wait(struct cfg80211_registered_device *rdev, | 733 | rdev_mgmt_tx_cancel_wait(struct cfg80211_registered_device *rdev, |
719 | struct wireless_dev *wdev, u64 cookie) | 734 | struct wireless_dev *wdev, u64 cookie) |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7b42f0bacfd8..16c7e4ef5820 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com> | 5 | * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com> |
6 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 6 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
7 | * Copyright 2017 Intel Deutschland GmbH | 7 | * Copyright 2017 Intel Deutschland GmbH |
8 | * Copyright (C) 2018 Intel Corporation | ||
8 | * | 9 | * |
9 | * Permission to use, copy, modify, and/or distribute this software for any | 10 | * Permission to use, copy, modify, and/or distribute this software for any |
10 | * purpose with or without fee is hereby granted, provided that the above | 11 | * purpose with or without fee is hereby granted, provided that the above |
@@ -134,12 +135,12 @@ static void restore_regulatory_settings(bool reset_user); | |||
134 | 135 | ||
135 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) | 136 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) |
136 | { | 137 | { |
137 | return rtnl_dereference(cfg80211_regdomain); | 138 | return rcu_dereference_rtnl(cfg80211_regdomain); |
138 | } | 139 | } |
139 | 140 | ||
140 | const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) | 141 | const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) |
141 | { | 142 | { |
142 | return rtnl_dereference(wiphy->regd); | 143 | return rcu_dereference_rtnl(wiphy->regd); |
143 | } | 144 | } |
144 | 145 | ||
145 | static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region) | 146 | static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region) |
@@ -424,23 +425,36 @@ static const struct ieee80211_regdomain * | |||
424 | reg_copy_regd(const struct ieee80211_regdomain *src_regd) | 425 | reg_copy_regd(const struct ieee80211_regdomain *src_regd) |
425 | { | 426 | { |
426 | struct ieee80211_regdomain *regd; | 427 | struct ieee80211_regdomain *regd; |
427 | int size_of_regd; | 428 | int size_of_regd, size_of_wmms; |
428 | unsigned int i; | 429 | unsigned int i; |
430 | struct ieee80211_wmm_rule *d_wmm, *s_wmm; | ||
429 | 431 | ||
430 | size_of_regd = | 432 | size_of_regd = |
431 | sizeof(struct ieee80211_regdomain) + | 433 | sizeof(struct ieee80211_regdomain) + |
432 | src_regd->n_reg_rules * sizeof(struct ieee80211_reg_rule); | 434 | src_regd->n_reg_rules * sizeof(struct ieee80211_reg_rule); |
435 | size_of_wmms = src_regd->n_wmm_rules * | ||
436 | sizeof(struct ieee80211_wmm_rule); | ||
433 | 437 | ||
434 | regd = kzalloc(size_of_regd, GFP_KERNEL); | 438 | regd = kzalloc(size_of_regd + size_of_wmms, GFP_KERNEL); |
435 | if (!regd) | 439 | if (!regd) |
436 | return ERR_PTR(-ENOMEM); | 440 | return ERR_PTR(-ENOMEM); |
437 | 441 | ||
438 | memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); | 442 | memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); |
439 | 443 | ||
440 | for (i = 0; i < src_regd->n_reg_rules; i++) | 444 | d_wmm = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd); |
445 | s_wmm = (struct ieee80211_wmm_rule *)((u8 *)src_regd + size_of_regd); | ||
446 | memcpy(d_wmm, s_wmm, size_of_wmms); | ||
447 | |||
448 | for (i = 0; i < src_regd->n_reg_rules; i++) { | ||
441 | memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], | 449 | memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], |
442 | sizeof(struct ieee80211_reg_rule)); | 450 | sizeof(struct ieee80211_reg_rule)); |
451 | if (!src_regd->reg_rules[i].wmm_rule) | ||
452 | continue; | ||
443 | 453 | ||
454 | regd->reg_rules[i].wmm_rule = d_wmm + | ||
455 | (src_regd->reg_rules[i].wmm_rule - s_wmm) / | ||
456 | sizeof(struct ieee80211_wmm_rule); | ||
457 | } | ||
444 | return regd; | 458 | return regd; |
445 | } | 459 | } |
446 | 460 | ||
@@ -595,6 +609,17 @@ enum fwdb_flags { | |||
595 | FWDB_FLAG_AUTO_BW = BIT(4), | 609 | FWDB_FLAG_AUTO_BW = BIT(4), |
596 | }; | 610 | }; |
597 | 611 | ||
612 | struct fwdb_wmm_ac { | ||
613 | u8 ecw; | ||
614 | u8 aifsn; | ||
615 | __be16 cot; | ||
616 | } __packed; | ||
617 | |||
618 | struct fwdb_wmm_rule { | ||
619 | struct fwdb_wmm_ac client[IEEE80211_NUM_ACS]; | ||
620 | struct fwdb_wmm_ac ap[IEEE80211_NUM_ACS]; | ||
621 | } __packed; | ||
622 | |||
598 | struct fwdb_rule { | 623 | struct fwdb_rule { |
599 | u8 len; | 624 | u8 len; |
600 | u8 flags; | 625 | u8 flags; |
@@ -602,6 +627,7 @@ struct fwdb_rule { | |||
602 | __be32 start, end, max_bw; | 627 | __be32 start, end, max_bw; |
603 | /* start of optional data */ | 628 | /* start of optional data */ |
604 | __be16 cac_timeout; | 629 | __be16 cac_timeout; |
630 | __be16 wmm_ptr; | ||
605 | } __packed __aligned(4); | 631 | } __packed __aligned(4); |
606 | 632 | ||
607 | #define FWDB_MAGIC 0x52474442 | 633 | #define FWDB_MAGIC 0x52474442 |
@@ -613,6 +639,31 @@ struct fwdb_header { | |||
613 | struct fwdb_country country[]; | 639 | struct fwdb_country country[]; |
614 | } __packed __aligned(4); | 640 | } __packed __aligned(4); |
615 | 641 | ||
642 | static int ecw2cw(int ecw) | ||
643 | { | ||
644 | return (1 << ecw) - 1; | ||
645 | } | ||
646 | |||
647 | static bool valid_wmm(struct fwdb_wmm_rule *rule) | ||
648 | { | ||
649 | struct fwdb_wmm_ac *ac = (struct fwdb_wmm_ac *)rule; | ||
650 | int i; | ||
651 | |||
652 | for (i = 0; i < IEEE80211_NUM_ACS * 2; i++) { | ||
653 | u16 cw_min = ecw2cw((ac[i].ecw & 0xf0) >> 4); | ||
654 | u16 cw_max = ecw2cw(ac[i].ecw & 0x0f); | ||
655 | u8 aifsn = ac[i].aifsn; | ||
656 | |||
657 | if (cw_min >= cw_max) | ||
658 | return false; | ||
659 | |||
660 | if (aifsn < 1) | ||
661 | return false; | ||
662 | } | ||
663 | |||
664 | return true; | ||
665 | } | ||
666 | |||
616 | static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr) | 667 | static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr) |
617 | { | 668 | { |
618 | struct fwdb_rule *rule = (void *)(data + (rule_ptr << 2)); | 669 | struct fwdb_rule *rule = (void *)(data + (rule_ptr << 2)); |
@@ -623,7 +674,18 @@ static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr) | |||
623 | /* mandatory fields */ | 674 | /* mandatory fields */ |
624 | if (rule->len < offsetofend(struct fwdb_rule, max_bw)) | 675 | if (rule->len < offsetofend(struct fwdb_rule, max_bw)) |
625 | return false; | 676 | return false; |
677 | if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) { | ||
678 | u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2; | ||
679 | struct fwdb_wmm_rule *wmm; | ||
680 | |||
681 | if (wmm_ptr + sizeof(struct fwdb_wmm_rule) > size) | ||
682 | return false; | ||
626 | 683 | ||
684 | wmm = (void *)(data + wmm_ptr); | ||
685 | |||
686 | if (!valid_wmm(wmm)) | ||
687 | return false; | ||
688 | } | ||
627 | return true; | 689 | return true; |
628 | } | 690 | } |
629 | 691 | ||
@@ -798,23 +860,118 @@ static bool valid_regdb(const u8 *data, unsigned int size) | |||
798 | return true; | 860 | return true; |
799 | } | 861 | } |
800 | 862 | ||
863 | static void set_wmm_rule(struct ieee80211_wmm_rule *rule, | ||
864 | struct fwdb_wmm_rule *wmm) | ||
865 | { | ||
866 | unsigned int i; | ||
867 | |||
868 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | ||
869 | rule->client[i].cw_min = | ||
870 | ecw2cw((wmm->client[i].ecw & 0xf0) >> 4); | ||
871 | rule->client[i].cw_max = ecw2cw(wmm->client[i].ecw & 0x0f); | ||
872 | rule->client[i].aifsn = wmm->client[i].aifsn; | ||
873 | rule->client[i].cot = 1000 * be16_to_cpu(wmm->client[i].cot); | ||
874 | rule->ap[i].cw_min = ecw2cw((wmm->ap[i].ecw & 0xf0) >> 4); | ||
875 | rule->ap[i].cw_max = ecw2cw(wmm->ap[i].ecw & 0x0f); | ||
876 | rule->ap[i].aifsn = wmm->ap[i].aifsn; | ||
877 | rule->ap[i].cot = 1000 * be16_to_cpu(wmm->ap[i].cot); | ||
878 | } | ||
879 | } | ||
880 | |||
881 | static int __regdb_query_wmm(const struct fwdb_header *db, | ||
882 | const struct fwdb_country *country, int freq, | ||
883 | u32 *dbptr, struct ieee80211_wmm_rule *rule) | ||
884 | { | ||
885 | unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2; | ||
886 | struct fwdb_collection *coll = (void *)((u8 *)db + ptr); | ||
887 | int i; | ||
888 | |||
889 | for (i = 0; i < coll->n_rules; i++) { | ||
890 | __be16 *rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2)); | ||
891 | unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2; | ||
892 | struct fwdb_rule *rrule = (void *)((u8 *)db + rule_ptr); | ||
893 | struct fwdb_wmm_rule *wmm; | ||
894 | unsigned int wmm_ptr; | ||
895 | |||
896 | if (rrule->len < offsetofend(struct fwdb_rule, wmm_ptr)) | ||
897 | continue; | ||
898 | |||
899 | if (freq >= KHZ_TO_MHZ(be32_to_cpu(rrule->start)) && | ||
900 | freq <= KHZ_TO_MHZ(be32_to_cpu(rrule->end))) { | ||
901 | wmm_ptr = be16_to_cpu(rrule->wmm_ptr) << 2; | ||
902 | wmm = (void *)((u8 *)db + wmm_ptr); | ||
903 | set_wmm_rule(rule, wmm); | ||
904 | if (dbptr) | ||
905 | *dbptr = wmm_ptr; | ||
906 | return 0; | ||
907 | } | ||
908 | } | ||
909 | |||
910 | return -ENODATA; | ||
911 | } | ||
912 | |||
913 | int reg_query_regdb_wmm(char *alpha2, int freq, u32 *dbptr, | ||
914 | struct ieee80211_wmm_rule *rule) | ||
915 | { | ||
916 | const struct fwdb_header *hdr = regdb; | ||
917 | const struct fwdb_country *country; | ||
918 | |||
919 | if (IS_ERR(regdb)) | ||
920 | return PTR_ERR(regdb); | ||
921 | |||
922 | country = &hdr->country[0]; | ||
923 | while (country->coll_ptr) { | ||
924 | if (alpha2_equal(alpha2, country->alpha2)) | ||
925 | return __regdb_query_wmm(regdb, country, freq, dbptr, | ||
926 | rule); | ||
927 | |||
928 | country++; | ||
929 | } | ||
930 | |||
931 | return -ENODATA; | ||
932 | } | ||
933 | EXPORT_SYMBOL(reg_query_regdb_wmm); | ||
934 | |||
935 | struct wmm_ptrs { | ||
936 | struct ieee80211_wmm_rule *rule; | ||
937 | u32 ptr; | ||
938 | }; | ||
939 | |||
940 | static struct ieee80211_wmm_rule *find_wmm_ptr(struct wmm_ptrs *wmm_ptrs, | ||
941 | u32 wmm_ptr, int n_wmms) | ||
942 | { | ||
943 | int i; | ||
944 | |||
945 | for (i = 0; i < n_wmms; i++) { | ||
946 | if (wmm_ptrs[i].ptr == wmm_ptr) | ||
947 | return wmm_ptrs[i].rule; | ||
948 | } | ||
949 | return NULL; | ||
950 | } | ||
951 | |||
801 | static int regdb_query_country(const struct fwdb_header *db, | 952 | static int regdb_query_country(const struct fwdb_header *db, |
802 | const struct fwdb_country *country) | 953 | const struct fwdb_country *country) |
803 | { | 954 | { |
804 | unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2; | 955 | unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2; |
805 | struct fwdb_collection *coll = (void *)((u8 *)db + ptr); | 956 | struct fwdb_collection *coll = (void *)((u8 *)db + ptr); |
806 | struct ieee80211_regdomain *regdom; | 957 | struct ieee80211_regdomain *regdom; |
807 | unsigned int size_of_regd; | 958 | struct ieee80211_regdomain *tmp_rd; |
808 | unsigned int i; | 959 | unsigned int size_of_regd, i, n_wmms = 0; |
960 | struct wmm_ptrs *wmm_ptrs; | ||
809 | 961 | ||
810 | size_of_regd = | 962 | size_of_regd = sizeof(struct ieee80211_regdomain) + |
811 | sizeof(struct ieee80211_regdomain) + | ||
812 | coll->n_rules * sizeof(struct ieee80211_reg_rule); | 963 | coll->n_rules * sizeof(struct ieee80211_reg_rule); |
813 | 964 | ||
814 | regdom = kzalloc(size_of_regd, GFP_KERNEL); | 965 | regdom = kzalloc(size_of_regd, GFP_KERNEL); |
815 | if (!regdom) | 966 | if (!regdom) |
816 | return -ENOMEM; | 967 | return -ENOMEM; |
817 | 968 | ||
969 | wmm_ptrs = kcalloc(coll->n_rules, sizeof(*wmm_ptrs), GFP_KERNEL); | ||
970 | if (!wmm_ptrs) { | ||
971 | kfree(regdom); | ||
972 | return -ENOMEM; | ||
973 | } | ||
974 | |||
818 | regdom->n_reg_rules = coll->n_rules; | 975 | regdom->n_reg_rules = coll->n_rules; |
819 | regdom->alpha2[0] = country->alpha2[0]; | 976 | regdom->alpha2[0] = country->alpha2[0]; |
820 | regdom->alpha2[1] = country->alpha2[1]; | 977 | regdom->alpha2[1] = country->alpha2[1]; |
@@ -851,7 +1008,38 @@ static int regdb_query_country(const struct fwdb_header *db, | |||
851 | if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout)) | 1008 | if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout)) |
852 | rrule->dfs_cac_ms = | 1009 | rrule->dfs_cac_ms = |
853 | 1000 * be16_to_cpu(rule->cac_timeout); | 1010 | 1000 * be16_to_cpu(rule->cac_timeout); |
1011 | if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) { | ||
1012 | u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2; | ||
1013 | struct ieee80211_wmm_rule *wmm_pos = | ||
1014 | find_wmm_ptr(wmm_ptrs, wmm_ptr, n_wmms); | ||
1015 | struct fwdb_wmm_rule *wmm; | ||
1016 | struct ieee80211_wmm_rule *wmm_rule; | ||
1017 | |||
1018 | if (wmm_pos) { | ||
1019 | rrule->wmm_rule = wmm_pos; | ||
1020 | continue; | ||
1021 | } | ||
1022 | wmm = (void *)((u8 *)db + wmm_ptr); | ||
1023 | tmp_rd = krealloc(regdom, size_of_regd + (n_wmms + 1) * | ||
1024 | sizeof(struct ieee80211_wmm_rule), | ||
1025 | GFP_KERNEL); | ||
1026 | |||
1027 | if (!tmp_rd) { | ||
1028 | kfree(regdom); | ||
1029 | return -ENOMEM; | ||
1030 | } | ||
1031 | regdom = tmp_rd; | ||
1032 | |||
1033 | wmm_rule = (struct ieee80211_wmm_rule *) | ||
1034 | ((u8 *)regdom + size_of_regd + n_wmms * | ||
1035 | sizeof(struct ieee80211_wmm_rule)); | ||
1036 | |||
1037 | set_wmm_rule(wmm_rule, wmm); | ||
1038 | wmm_ptrs[n_wmms].ptr = wmm_ptr; | ||
1039 | wmm_ptrs[n_wmms++].rule = wmm_rule; | ||
1040 | } | ||
854 | } | 1041 | } |
1042 | kfree(wmm_ptrs); | ||
855 | 1043 | ||
856 | return reg_schedule_apply(regdom); | 1044 | return reg_schedule_apply(regdom); |
857 | } | 1045 | } |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 701cfd7acc1b..5df6b33db786 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -1239,17 +1239,38 @@ void cfg80211_autodisconnect_wk(struct work_struct *work) | |||
1239 | wdev_lock(wdev); | 1239 | wdev_lock(wdev); |
1240 | 1240 | ||
1241 | if (wdev->conn_owner_nlportid) { | 1241 | if (wdev->conn_owner_nlportid) { |
1242 | /* | 1242 | switch (wdev->iftype) { |
1243 | * Use disconnect_bssid if still connecting and ops->disconnect | 1243 | case NL80211_IFTYPE_ADHOC: |
1244 | * not implemented. Otherwise we can use cfg80211_disconnect. | 1244 | cfg80211_leave_ibss(rdev, wdev->netdev, false); |
1245 | */ | 1245 | break; |
1246 | if (rdev->ops->disconnect || wdev->current_bss) | 1246 | case NL80211_IFTYPE_AP: |
1247 | cfg80211_disconnect(rdev, wdev->netdev, | 1247 | case NL80211_IFTYPE_P2P_GO: |
1248 | WLAN_REASON_DEAUTH_LEAVING, true); | 1248 | cfg80211_stop_ap(rdev, wdev->netdev, false); |
1249 | else | 1249 | break; |
1250 | cfg80211_mlme_deauth(rdev, wdev->netdev, | 1250 | case NL80211_IFTYPE_MESH_POINT: |
1251 | wdev->disconnect_bssid, NULL, 0, | 1251 | cfg80211_leave_mesh(rdev, wdev->netdev); |
1252 | WLAN_REASON_DEAUTH_LEAVING, false); | 1252 | break; |
1253 | case NL80211_IFTYPE_STATION: | ||
1254 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1255 | /* | ||
1256 | * Use disconnect_bssid if still connecting and | ||
1257 | * ops->disconnect not implemented. Otherwise we can | ||
1258 | * use cfg80211_disconnect. | ||
1259 | */ | ||
1260 | if (rdev->ops->disconnect || wdev->current_bss) | ||
1261 | cfg80211_disconnect(rdev, wdev->netdev, | ||
1262 | WLAN_REASON_DEAUTH_LEAVING, | ||
1263 | true); | ||
1264 | else | ||
1265 | cfg80211_mlme_deauth(rdev, wdev->netdev, | ||
1266 | wdev->disconnect_bssid, | ||
1267 | NULL, 0, | ||
1268 | WLAN_REASON_DEAUTH_LEAVING, | ||
1269 | false); | ||
1270 | break; | ||
1271 | default: | ||
1272 | break; | ||
1273 | } | ||
1253 | } | 1274 | } |
1254 | 1275 | ||
1255 | wdev_unlock(wdev); | 1276 | wdev_unlock(wdev); |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 5152938b358d..a64291ae52a6 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -1882,6 +1882,32 @@ TRACE_EVENT(rdev_mgmt_tx, | |||
1882 | BOOL_TO_STR(__entry->dont_wait_for_ack)) | 1882 | BOOL_TO_STR(__entry->dont_wait_for_ack)) |
1883 | ); | 1883 | ); |
1884 | 1884 | ||
1885 | TRACE_EVENT(rdev_tx_control_port, | ||
1886 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
1887 | const u8 *buf, size_t len, const u8 *dest, __be16 proto, | ||
1888 | bool unencrypted), | ||
1889 | TP_ARGS(wiphy, netdev, buf, len, dest, proto, unencrypted), | ||
1890 | TP_STRUCT__entry( | ||
1891 | WIPHY_ENTRY | ||
1892 | NETDEV_ENTRY | ||
1893 | MAC_ENTRY(dest) | ||
1894 | __field(__be16, proto) | ||
1895 | __field(bool, unencrypted) | ||
1896 | ), | ||
1897 | TP_fast_assign( | ||
1898 | WIPHY_ASSIGN; | ||
1899 | NETDEV_ASSIGN; | ||
1900 | MAC_ASSIGN(dest, dest); | ||
1901 | __entry->proto = proto; | ||
1902 | __entry->unencrypted = unencrypted; | ||
1903 | ), | ||
1904 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT "," | ||
1905 | " proto: 0x%x, unencrypted: %s", | ||
1906 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest), | ||
1907 | be16_to_cpu(__entry->proto), | ||
1908 | BOOL_TO_STR(__entry->unencrypted)) | ||
1909 | ); | ||
1910 | |||
1885 | TRACE_EVENT(rdev_set_noack_map, | 1911 | TRACE_EVENT(rdev_set_noack_map, |
1886 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | 1912 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, |
1887 | u16 noack_map), | 1913 | u16 noack_map), |
@@ -2600,6 +2626,27 @@ TRACE_EVENT(cfg80211_mgmt_tx_status, | |||
2600 | WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack)) | 2626 | WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack)) |
2601 | ); | 2627 | ); |
2602 | 2628 | ||
2629 | TRACE_EVENT(cfg80211_rx_control_port, | ||
2630 | TP_PROTO(struct net_device *netdev, const u8 *buf, size_t len, | ||
2631 | const u8 *addr, u16 proto, bool unencrypted), | ||
2632 | TP_ARGS(netdev, buf, len, addr, proto, unencrypted), | ||
2633 | TP_STRUCT__entry( | ||
2634 | NETDEV_ENTRY | ||
2635 | MAC_ENTRY(addr) | ||
2636 | __field(u16, proto) | ||
2637 | __field(bool, unencrypted) | ||
2638 | ), | ||
2639 | TP_fast_assign( | ||
2640 | NETDEV_ASSIGN; | ||
2641 | MAC_ASSIGN(addr, addr); | ||
2642 | __entry->proto = proto; | ||
2643 | __entry->unencrypted = unencrypted; | ||
2644 | ), | ||
2645 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT " proto: 0x%x, unencrypted: %s", | ||
2646 | NETDEV_PR_ARG, MAC_PR_ARG(addr), | ||
2647 | __entry->proto, BOOL_TO_STR(__entry->unencrypted)) | ||
2648 | ); | ||
2649 | |||
2603 | TRACE_EVENT(cfg80211_cqm_rssi_notify, | 2650 | TRACE_EVENT(cfg80211_cqm_rssi_notify, |
2604 | TP_PROTO(struct net_device *netdev, | 2651 | TP_PROTO(struct net_device *netdev, |
2605 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 2652 | enum nl80211_cqm_rssi_threshold_event rssi_event, |