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 /net/mac80211 | |
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>
Diffstat (limited to 'net/mac80211')
-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 |
14 files changed, 311 insertions, 96 deletions
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 | } |