aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-12-06 14:58:41 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-12-06 14:58:41 -0500
commit403e16731ffddc097eae89f53f9a7b0f0c9769c4 (patch)
tree228d17985ad8ea22a7763457bf9641eb44781568
parent55cb0797fa779e36f62876a8aa44cbf3984e8d59 (diff)
parentda29d2a5780d80857773d7776b7603a449b0b6e0 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Conflicts: drivers/net/wireless/mwifiex/sta_ioctl.c net/mac80211/scan.c
-rw-r--r--drivers/net/wireless/libertas/cfg.c9
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c7
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c33
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c4
-rw-r--r--include/linux/ieee80211.h15
-rw-r--r--include/net/cfg80211.h69
-rw-r--r--include/net/ieee80211_radiotap.h24
-rw-r--r--include/net/mac80211.h12
-rw-r--r--include/uapi/linux/nl80211.h16
-rw-r--r--net/mac80211/cfg.c77
-rw-r--r--net/mac80211/debugfs_sta.c36
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/iface.c45
-rw-r--r--net/mac80211/main.c5
-rw-r--r--net/mac80211/mesh_plink.c3
-rw-r--r--net/mac80211/mesh_sync.c4
-rw-r--r--net/mac80211/mlme.c431
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c8
-rw-r--r--net/mac80211/rx.c42
-rw-r--r--net/mac80211/scan.c21
-rw-r--r--net/mac80211/sta_info.h4
-rw-r--r--net/mac80211/status.c3
-rw-r--r--net/mac80211/tx.c9
-rw-r--r--net/mac80211/util.c58
-rw-r--r--net/wireless/chan.c92
-rw-r--r--net/wireless/core.h8
-rw-r--r--net/wireless/mesh.c3
-rw-r--r--net/wireless/nl80211.c155
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/reg.h2
-rw-r--r--net/wireless/scan.c452
-rw-r--r--net/wireless/sme.c13
-rw-r--r--net/wireless/util.c9
-rw-r--r--net/wireless/wext-sme.c8
35 files changed, 1138 insertions, 550 deletions
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index ec36868f6fc..ec6d5d6b452 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -298,6 +298,7 @@ static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss)
298 const u8 *rates_eid, *ext_rates_eid; 298 const u8 *rates_eid, *ext_rates_eid;
299 int n = 0; 299 int n = 0;
300 300
301 rcu_read_lock();
301 rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); 302 rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
302 ext_rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES); 303 ext_rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
303 304
@@ -325,6 +326,7 @@ static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss)
325 *tlv++ = 0x96; 326 *tlv++ = 0x96;
326 n = 4; 327 n = 4;
327 } 328 }
329 rcu_read_unlock();
328 330
329 rate_tlv->header.len = cpu_to_le16(n); 331 rate_tlv->header.len = cpu_to_le16(n);
330 return sizeof(rate_tlv->header) + n; 332 return sizeof(rate_tlv->header) + n;
@@ -1140,11 +1142,13 @@ static int lbs_associate(struct lbs_private *priv,
1140 cmd->capability = cpu_to_le16(bss->capability); 1142 cmd->capability = cpu_to_le16(bss->capability);
1141 1143
1142 /* add SSID TLV */ 1144 /* add SSID TLV */
1145 rcu_read_lock();
1143 ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); 1146 ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
1144 if (ssid_eid) 1147 if (ssid_eid)
1145 pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]); 1148 pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]);
1146 else 1149 else
1147 lbs_deb_assoc("no SSID\n"); 1150 lbs_deb_assoc("no SSID\n");
1151 rcu_read_unlock();
1148 1152
1149 /* add DS param TLV */ 1153 /* add DS param TLV */
1150 if (bss->channel) 1154 if (bss->channel)
@@ -1782,7 +1786,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
1782 struct cfg80211_ibss_params *params, 1786 struct cfg80211_ibss_params *params,
1783 struct cfg80211_bss *bss) 1787 struct cfg80211_bss *bss)
1784{ 1788{
1785 const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); 1789 const u8 *rates_eid;
1786 struct cmd_ds_802_11_ad_hoc_join cmd; 1790 struct cmd_ds_802_11_ad_hoc_join cmd;
1787 u8 preamble = RADIO_PREAMBLE_SHORT; 1791 u8 preamble = RADIO_PREAMBLE_SHORT;
1788 int ret = 0; 1792 int ret = 0;
@@ -1841,6 +1845,8 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
1841 1845
1842 /* set rates to the intersection of our rates and the rates in the 1846 /* set rates to the intersection of our rates and the rates in the
1843 bss */ 1847 bss */
1848 rcu_read_lock();
1849 rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
1844 if (!rates_eid) { 1850 if (!rates_eid) {
1845 lbs_add_rates(cmd.bss.rates); 1851 lbs_add_rates(cmd.bss.rates);
1846 } else { 1852 } else {
@@ -1860,6 +1866,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
1860 } 1866 }
1861 } 1867 }
1862 } 1868 }
1869 rcu_read_unlock();
1863 1870
1864 /* Only v8 and below support setting this */ 1871 /* Only v8 and below support setting this */
1865 if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) { 1872 if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) {
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 2aa8a1aa118..8a61dbd320e 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1347,9 +1347,14 @@ static void hw_scan_work(struct work_struct *work)
1347 hwsim->hw_scan_vif, 1347 hwsim->hw_scan_vif,
1348 req->ssids[i].ssid, 1348 req->ssids[i].ssid,
1349 req->ssids[i].ssid_len, 1349 req->ssids[i].ssid_len,
1350 req->ie, req->ie_len); 1350 req->ie_len);
1351 if (!probe) 1351 if (!probe)
1352 continue; 1352 continue;
1353
1354 if (req->ie_len)
1355 memcpy(skb_put(probe, req->ie_len), req->ie,
1356 req->ie_len);
1357
1353 local_bh_disable(); 1358 local_bh_disable();
1354 mac80211_hwsim_tx_frame(hwsim->hw, probe, 1359 mac80211_hwsim_tx_frame(hwsim->hw, probe,
1355 hwsim->tmp_chan); 1360 hwsim->tmp_chan);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 95e3ab531c9..cb682561c43 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -160,11 +160,21 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
160{ 160{
161 int ret; 161 int ret;
162 u8 *beacon_ie; 162 u8 *beacon_ie;
163 size_t beacon_ie_len;
163 struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; 164 struct mwifiex_bss_priv *bss_priv = (void *)bss->priv;
164 size_t beacon_ie_len = bss->len_information_elements; 165 const struct cfg80211_bss_ies *ies;
166
167 rcu_read_lock();
168 ies = rcu_dereference(bss->ies);
169 if (WARN_ON(!ies)) {
170 /* should never happen */
171 rcu_read_unlock();
172 return -EINVAL;
173 }
174 beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC);
175 beacon_ie_len = ies->len;
176 rcu_read_unlock();
165 177
166 beacon_ie = kmemdup(bss->information_elements, beacon_ie_len,
167 GFP_KERNEL);
168 if (!beacon_ie) { 178 if (!beacon_ie) {
169 dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); 179 dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
170 return -ENOMEM; 180 return -ENOMEM;
@@ -199,18 +209,23 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
199static int mwifiex_process_country_ie(struct mwifiex_private *priv, 209static int mwifiex_process_country_ie(struct mwifiex_private *priv,
200 struct cfg80211_bss *bss) 210 struct cfg80211_bss *bss)
201{ 211{
202 u8 *country_ie, country_ie_len; 212 const u8 *country_ie;
213 u8 country_ie_len;
203 struct mwifiex_802_11d_domain_reg *domain_info = 214 struct mwifiex_802_11d_domain_reg *domain_info =
204 &priv->adapter->domain_reg; 215 &priv->adapter->domain_reg;
205 216
206 country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); 217 rcu_read_lock();
207 218 country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
208 if (!country_ie) 219 if (!country_ie) {
220 rcu_read_unlock();
209 return 0; 221 return 0;
222 }
210 223
211 country_ie_len = country_ie[1]; 224 country_ie_len = country_ie[1];
212 if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) 225 if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) {
226 rcu_read_unlock();
213 return 0; 227 return 0;
228 }
214 229
215 domain_info->country_code[0] = country_ie[2]; 230 domain_info->country_code[0] = country_ie[2];
216 domain_info->country_code[1] = country_ie[3]; 231 domain_info->country_code[1] = country_ie[3];
@@ -224,6 +239,8 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
224 memcpy((u8 *)domain_info->triplet, 239 memcpy((u8 *)domain_info->triplet,
225 &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len); 240 &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len);
226 241
242 rcu_read_unlock();
243
227 if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, 244 if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
228 HostCmd_ACT_GEN_SET, 0, NULL)) { 245 HostCmd_ACT_GEN_SET, 0, NULL)) {
229 wiphy_err(priv->adapter->wiphy, 246 wiphy_err(priv->adapter->wiphy,
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 441cbccbd38..f47e8b0482a 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -896,11 +896,13 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
896 goto out; 896 goto out;
897 897
898 skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, 898 skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
899 req->ie, req->ie_len); 899 req->ie_len);
900 if (!skb) { 900 if (!skb) {
901 ret = -ENOMEM; 901 ret = -ENOMEM;
902 goto out; 902 goto out;
903 } 903 }
904 if (req->ie_len)
905 memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len);
904 906
905 ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data, 907 ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data,
906 skb->len); 908 skb->len);
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index eaef3f41b25..27f83f72a93 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -1038,11 +1038,13 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1038 u16 template_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; 1038 u16 template_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
1039 1039
1040 skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, 1040 skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
1041 ie, ie_len); 1041 ie_len);
1042 if (!skb) { 1042 if (!skb) {
1043 ret = -ENOMEM; 1043 ret = -ENOMEM;
1044 goto out; 1044 goto out;
1045 } 1045 }
1046 if (ie_len)
1047 memcpy(skb_put(skb, ie_len), ie, ie_len);
1046 1048
1047 wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); 1049 wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
1048 1050
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index f9c5a787d35..8f690e53dd8 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1213,6 +1213,21 @@ struct ieee80211_vht_cap {
1213} __packed; 1213} __packed;
1214 1214
1215/** 1215/**
1216 * enum ieee80211_vht_chanwidth - VHT channel width
1217 * @IEEE80211_VHT_CHANWIDTH_USE_HT: use the HT operation IE to
1218 * determine the channel width (20 or 40 MHz)
1219 * @IEEE80211_VHT_CHANWIDTH_80MHZ: 80 MHz bandwidth
1220 * @IEEE80211_VHT_CHANWIDTH_160MHZ: 160 MHz bandwidth
1221 * @IEEE80211_VHT_CHANWIDTH_80P80MHZ: 80+80 MHz bandwidth
1222 */
1223enum ieee80211_vht_chanwidth {
1224 IEEE80211_VHT_CHANWIDTH_USE_HT = 0,
1225 IEEE80211_VHT_CHANWIDTH_80MHZ = 1,
1226 IEEE80211_VHT_CHANWIDTH_160MHZ = 2,
1227 IEEE80211_VHT_CHANWIDTH_80P80MHZ = 3,
1228};
1229
1230/**
1216 * struct ieee80211_vht_operation - VHT operation IE 1231 * struct ieee80211_vht_operation - VHT operation IE
1217 * 1232 *
1218 * This structure is the "VHT operation element" as 1233 * This structure is the "VHT operation element" as
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e78db2cf3d1..8e6a6b73b9c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -58,6 +58,8 @@
58 * structures here describe these capabilities in detail. 58 * structures here describe these capabilities in detail.
59 */ 59 */
60 60
61struct wiphy;
62
61/* 63/*
62 * wireless hardware capability structures 64 * wireless hardware capability structures
63 */ 65 */
@@ -388,6 +390,22 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
388 const struct cfg80211_chan_def *chandef2); 390 const struct cfg80211_chan_def *chandef2);
389 391
390/** 392/**
393 * cfg80211_chandef_valid - check if a channel definition is valid
394 * @chandef: the channel definition to check
395 */
396bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef);
397
398/**
399 * cfg80211_chandef_usable - check if secondary channels can be used
400 * @wiphy: the wiphy to validate against
401 * @chandef: the channel definition to check
402 * @prohibited_flags: the regulatory chanenl flags that must not be set
403 */
404bool cfg80211_chandef_usable(struct wiphy *wiphy,
405 const struct cfg80211_chan_def *chandef,
406 u32 prohibited_flags);
407
408/**
391 * enum survey_info_flags - survey information flags 409 * enum survey_info_flags - survey information flags
392 * 410 *
393 * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in 411 * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
@@ -520,6 +538,8 @@ struct cfg80211_beacon_data {
520 * @privacy: the BSS uses privacy 538 * @privacy: the BSS uses privacy
521 * @auth_type: Authentication type (algorithm) 539 * @auth_type: Authentication type (algorithm)
522 * @inactivity_timeout: time in seconds to determine station's inactivity. 540 * @inactivity_timeout: time in seconds to determine station's inactivity.
541 * @p2p_ctwindow: P2P CT Window
542 * @p2p_opp_ps: P2P opportunistic PS
523 */ 543 */
524struct cfg80211_ap_settings { 544struct cfg80211_ap_settings {
525 struct cfg80211_chan_def chandef; 545 struct cfg80211_chan_def chandef;
@@ -534,6 +554,8 @@ struct cfg80211_ap_settings {
534 bool privacy; 554 bool privacy;
535 enum nl80211_auth_type auth_type; 555 enum nl80211_auth_type auth_type;
536 int inactivity_timeout; 556 int inactivity_timeout;
557 u8 p2p_ctwindow;
558 bool p2p_opp_ps;
537}; 559};
538 560
539/** 561/**
@@ -895,6 +917,8 @@ struct mpath_info {
895 * @ap_isolate: do not forward packets between connected stations 917 * @ap_isolate: do not forward packets between connected stations
896 * @ht_opmode: HT Operation mode 918 * @ht_opmode: HT Operation mode
897 * (u16 = opmode, -1 = do not change) 919 * (u16 = opmode, -1 = do not change)
920 * @p2p_ctwindow: P2P CT Window (-1 = no change)
921 * @p2p_opp_ps: P2P opportunistic PS (-1 = no change)
898 */ 922 */
899struct bss_parameters { 923struct bss_parameters {
900 int use_cts_prot; 924 int use_cts_prot;
@@ -904,6 +928,7 @@ struct bss_parameters {
904 u8 basic_rates_len; 928 u8 basic_rates_len;
905 int ap_isolate; 929 int ap_isolate;
906 int ht_opmode; 930 int ht_opmode;
931 s8 p2p_ctwindow, p2p_opp_ps;
907}; 932};
908 933
909/** 934/**
@@ -1045,9 +1070,6 @@ struct ieee80211_txq_params {
1045 u8 aifs; 1070 u8 aifs;
1046}; 1071};
1047 1072
1048/* from net/wireless.h */
1049struct wiphy;
1050
1051/** 1073/**
1052 * DOC: Scanning and BSS list handling 1074 * DOC: Scanning and BSS list handling
1053 * 1075 *
@@ -1184,6 +1206,18 @@ enum cfg80211_signal_type {
1184}; 1206};
1185 1207
1186/** 1208/**
1209 * struct cfg80211_bss_ie_data - BSS entry IE data
1210 * @rcu_head: internal use, for freeing
1211 * @len: length of the IEs
1212 * @data: IE data
1213 */
1214struct cfg80211_bss_ies {
1215 struct rcu_head rcu_head;
1216 int len;
1217 u8 data[];
1218};
1219
1220/**
1187 * struct cfg80211_bss - BSS description 1221 * struct cfg80211_bss - BSS description
1188 * 1222 *
1189 * This structure describes a BSS (which may also be a mesh network) 1223 * This structure describes a BSS (which may also be a mesh network)
@@ -1194,36 +1228,34 @@ enum cfg80211_signal_type {
1194 * @tsf: timestamp of last received update 1228 * @tsf: timestamp of last received update
1195 * @beacon_interval: the beacon interval as from the frame 1229 * @beacon_interval: the beacon interval as from the frame
1196 * @capability: the capability field in host byte order 1230 * @capability: the capability field in host byte order
1197 * @information_elements: the information elements (Note that there 1231 * @ies: the information elements (Note that there
1198 * is no guarantee that these are well-formed!); this is a pointer to 1232 * is no guarantee that these are well-formed!); this is a pointer to
1199 * either the beacon_ies or proberesp_ies depending on whether Probe 1233 * either the beacon_ies or proberesp_ies depending on whether Probe
1200 * Response frame has been received 1234 * Response frame has been received
1201 * @len_information_elements: total length of the information elements
1202 * @beacon_ies: the information elements from the last Beacon frame 1235 * @beacon_ies: the information elements from the last Beacon frame
1203 * @len_beacon_ies: total length of the beacon_ies
1204 * @proberesp_ies: the information elements from the last Probe Response frame 1236 * @proberesp_ies: the information elements from the last Probe Response frame
1205 * @len_proberesp_ies: total length of the proberesp_ies
1206 * @signal: signal strength value (type depends on the wiphy's signal_type) 1237 * @signal: signal strength value (type depends on the wiphy's signal_type)
1207 * @free_priv: function pointer to free private data 1238 * @free_priv: function pointer to free private data
1208 * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes 1239 * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
1209 */ 1240 */
1210struct cfg80211_bss { 1241struct cfg80211_bss {
1242 u64 tsf;
1243
1211 struct ieee80211_channel *channel; 1244 struct ieee80211_channel *channel;
1212 1245
1213 u8 bssid[ETH_ALEN]; 1246 const struct cfg80211_bss_ies __rcu *ies;
1214 u64 tsf; 1247 const struct cfg80211_bss_ies __rcu *beacon_ies;
1248 const struct cfg80211_bss_ies __rcu *proberesp_ies;
1249
1250 void (*free_priv)(struct cfg80211_bss *bss);
1251
1252 s32 signal;
1253
1215 u16 beacon_interval; 1254 u16 beacon_interval;
1216 u16 capability; 1255 u16 capability;
1217 u8 *information_elements;
1218 size_t len_information_elements;
1219 u8 *beacon_ies;
1220 size_t len_beacon_ies;
1221 u8 *proberesp_ies;
1222 size_t len_proberesp_ies;
1223 1256
1224 s32 signal; 1257 u8 bssid[ETH_ALEN];
1225 1258
1226 void (*free_priv)(struct cfg80211_bss *bss);
1227 u8 priv[0] __attribute__((__aligned__(sizeof(void *)))); 1259 u8 priv[0] __attribute__((__aligned__(sizeof(void *))));
1228}; 1260};
1229 1261
@@ -1231,6 +1263,9 @@ struct cfg80211_bss {
1231 * ieee80211_bss_get_ie - find IE with given ID 1263 * ieee80211_bss_get_ie - find IE with given ID
1232 * @bss: the bss to search 1264 * @bss: the bss to search
1233 * @ie: the IE ID 1265 * @ie: the IE ID
1266 *
1267 * Note that the return value is an RCU-protected pointer, so
1268 * rcu_read_lock() must be held when calling this function.
1234 * Returns %NULL if not found. 1269 * Returns %NULL if not found.
1235 */ 1270 */
1236const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); 1271const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index 7f0df133d11..c3999632e61 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -186,6 +186,10 @@ struct ieee80211_radiotap_header {
186 * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless 186 * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
187 * 187 *
188 * Contains the AMPDU information for the subframe. 188 * Contains the AMPDU information for the subframe.
189 *
190 * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
191 *
192 * Contains VHT information about this frame.
189 */ 193 */
190enum ieee80211_radiotap_type { 194enum ieee80211_radiotap_type {
191 IEEE80211_RADIOTAP_TSFT = 0, 195 IEEE80211_RADIOTAP_TSFT = 0,
@@ -209,6 +213,7 @@ enum ieee80211_radiotap_type {
209 213
210 IEEE80211_RADIOTAP_MCS = 19, 214 IEEE80211_RADIOTAP_MCS = 19,
211 IEEE80211_RADIOTAP_AMPDU_STATUS = 20, 215 IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
216 IEEE80211_RADIOTAP_VHT = 21,
212 217
213 /* valid in every it_present bitmap, even vendor namespaces */ 218 /* valid in every it_present bitmap, even vendor namespaces */
214 IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, 219 IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
@@ -282,6 +287,25 @@ enum ieee80211_radiotap_type {
282#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 287#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
283#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 288#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
284 289
290/* For IEEE80211_RADIOTAP_VHT */
291#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001
292#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002
293#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004
294#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008
295#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010
296#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020
297#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040
298#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080
299#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100
300
301#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01
302#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02
303#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04
304#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08
305#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10
306#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20
307
308
285/* helpers */ 309/* helpers */
286static inline int ieee80211_get_radiotap_len(unsigned char *data) 310static inline int ieee80211_get_radiotap_len(unsigned char *data)
287{ 311{
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index db7680acd0d..1c02fb3b381 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -164,7 +164,7 @@ enum ieee80211_chanctx_change {
164 * active on the channel to receive MIMO transmissions 164 * active on the channel to receive MIMO transmissions
165 * @rx_chains_dynamic: The number of RX chains that must be enabled 165 * @rx_chains_dynamic: The number of RX chains that must be enabled
166 * after RTS/CTS handshake to receive SMPS MIMO transmissions; 166 * after RTS/CTS handshake to receive SMPS MIMO transmissions;
167 * this will always be >= @rx_chains_always. 167 * this will always be >= @rx_chains_static.
168 * @drv_priv: data area for driver use, will always be aligned to 168 * @drv_priv: data area for driver use, will always be aligned to
169 * sizeof(void *), size is determined in hw information. 169 * sizeof(void *), size is determined in hw information.
170 */ 170 */
@@ -1473,6 +1473,10 @@ enum ieee80211_hw_flags {
1473 * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only 1473 * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only
1474 * adding _BW is supported today. 1474 * adding _BW is supported today.
1475 * 1475 *
1476 * @radiotap_vht_details: lists which VHT MCS information the HW reports,
1477 * the default is _GI | _BANDWIDTH.
1478 * Use the %IEEE80211_RADIOTAP_VHT_KNOWN_* values.
1479 *
1476 * @netdev_features: netdev features to be set in each netdev created 1480 * @netdev_features: netdev features to be set in each netdev created
1477 * from this HW. Note only HW checksum features are currently 1481 * from this HW. Note only HW checksum features are currently
1478 * compatible with mac80211. Other feature bits will be rejected. 1482 * compatible with mac80211. Other feature bits will be rejected.
@@ -1499,6 +1503,7 @@ struct ieee80211_hw {
1499 u8 max_tx_aggregation_subframes; 1503 u8 max_tx_aggregation_subframes;
1500 u8 offchannel_tx_hw_queue; 1504 u8 offchannel_tx_hw_queue;
1501 u8 radiotap_mcs_details; 1505 u8 radiotap_mcs_details;
1506 u16 radiotap_vht_details;
1502 netdev_features_t netdev_features; 1507 netdev_features_t netdev_features;
1503}; 1508};
1504 1509
@@ -3139,8 +3144,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
3139 * @vif: &struct ieee80211_vif pointer from the add_interface callback. 3144 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
3140 * @ssid: SSID buffer 3145 * @ssid: SSID buffer
3141 * @ssid_len: length of SSID 3146 * @ssid_len: length of SSID
3142 * @ie: buffer containing all IEs except SSID for the template 3147 * @tailroom: tailroom to reserve at end of SKB for IEs
3143 * @ie_len: length of the IE buffer
3144 * 3148 *
3145 * Creates a Probe Request template which can, for example, be uploaded to 3149 * Creates a Probe Request template which can, for example, be uploaded to
3146 * hardware. 3150 * hardware.
@@ -3148,7 +3152,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
3148struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, 3152struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
3149 struct ieee80211_vif *vif, 3153 struct ieee80211_vif *vif,
3150 const u8 *ssid, size_t ssid_len, 3154 const u8 *ssid, size_t ssid_len,
3151 const u8 *ie, size_t ie_len); 3155 size_t tailroom);
3152 3156
3153/** 3157/**
3154 * ieee80211_rts_get - RTS frame generation function 3158 * ieee80211_rts_get - RTS frame generation function
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 33a417481ad..e3e19f8b16f 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1303,6 +1303,13 @@ enum nl80211_commands {
1303 * 1303 *
1304 * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32) 1304 * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32)
1305 * 1305 *
1306 * @NL80211_ATTR_P2P_CTWINDOW: P2P GO Client Traffic Window (u8), used with
1307 * the START_AP and SET_BSS commands
1308 * @NL80211_ATTR_P2P_OPPPS: P2P GO opportunistic PS (u8), used with the
1309 * START_AP and SET_BSS commands. This can have the values 0 or 1;
1310 * if not given in START_AP 0 is assumed, if not given in SET_BSS
1311 * no change is made.
1312 *
1306 * @NL80211_ATTR_MAX: highest attribute number currently defined 1313 * @NL80211_ATTR_MAX: highest attribute number currently defined
1307 * @__NL80211_ATTR_AFTER_LAST: internal use 1314 * @__NL80211_ATTR_AFTER_LAST: internal use
1308 */ 1315 */
@@ -1570,6 +1577,9 @@ enum nl80211_attrs {
1570 NL80211_ATTR_CENTER_FREQ1, 1577 NL80211_ATTR_CENTER_FREQ1,
1571 NL80211_ATTR_CENTER_FREQ2, 1578 NL80211_ATTR_CENTER_FREQ2,
1572 1579
1580 NL80211_ATTR_P2P_CTWINDOW,
1581 NL80211_ATTR_P2P_OPPPS,
1582
1573 /* add attributes here, update the policy in nl80211.c */ 1583 /* add attributes here, update the policy in nl80211.c */
1574 1584
1575 __NL80211_ATTR_AFTER_LAST, 1585 __NL80211_ATTR_AFTER_LAST,
@@ -3126,6 +3136,10 @@ enum nl80211_ap_sme_features {
3126 * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform 3136 * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform
3127 * OBSS scans and generate 20/40 BSS coex reports. This flag is used only 3137 * OBSS scans and generate 20/40 BSS coex reports. This flag is used only
3128 * for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied. 3138 * for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied.
3139 * @NL80211_FEATURE_P2P_GO_CTWIN: P2P GO implementation supports CT Window
3140 * setting
3141 * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic
3142 * powersave
3129 */ 3143 */
3130enum nl80211_feature_flags { 3144enum nl80211_feature_flags {
3131 NL80211_FEATURE_SK_TX_STATUS = 1 << 0, 3145 NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -3139,6 +3153,8 @@ enum nl80211_feature_flags {
3139 NL80211_FEATURE_AP_SCAN = 1 << 8, 3153 NL80211_FEATURE_AP_SCAN = 1 << 8,
3140 NL80211_FEATURE_VIF_TXPOWER = 1 << 9, 3154 NL80211_FEATURE_VIF_TXPOWER = 1 << 9,
3141 NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10, 3155 NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10,
3156 NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11,
3157 NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12,
3142}; 3158};
3143 3159
3144/** 3160/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4965aa6424e..5c61677487c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -398,6 +398,38 @@ void sta_set_rate_info_tx(struct sta_info *sta,
398 rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; 398 rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
399} 399}
400 400
401void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
402{
403 rinfo->flags = 0;
404
405 if (sta->last_rx_rate_flag & RX_FLAG_HT) {
406 rinfo->flags |= RATE_INFO_FLAGS_MCS;
407 rinfo->mcs = sta->last_rx_rate_idx;
408 } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) {
409 rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
410 rinfo->nss = sta->last_rx_rate_vht_nss;
411 rinfo->mcs = sta->last_rx_rate_idx;
412 } else {
413 struct ieee80211_supported_band *sband;
414
415 sband = sta->local->hw.wiphy->bands[
416 ieee80211_get_sdata_band(sta->sdata)];
417 rinfo->legacy =
418 sband->bitrates[sta->last_rx_rate_idx].bitrate;
419 }
420
421 if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
422 rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
423 if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
424 rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
425 if (sta->last_rx_rate_flag & RX_FLAG_80MHZ)
426 rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
427 if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ)
428 rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
429 if (sta->last_rx_rate_flag & RX_FLAG_160MHZ)
430 rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
431}
432
401static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) 433static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
402{ 434{
403 struct ieee80211_sub_if_data *sdata = sta->sdata; 435 struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -444,34 +476,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
444 } 476 }
445 477
446 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); 478 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
447 479 sta_set_rate_info_rx(sta, &sinfo->rxrate);
448 sinfo->rxrate.flags = 0;
449 if (sta->last_rx_rate_flag & RX_FLAG_HT) {
450 sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS;
451 sinfo->rxrate.mcs = sta->last_rx_rate_idx;
452 } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) {
453 sinfo->rxrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
454 sinfo->rxrate.nss = sta->last_rx_rate_vht_nss;
455 sinfo->rxrate.mcs = sta->last_rx_rate_idx;
456 } else {
457 struct ieee80211_supported_band *sband;
458
459 sband = sta->local->hw.wiphy->bands[
460 ieee80211_get_sdata_band(sta->sdata)];
461 sinfo->rxrate.legacy =
462 sband->bitrates[sta->last_rx_rate_idx].bitrate;
463 }
464
465 if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
466 sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
467 if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
468 sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
469 if (sta->last_rx_rate_flag & RX_FLAG_80MHZ)
470 sinfo->rxrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
471 if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ)
472 sinfo->rxrate.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
473 if (sta->last_rx_rate_flag & RX_FLAG_160MHZ)
474 sinfo->rxrate.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
475 480
476 if (ieee80211_vif_is_mesh(&sdata->vif)) { 481 if (ieee80211_vif_is_mesh(&sdata->vif)) {
477#ifdef CONFIG_MAC80211_MESH 482#ifdef CONFIG_MAC80211_MESH
@@ -893,7 +898,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
893 u32 changed = BSS_CHANGED_BEACON_INT | 898 u32 changed = BSS_CHANGED_BEACON_INT |
894 BSS_CHANGED_BEACON_ENABLED | 899 BSS_CHANGED_BEACON_ENABLED |
895 BSS_CHANGED_BEACON | 900 BSS_CHANGED_BEACON |
896 BSS_CHANGED_SSID; 901 BSS_CHANGED_SSID |
902 BSS_CHANGED_P2P_PS;
897 int err; 903 int err;
898 904
899 old = rtnl_dereference(sdata->u.ap.beacon); 905 old = rtnl_dereference(sdata->u.ap.beacon);
@@ -932,6 +938,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
932 sdata->vif.bss_conf.hidden_ssid = 938 sdata->vif.bss_conf.hidden_ssid =
933 (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); 939 (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);
934 940
941 sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
942 sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
943
935 err = ieee80211_assign_beacon(sdata, &params->beacon); 944 err = ieee80211_assign_beacon(sdata, &params->beacon);
936 if (err < 0) 945 if (err < 0)
937 return err; 946 return err;
@@ -1807,6 +1816,16 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
1807 changed |= BSS_CHANGED_HT; 1816 changed |= BSS_CHANGED_HT;
1808 } 1817 }
1809 1818
1819 if (params->p2p_ctwindow >= 0) {
1820 sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
1821 changed |= BSS_CHANGED_P2P_PS;
1822 }
1823
1824 if (params->p2p_opp_ps >= 0) {
1825 sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
1826 changed |= BSS_CHANGED_P2P_PS;
1827 }
1828
1810 ieee80211_bss_info_change_notify(sdata, changed); 1829 ieee80211_bss_info_change_notify(sdata, changed);
1811 1830
1812 return 0; 1831 return 0;
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 89281d24b09..49a1c70bbd7 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -53,6 +53,7 @@ static const struct file_operations sta_ ##name## _ops = { \
53STA_FILE(aid, sta.aid, D); 53STA_FILE(aid, sta.aid, D);
54STA_FILE(dev, sdata->name, S); 54STA_FILE(dev, sdata->name, S);
55STA_FILE(last_signal, last_signal, D); 55STA_FILE(last_signal, last_signal, D);
56STA_FILE(last_ack_signal, last_ack_signal, D);
56 57
57static ssize_t sta_flags_read(struct file *file, char __user *userbuf, 58static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
58 size_t count, loff_t *ppos) 59 size_t count, loff_t *ppos)
@@ -321,6 +322,38 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
321} 322}
322STA_OPS(ht_capa); 323STA_OPS(ht_capa);
323 324
325static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf,
326 size_t count, loff_t *ppos)
327{
328 struct sta_info *sta = file->private_data;
329 struct rate_info rinfo;
330 u16 rate;
331 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo);
332 rate = cfg80211_calculate_bitrate(&rinfo);
333
334 return mac80211_format_buffer(userbuf, count, ppos,
335 "%d.%d MBit/s\n",
336 rate/10, rate%10);
337}
338STA_OPS(current_tx_rate);
339
340static ssize_t sta_last_rx_rate_read(struct file *file, char __user *userbuf,
341 size_t count, loff_t *ppos)
342{
343 struct sta_info *sta = file->private_data;
344 struct rate_info rinfo;
345 u16 rate;
346
347 sta_set_rate_info_rx(sta, &rinfo);
348
349 rate = cfg80211_calculate_bitrate(&rinfo);
350
351 return mac80211_format_buffer(userbuf, count, ppos,
352 "%d.%d MBit/s\n",
353 rate/10, rate%10);
354}
355STA_OPS(last_rx_rate);
356
324#define DEBUGFS_ADD(name) \ 357#define DEBUGFS_ADD(name) \
325 debugfs_create_file(#name, 0400, \ 358 debugfs_create_file(#name, 0400, \
326 sta->debugfs.dir, sta, &sta_ ##name## _ops); 359 sta->debugfs.dir, sta, &sta_ ##name## _ops);
@@ -369,6 +402,9 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
369 DEBUGFS_ADD(dev); 402 DEBUGFS_ADD(dev);
370 DEBUGFS_ADD(last_signal); 403 DEBUGFS_ADD(last_signal);
371 DEBUGFS_ADD(ht_capa); 404 DEBUGFS_ADD(ht_capa);
405 DEBUGFS_ADD(last_ack_signal);
406 DEBUGFS_ADD(current_tx_rate);
407 DEBUGFS_ADD(last_rx_rate);
372 408
373 DEBUGFS_ADD_COUNTER(rx_packets, rx_packets); 409 DEBUGFS_ADD_COUNTER(rx_packets, rx_packets);
374 DEBUGFS_ADD_COUNTER(tx_packets, tx_packets); 410 DEBUGFS_ADD_COUNTER(tx_packets, tx_packets);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5c0d5a6946c..42d0d026773 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -371,6 +371,8 @@ enum ieee80211_sta_flags {
371 IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), 371 IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9),
372 IEEE80211_STA_DISABLE_40MHZ = BIT(10), 372 IEEE80211_STA_DISABLE_40MHZ = BIT(10),
373 IEEE80211_STA_DISABLE_VHT = BIT(11), 373 IEEE80211_STA_DISABLE_VHT = BIT(11),
374 IEEE80211_STA_DISABLE_80P80MHZ = BIT(12),
375 IEEE80211_STA_DISABLE_160MHZ = BIT(13),
374}; 376};
375 377
376struct ieee80211_mgd_auth_data { 378struct ieee80211_mgd_auth_data {
@@ -1032,6 +1034,7 @@ struct ieee80211_local {
1032 enum ieee80211_band hw_scan_band; 1034 enum ieee80211_band hw_scan_band;
1033 int scan_channel_idx; 1035 int scan_channel_idx;
1034 int scan_ies_len; 1036 int scan_ies_len;
1037 int hw_scan_ies_bufsize;
1035 1038
1036 struct work_struct sched_scan_stopped_work; 1039 struct work_struct sched_scan_stopped_work;
1037 struct ieee80211_sub_if_data __rcu *sched_scan_sdata; 1040 struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
@@ -1573,7 +1576,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
1573 const u8 *bssid, u16 stype, u16 reason, 1576 const u8 *bssid, u16 stype, u16 reason,
1574 bool send_frame, u8 *frame_buf); 1577 bool send_frame, u8 *frame_buf);
1575int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 1578int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1576 const u8 *ie, size_t ie_len, 1579 size_t buffer_len, const u8 *ie, size_t ie_len,
1577 enum ieee80211_band band, u32 rate_mask, 1580 enum ieee80211_band band, u32 rate_mask,
1578 u8 channel); 1581 u8 channel);
1579struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, 1582struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 5331662489f..40c36d5d737 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -223,6 +223,47 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
223 return 0; 223 return 0;
224} 224}
225 225
226static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
227{
228 struct ieee80211_sub_if_data *sdata;
229 u64 new, mask, tmp;
230 u8 *m;
231 int ret = 0;
232
233 if (is_zero_ether_addr(local->hw.wiphy->addr_mask))
234 return 0;
235
236 m = addr;
237 new = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
238 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
239 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
240
241 m = local->hw.wiphy->addr_mask;
242 mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
243 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
244 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
245
246
247 mutex_lock(&local->iflist_mtx);
248 list_for_each_entry(sdata, &local->interfaces, list) {
249 if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
250 continue;
251
252 m = sdata->vif.addr;
253 tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
254 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
255 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
256
257 if ((new & ~mask) != (tmp & ~mask)) {
258 ret = -EINVAL;
259 break;
260 }
261 }
262 mutex_unlock(&local->iflist_mtx);
263
264 return ret;
265}
266
226static int ieee80211_change_mac(struct net_device *dev, void *addr) 267static int ieee80211_change_mac(struct net_device *dev, void *addr)
227{ 268{
228 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 269 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -232,6 +273,10 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
232 if (ieee80211_sdata_running(sdata)) 273 if (ieee80211_sdata_running(sdata))
233 return -EBUSY; 274 return -EBUSY;
234 275
276 ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
277 if (ret)
278 return ret;
279
235 ret = eth_mac_addr(dev, sa); 280 ret = eth_mac_addr(dev, sa);
236 281
237 if (ret == 0) 282 if (ret == 0)
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index f5e4c1f24bf..1b087fff93e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -474,7 +474,8 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
474 .tx = 0xffff, 474 .tx = 0xffff,
475 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | 475 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
476 BIT(IEEE80211_STYPE_AUTH >> 4) | 476 BIT(IEEE80211_STYPE_AUTH >> 4) |
477 BIT(IEEE80211_STYPE_DEAUTH >> 4), 477 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
478 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
478 }, 479 },
479 [NL80211_IFTYPE_STATION] = { 480 [NL80211_IFTYPE_STATION] = {
480 .tx = 0xffff, 481 .tx = 0xffff,
@@ -638,6 +639,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
638 local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS | 639 local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
639 IEEE80211_RADIOTAP_MCS_HAVE_GI | 640 IEEE80211_RADIOTAP_MCS_HAVE_GI |
640 IEEE80211_RADIOTAP_MCS_HAVE_BW; 641 IEEE80211_RADIOTAP_MCS_HAVE_BW;
642 local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
643 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
641 local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; 644 local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
642 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; 645 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
643 646
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index ca52dfdd537..4b274e9c91a 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -391,7 +391,8 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
391 sta->ch_width = chandef.width; 391 sta->ch_width = chandef.width;
392 } 392 }
393 393
394 rate_control_rate_init(sta); 394 if (insert)
395 rate_control_rate_init(sta);
395 spin_unlock_bh(&sta->lock); 396 spin_unlock_bh(&sta->lock);
396 397
397 if (insert && sta_info_insert(sta)) 398 if (insert && sta_info_insert(sta))
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c
index 0f40086cce1..aa8d1e43738 100644
--- a/net/mac80211/mesh_sync.c
+++ b/net/mac80211/mesh_sync.c
@@ -195,11 +195,15 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
195 ifmsh->sync_offset_clockdrift_max); 195 ifmsh->sync_offset_clockdrift_max);
196 set_bit(MESH_WORK_DRIFT_ADJUST, 196 set_bit(MESH_WORK_DRIFT_ADJUST,
197 &ifmsh->wrkq_flags); 197 &ifmsh->wrkq_flags);
198
199 ifmsh->adjusting_tbtt = true;
198 } else { 200 } else {
199 msync_dbg(sdata, 201 msync_dbg(sdata,
200 "TBTT : max clockdrift=%lld; too small to adjust\n", 202 "TBTT : max clockdrift=%lld; too small to adjust\n",
201 (long long)ifmsh->sync_offset_clockdrift_max); 203 (long long)ifmsh->sync_offset_clockdrift_max);
202 ifmsh->sync_offset_clockdrift_max = 0; 204 ifmsh->sync_offset_clockdrift_max = 0;
205
206 ifmsh->adjusting_tbtt = false;
203 } 207 }
204 spin_unlock_bh(&ifmsh->sync_offset_lock); 208 spin_unlock_bh(&ifmsh->sync_offset_lock);
205} 209}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d2a4f78b4b0..09556303c7e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -354,6 +354,16 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
354 /* determine capability flags */ 354 /* determine capability flags */
355 cap = vht_cap.cap; 355 cap = vht_cap.cap;
356 356
357 if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) {
358 cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
359 cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
360 }
361
362 if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) {
363 cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
364 cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
365 }
366
357 /* reserve and fill IE */ 367 /* reserve and fill IE */
358 pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); 368 pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
359 ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); 369 ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
@@ -543,6 +553,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
543 offset = noffset; 553 offset = noffset;
544 } 554 }
545 555
556 if (WARN_ON_ONCE((ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
557 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)))
558 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
559
546 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) 560 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
547 ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, 561 ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
548 sband, chan, sdata->smps_mode); 562 sband, chan, sdata->smps_mode);
@@ -775,6 +789,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
775 "not handling channel switch with channel contexts\n"); 789 "not handling channel switch with channel contexts\n");
776 ieee80211_queue_work(&sdata->local->hw, 790 ieee80211_queue_work(&sdata->local->hw,
777 &ifmgd->csa_connection_drop_work); 791 &ifmgd->csa_connection_drop_work);
792 return;
778 } 793 }
779 794
780 mutex_lock(&sdata->local->chanctx_mtx); 795 mutex_lock(&sdata->local->chanctx_mtx);
@@ -1368,19 +1383,26 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1368 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; 1383 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
1369 1384
1370 if (sdata->vif.p2p) { 1385 if (sdata->vif.p2p) {
1371 u8 noa[2]; 1386 const struct cfg80211_bss_ies *ies;
1372 int ret;
1373 1387
1374 ret = cfg80211_get_p2p_attr(cbss->information_elements, 1388 rcu_read_lock();
1375 cbss->len_information_elements, 1389 ies = rcu_dereference(cbss->ies);
1376 IEEE80211_P2P_ATTR_ABSENCE_NOTICE, 1390 if (ies) {
1377 noa, sizeof(noa)); 1391 u8 noa[2];
1378 if (ret >= 2) { 1392 int ret;
1379 bss_conf->p2p_oppps = noa[1] & 0x80; 1393
1380 bss_conf->p2p_ctwindow = noa[1] & 0x7f; 1394 ret = cfg80211_get_p2p_attr(
1381 bss_info_changed |= BSS_CHANGED_P2P_PS; 1395 ies->data, ies->len,
1382 sdata->u.mgd.p2p_noa_index = noa[0]; 1396 IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
1397 noa, sizeof(noa));
1398 if (ret >= 2) {
1399 bss_conf->p2p_oppps = noa[1] & 0x80;
1400 bss_conf->p2p_ctwindow = noa[1] & 0x7f;
1401 bss_info_changed |= BSS_CHANGED_P2P_PS;
1402 sdata->u.mgd.p2p_noa_index = noa[0];
1403 }
1383 } 1404 }
1405 rcu_read_unlock();
1384 } 1406 }
1385 1407
1386 /* just to be sure */ 1408 /* just to be sure */
@@ -1645,6 +1667,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1645 } else { 1667 } else {
1646 int ssid_len; 1668 int ssid_len;
1647 1669
1670 rcu_read_lock();
1648 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1671 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1649 if (WARN_ON_ONCE(ssid == NULL)) 1672 if (WARN_ON_ONCE(ssid == NULL))
1650 ssid_len = 0; 1673 ssid_len = 0;
@@ -1654,6 +1677,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1654 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, 1677 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
1655 0, (u32) -1, true, false, 1678 0, (u32) -1, true, false,
1656 ifmgd->associated->channel, false); 1679 ifmgd->associated->channel, false);
1680 rcu_read_unlock();
1657 } 1681 }
1658 1682
1659 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); 1683 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
@@ -1749,6 +1773,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1749 else 1773 else
1750 return NULL; 1774 return NULL;
1751 1775
1776 rcu_read_lock();
1752 ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); 1777 ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
1753 if (WARN_ON_ONCE(ssid == NULL)) 1778 if (WARN_ON_ONCE(ssid == NULL))
1754 ssid_len = 0; 1779 ssid_len = 0;
@@ -1759,6 +1784,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1759 (u32) -1, cbss->channel, 1784 (u32) -1, cbss->channel,
1760 ssid + 2, ssid_len, 1785 ssid + 2, ssid_len,
1761 NULL, 0, true); 1786 NULL, 0, true);
1787 rcu_read_unlock();
1762 1788
1763 return skb; 1789 return skb;
1764} 1790}
@@ -2844,9 +2870,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
2844 auth_data->bss->bssid, auth_data->tries, 2870 auth_data->bss->bssid, auth_data->tries,
2845 IEEE80211_AUTH_MAX_TRIES); 2871 IEEE80211_AUTH_MAX_TRIES);
2846 2872
2873 rcu_read_lock();
2847 ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); 2874 ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID);
2848 if (!ssidie) 2875 if (!ssidie) {
2876 rcu_read_unlock();
2849 return -EINVAL; 2877 return -EINVAL;
2878 }
2850 /* 2879 /*
2851 * Direct probe is sent to broadcast address as some APs 2880 * Direct probe is sent to broadcast address as some APs
2852 * will not answer to direct packet in unassociated state. 2881 * will not answer to direct packet in unassociated state.
@@ -2854,6 +2883,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
2854 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], 2883 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
2855 NULL, 0, (u32) -1, true, false, 2884 NULL, 0, (u32) -1, true, false,
2856 auth_data->bss->channel, false); 2885 auth_data->bss->channel, false);
2886 rcu_read_unlock();
2857 } 2887 }
2858 2888
2859 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; 2889 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
@@ -3183,106 +3213,313 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
3183 return 0; 3213 return 0;
3184} 3214}
3185 3215
3216static u32 chandef_downgrade(struct cfg80211_chan_def *c)
3217{
3218 u32 ret;
3219 int tmp;
3220
3221 switch (c->width) {
3222 case NL80211_CHAN_WIDTH_20:
3223 c->width = NL80211_CHAN_WIDTH_20_NOHT;
3224 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
3225 break;
3226 case NL80211_CHAN_WIDTH_40:
3227 c->width = NL80211_CHAN_WIDTH_20;
3228 c->center_freq1 = c->chan->center_freq;
3229 ret = IEEE80211_STA_DISABLE_40MHZ |
3230 IEEE80211_STA_DISABLE_VHT;
3231 break;
3232 case NL80211_CHAN_WIDTH_80:
3233 tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
3234 /* n_P40 */
3235 tmp /= 2;
3236 /* freq_P40 */
3237 c->center_freq1 = c->center_freq1 - 20 + 40 * tmp;
3238 c->width = NL80211_CHAN_WIDTH_40;
3239 ret = IEEE80211_STA_DISABLE_VHT;
3240 break;
3241 case NL80211_CHAN_WIDTH_80P80:
3242 c->center_freq2 = 0;
3243 c->width = NL80211_CHAN_WIDTH_80;
3244 ret = IEEE80211_STA_DISABLE_80P80MHZ |
3245 IEEE80211_STA_DISABLE_160MHZ;
3246 break;
3247 case NL80211_CHAN_WIDTH_160:
3248 /* n_P20 */
3249 tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
3250 /* n_P80 */
3251 tmp /= 4;
3252 c->center_freq1 = c->center_freq1 - 40 + 80 * tmp;
3253 c->width = NL80211_CHAN_WIDTH_80;
3254 ret = IEEE80211_STA_DISABLE_80P80MHZ |
3255 IEEE80211_STA_DISABLE_160MHZ;
3256 break;
3257 default:
3258 case NL80211_CHAN_WIDTH_20_NOHT:
3259 WARN_ON_ONCE(1);
3260 c->width = NL80211_CHAN_WIDTH_20_NOHT;
3261 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
3262 break;
3263 }
3264
3265 WARN_ON_ONCE(!cfg80211_chandef_valid(c));
3266
3267 return ret;
3268}
3269
3270static u32
3271ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
3272 struct ieee80211_supported_band *sband,
3273 struct ieee80211_channel *channel,
3274 const struct ieee80211_ht_operation *ht_oper,
3275 const struct ieee80211_vht_operation *vht_oper,
3276 struct cfg80211_chan_def *chandef)
3277{
3278 struct cfg80211_chan_def vht_chandef;
3279 u32 ht_cfreq, ret;
3280
3281 chandef->chan = channel;
3282 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
3283 chandef->center_freq1 = channel->center_freq;
3284 chandef->center_freq2 = 0;
3285
3286 if (!ht_oper || !sband->ht_cap.ht_supported) {
3287 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
3288 goto out;
3289 }
3290
3291 chandef->width = NL80211_CHAN_WIDTH_20;
3292
3293 ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
3294 channel->band);
3295 /* check that channel matches the right operating channel */
3296 if (channel->center_freq != ht_cfreq) {
3297 /*
3298 * It's possible that some APs are confused here;
3299 * Netgear WNDR3700 sometimes reports 4 higher than
3300 * the actual channel in association responses, but
3301 * since we look at probe response/beacon data here
3302 * it should be OK.
3303 */
3304 sdata_info(sdata,
3305 "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
3306 channel->center_freq, ht_cfreq,
3307 ht_oper->primary_chan, channel->band);
3308 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
3309 goto out;
3310 }
3311
3312 /* check 40 MHz support, if we have it */
3313 if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
3314 switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
3315 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
3316 chandef->width = NL80211_CHAN_WIDTH_40;
3317 chandef->center_freq1 += 10;
3318 break;
3319 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
3320 chandef->width = NL80211_CHAN_WIDTH_40;
3321 chandef->center_freq1 -= 10;
3322 break;
3323 }
3324 } else {
3325 /* 40 MHz (and 80 MHz) must be supported for VHT */
3326 ret = IEEE80211_STA_DISABLE_VHT;
3327 goto out;
3328 }
3329
3330 if (!vht_oper || !sband->vht_cap.vht_supported) {
3331 ret = IEEE80211_STA_DISABLE_VHT;
3332 goto out;
3333 }
3334
3335 vht_chandef.chan = channel;
3336 vht_chandef.center_freq1 =
3337 ieee80211_channel_to_frequency(vht_oper->center_freq_seg1_idx,
3338 channel->band);
3339 vht_chandef.center_freq2 = 0;
3340
3341 if (vht_oper->center_freq_seg2_idx)
3342 vht_chandef.center_freq2 =
3343 ieee80211_channel_to_frequency(
3344 vht_oper->center_freq_seg2_idx,
3345 channel->band);
3346
3347 switch (vht_oper->chan_width) {
3348 case IEEE80211_VHT_CHANWIDTH_USE_HT:
3349 vht_chandef.width = chandef->width;
3350 break;
3351 case IEEE80211_VHT_CHANWIDTH_80MHZ:
3352 vht_chandef.width = NL80211_CHAN_WIDTH_80;
3353 break;
3354 case IEEE80211_VHT_CHANWIDTH_160MHZ:
3355 vht_chandef.width = NL80211_CHAN_WIDTH_160;
3356 break;
3357 case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
3358 vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
3359 break;
3360 default:
3361 sdata_info(sdata,
3362 "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
3363 vht_oper->chan_width);
3364 ret = IEEE80211_STA_DISABLE_VHT;
3365 goto out;
3366 }
3367
3368 if (!cfg80211_chandef_valid(&vht_chandef)) {
3369 sdata_info(sdata,
3370 "AP VHT information is invalid, disable VHT\n");
3371 ret = IEEE80211_STA_DISABLE_VHT;
3372 goto out;
3373 }
3374
3375 if (cfg80211_chandef_identical(chandef, &vht_chandef)) {
3376 ret = 0;
3377 goto out;
3378 }
3379
3380 if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
3381 sdata_info(sdata,
3382 "AP VHT information doesn't match HT, disable VHT\n");
3383 ret = IEEE80211_STA_DISABLE_VHT;
3384 goto out;
3385 }
3386
3387 *chandef = vht_chandef;
3388
3389 ret = 0;
3390
3391 while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
3392 IEEE80211_CHAN_DISABLED)) {
3393 if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
3394 ret = IEEE80211_STA_DISABLE_HT |
3395 IEEE80211_STA_DISABLE_VHT;
3396 goto out;
3397 }
3398
3399 ret = chandef_downgrade(chandef);
3400 }
3401
3402 if (chandef->width != vht_chandef.width)
3403 sdata_info(sdata,
3404 "local regulatory prevented using AP HT/VHT configuration, downgraded\n");
3405
3406out:
3407 WARN_ON_ONCE(!cfg80211_chandef_valid(chandef));
3408 return ret;
3409}
3410
3411static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata,
3412 struct cfg80211_bss *cbss)
3413{
3414 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3415 const u8 *ht_cap_ie, *vht_cap_ie;
3416 const struct ieee80211_ht_cap *ht_cap;
3417 const struct ieee80211_vht_cap *vht_cap;
3418 u8 chains = 1;
3419
3420 if (ifmgd->flags & IEEE80211_STA_DISABLE_HT)
3421 return chains;
3422
3423 ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
3424 if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) {
3425 ht_cap = (void *)(ht_cap_ie + 2);
3426 chains = ieee80211_mcs_to_chains(&ht_cap->mcs);
3427 /*
3428 * TODO: use "Tx Maximum Number Spatial Streams Supported" and
3429 * "Tx Unequal Modulation Supported" fields.
3430 */
3431 }
3432
3433 if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
3434 return chains;
3435
3436 vht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
3437 if (vht_cap_ie && vht_cap_ie[1] >= sizeof(*vht_cap)) {
3438 u8 nss;
3439 u16 tx_mcs_map;
3440
3441 vht_cap = (void *)(vht_cap_ie + 2);
3442 tx_mcs_map = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map);
3443 for (nss = 8; nss > 0; nss--) {
3444 if (((tx_mcs_map >> (2 * (nss - 1))) & 3) !=
3445 IEEE80211_VHT_MCS_NOT_SUPPORTED)
3446 break;
3447 }
3448 /* TODO: use "Tx Highest Supported Long GI Data Rate" field? */
3449 chains = max(chains, nss);
3450 }
3451
3452 return chains;
3453}
3454
3186static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, 3455static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3187 struct cfg80211_bss *cbss) 3456 struct cfg80211_bss *cbss)
3188{ 3457{
3189 struct ieee80211_local *local = sdata->local; 3458 struct ieee80211_local *local = sdata->local;
3190 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3459 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3191 int ht_cfreq;
3192 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
3193 const u8 *ht_oper_ie;
3194 const struct ieee80211_ht_operation *ht_oper = NULL; 3460 const struct ieee80211_ht_operation *ht_oper = NULL;
3461 const struct ieee80211_vht_operation *vht_oper = NULL;
3195 struct ieee80211_supported_band *sband; 3462 struct ieee80211_supported_band *sband;
3196 struct cfg80211_chan_def chandef; 3463 struct cfg80211_chan_def chandef;
3464 int ret;
3197 3465
3198 sband = local->hw.wiphy->bands[cbss->channel->band]; 3466 sband = local->hw.wiphy->bands[cbss->channel->band];
3199 3467
3200 ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; 3468 ifmgd->flags &= ~(IEEE80211_STA_DISABLE_40MHZ |
3469 IEEE80211_STA_DISABLE_80P80MHZ |
3470 IEEE80211_STA_DISABLE_160MHZ);
3201 3471
3202 if (sband->ht_cap.ht_supported) { 3472 rcu_read_lock();
3203 ht_oper_ie = cfg80211_find_ie(WLAN_EID_HT_OPERATION, 3473
3204 cbss->information_elements, 3474 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
3205 cbss->len_information_elements); 3475 sband->ht_cap.ht_supported) {
3476 const u8 *ht_oper_ie;
3477
3478 ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
3206 if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper)) 3479 if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
3207 ht_oper = (void *)(ht_oper_ie + 2); 3480 ht_oper = (void *)(ht_oper_ie + 2);
3208 } 3481 }
3209 3482
3210 if (ht_oper) { 3483 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
3211 ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, 3484 sband->vht_cap.vht_supported) {
3212 cbss->channel->band); 3485 const u8 *vht_oper_ie;
3213 /* check that channel matches the right operating channel */ 3486
3214 if (cbss->channel->center_freq != ht_cfreq) { 3487 vht_oper_ie = ieee80211_bss_get_ie(cbss,
3215 /* 3488 WLAN_EID_VHT_OPERATION);
3216 * It's possible that some APs are confused here; 3489 if (vht_oper_ie && vht_oper_ie[1] >= sizeof(*vht_oper))
3217 * Netgear WNDR3700 sometimes reports 4 higher than 3490 vht_oper = (void *)(vht_oper_ie + 2);
3218 * the actual channel in association responses, but 3491 if (vht_oper && !ht_oper) {
3219 * since we look at probe response/beacon data here 3492 vht_oper = NULL;
3220 * it should be OK.
3221 */
3222 sdata_info(sdata, 3493 sdata_info(sdata,
3223 "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", 3494 "AP advertised VHT without HT, disabling both\n");
3224 cbss->channel->center_freq, 3495 sdata->flags |= IEEE80211_STA_DISABLE_HT;
3225 ht_cfreq, ht_oper->primary_chan, 3496 sdata->flags |= IEEE80211_STA_DISABLE_VHT;
3226 cbss->channel->band);
3227 ht_oper = NULL;
3228 } 3497 }
3229 } 3498 }
3230 3499
3231 if (ht_oper) { 3500 ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
3232 /* 3501 cbss->channel,
3233 * cfg80211 already verified that the channel itself can 3502 ht_oper, vht_oper,
3234 * be used, but it didn't check that we can do the right 3503 &chandef);
3235 * HT type, so do that here as well. If HT40 isn't allowed
3236 * on this channel, disable 40 MHz operation.
3237 */
3238 const u8 *ht_cap_ie;
3239 const struct ieee80211_ht_cap *ht_cap;
3240 u8 chains = 1;
3241
3242 channel_type = NL80211_CHAN_HT20;
3243
3244 if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
3245 switch (ht_oper->ht_param &
3246 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
3247 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
3248 if (cbss->channel->flags &
3249 IEEE80211_CHAN_NO_HT40PLUS)
3250 ifmgd->flags |=
3251 IEEE80211_STA_DISABLE_40MHZ;
3252 else
3253 channel_type = NL80211_CHAN_HT40PLUS;
3254 break;
3255 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
3256 if (cbss->channel->flags &
3257 IEEE80211_CHAN_NO_HT40MINUS)
3258 ifmgd->flags |=
3259 IEEE80211_STA_DISABLE_40MHZ;
3260 else
3261 channel_type = NL80211_CHAN_HT40MINUS;
3262 break;
3263 }
3264 }
3265 3504
3266 ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, 3505 sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
3267 cbss->information_elements, 3506 local->rx_chains);
3268 cbss->len_information_elements); 3507
3269 if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) { 3508 rcu_read_unlock();
3270 ht_cap = (void *)(ht_cap_ie + 2);
3271 chains = ieee80211_mcs_to_chains(&ht_cap->mcs);
3272 }
3273 sdata->needed_rx_chains = min(chains, local->rx_chains);
3274 } else {
3275 sdata->needed_rx_chains = 1;
3276 sdata->u.mgd.flags |= IEEE80211_STA_DISABLE_HT;
3277 }
3278 3509
3279 /* will change later if needed */ 3510 /* will change later if needed */
3280 sdata->smps_mode = IEEE80211_SMPS_OFF; 3511 sdata->smps_mode = IEEE80211_SMPS_OFF;
3281 3512
3282 ieee80211_vif_release_channel(sdata); 3513 /*
3283 cfg80211_chandef_create(&chandef, cbss->channel, channel_type); 3514 * If this fails (possibly due to channel context sharing
3284 return ieee80211_vif_use_channel(sdata, &chandef, 3515 * on incompatible channels, e.g. 80+80 and 160 sharing the
3285 IEEE80211_CHANCTX_SHARED); 3516 * same control channel) try to use a smaller bandwidth.
3517 */
3518 ret = ieee80211_vif_use_channel(sdata, &chandef,
3519 IEEE80211_CHANCTX_SHARED);
3520 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
3521 ifmgd->flags |= chandef_downgrade(&chandef);
3522 return ret;
3286} 3523}
3287 3524
3288static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, 3525static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
@@ -3510,14 +3747,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3510 const u8 *ssidie, *ht_ie; 3747 const u8 *ssidie, *ht_ie;
3511 int i, err; 3748 int i, err;
3512 3749
3513 ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
3514 if (!ssidie)
3515 return -EINVAL;
3516
3517 assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); 3750 assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL);
3518 if (!assoc_data) 3751 if (!assoc_data)
3519 return -ENOMEM; 3752 return -ENOMEM;
3520 3753
3754 rcu_read_lock();
3755 ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
3756 if (!ssidie) {
3757 rcu_read_unlock();
3758 kfree(assoc_data);
3759 return -EINVAL;
3760 }
3761 memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
3762 assoc_data->ssid_len = ssidie[1];
3763 rcu_read_unlock();
3764
3521 mutex_lock(&ifmgd->mtx); 3765 mutex_lock(&ifmgd->mtx);
3522 3766
3523 if (ifmgd->associated) 3767 if (ifmgd->associated)
@@ -3612,12 +3856,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3612 assoc_data->supp_rates = bss->supp_rates; 3856 assoc_data->supp_rates = bss->supp_rates;
3613 assoc_data->supp_rates_len = bss->supp_rates_len; 3857 assoc_data->supp_rates_len = bss->supp_rates_len;
3614 3858
3859 rcu_read_lock();
3615 ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); 3860 ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION);
3616 if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation)) 3861 if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation))
3617 assoc_data->ap_ht_param = 3862 assoc_data->ap_ht_param =
3618 ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; 3863 ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param;
3619 else 3864 else
3620 ifmgd->flags |= IEEE80211_STA_DISABLE_HT; 3865 ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
3866 rcu_read_unlock();
3621 3867
3622 if (bss->wmm_used && bss->uapsd_supported && 3868 if (bss->wmm_used && bss->uapsd_supported &&
3623 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { 3869 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
@@ -3628,9 +3874,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3628 ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; 3874 ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED;
3629 } 3875 }
3630 3876
3631 memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
3632 assoc_data->ssid_len = ssidie[1];
3633
3634 if (req->prev_bssid) 3877 if (req->prev_bssid)
3635 memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN); 3878 memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN);
3636 3879
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index fb1d4aa65e8..9f9c453bc45 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -389,9 +389,9 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
389 struct ieee80211_tx_rate *ar = info->status.rates; 389 struct ieee80211_tx_rate *ar = info->status.rates;
390 struct minstrel_rate_stats *rate, *rate2; 390 struct minstrel_rate_stats *rate, *rate2;
391 struct minstrel_priv *mp = priv; 391 struct minstrel_priv *mp = priv;
392 bool last = false; 392 bool last;
393 int group; 393 int group;
394 int i = 0; 394 int i;
395 395
396 if (!msp->is_ht) 396 if (!msp->is_ht)
397 return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb); 397 return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb);
@@ -419,13 +419,11 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
419 if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) 419 if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
420 mi->sample_packets += info->status.ampdu_len; 420 mi->sample_packets += info->status.ampdu_len;
421 421
422 last = !minstrel_ht_txstat_valid(&ar[0]);
422 for (i = 0; !last; i++) { 423 for (i = 0; !last; i++) {
423 last = (i == IEEE80211_TX_MAX_RATES - 1) || 424 last = (i == IEEE80211_TX_MAX_RATES - 1) ||
424 !minstrel_ht_txstat_valid(&ar[i + 1]); 425 !minstrel_ht_txstat_valid(&ar[i + 1]);
425 426
426 if (!minstrel_ht_txstat_valid(&ar[i]))
427 break;
428
429 group = minstrel_ht_get_group_idx(&ar[i]); 427 group = minstrel_ht_get_group_idx(&ar[i]);
430 rate = &mi->groups[group].rates[ar[i].idx % 8]; 428 rate = &mi->groups[group].rates[ar[i].idx % 8];
431 429
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 825f33cf7bb..db343fa8033 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -49,7 +49,7 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
49 /* driver bug */ 49 /* driver bug */
50 WARN_ON(1); 50 WARN_ON(1);
51 dev_kfree_skb(skb); 51 dev_kfree_skb(skb);
52 skb = NULL; 52 return NULL;
53 } 53 }
54 } 54 }
55 55
@@ -111,6 +111,11 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local,
111 len += 8; 111 len += 8;
112 } 112 }
113 113
114 if (status->flag & RX_FLAG_VHT) {
115 len = ALIGN(len, 2);
116 len += 12;
117 }
118
114 if (status->vendor_radiotap_len) { 119 if (status->vendor_radiotap_len) {
115 if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) 120 if (WARN_ON_ONCE(status->vendor_radiotap_align == 0))
116 status->vendor_radiotap_align = 1; 121 status->vendor_radiotap_align = 1;
@@ -297,6 +302,41 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
297 *pos++ = 0; 302 *pos++ = 0;
298 } 303 }
299 304
305 if (status->flag & RX_FLAG_VHT) {
306 u16 known = local->hw.radiotap_vht_details;
307
308 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
309 /* known field - how to handle 80+80? */
310 if (status->flag & RX_FLAG_80P80MHZ)
311 known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
312 put_unaligned_le16(known, pos);
313 pos += 2;
314 /* flags */
315 if (status->flag & RX_FLAG_SHORT_GI)
316 *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
317 pos++;
318 /* bandwidth */
319 if (status->flag & RX_FLAG_80MHZ)
320 *pos++ = 4;
321 else if (status->flag & RX_FLAG_80P80MHZ)
322 *pos++ = 0; /* marked not known above */
323 else if (status->flag & RX_FLAG_160MHZ)
324 *pos++ = 11;
325 else if (status->flag & RX_FLAG_40MHZ)
326 *pos++ = 1;
327 else /* 20 MHz */
328 *pos++ = 0;
329 /* MCS/NSS */
330 *pos = (status->rate_idx << 4) | status->vht_nss;
331 pos += 4;
332 /* coding field */
333 pos++;
334 /* group ID */
335 pos++;
336 /* partial_aid */
337 pos += 2;
338 }
339
300 if (status->vendor_radiotap_len) { 340 if (status->vendor_radiotap_len) {
301 /* ensure 2 byte alignment for the vendor field as required */ 341 /* ensure 2 byte alignment for the vendor field as required */
302 if ((pos - (u8 *)rthdr) & 1) 342 if ((pos - (u8 *)rthdr) & 1)
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index f3340279aba..f7176ac5a53 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -247,6 +247,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
247 local->hw_scan_req->n_channels = n_chans; 247 local->hw_scan_req->n_channels = n_chans;
248 248
249 ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, 249 ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
250 local->hw_scan_ies_bufsize,
250 req->ie, req->ie_len, band, 251 req->ie, req->ie_len, band,
251 req->rates[band], 0); 252 req->rates[band], 0);
252 local->hw_scan_req->ie_len = ielen; 253 local->hw_scan_req->ie_len = ielen;
@@ -445,11 +446,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
445 if (local->ops->hw_scan) { 446 if (local->ops->hw_scan) {
446 u8 *ies; 447 u8 *ies;
447 448
449 local->hw_scan_ies_bufsize = 2 + IEEE80211_MAX_SSID_LEN +
450 local->scan_ies_len +
451 req->ie_len;
448 local->hw_scan_req = kmalloc( 452 local->hw_scan_req = kmalloc(
449 sizeof(*local->hw_scan_req) + 453 sizeof(*local->hw_scan_req) +
450 req->n_channels * sizeof(req->channels[0]) + 454 req->n_channels * sizeof(req->channels[0]) +
451 2 + IEEE80211_MAX_SSID_LEN + local->scan_ies_len + 455 local->hw_scan_ies_bufsize, GFP_KERNEL);
452 req->ie_len, GFP_KERNEL);
453 if (!local->hw_scan_req) 456 if (!local->hw_scan_req)
454 return -ENOMEM; 457 return -ENOMEM;
455 458
@@ -928,7 +931,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
928{ 931{
929 struct ieee80211_local *local = sdata->local; 932 struct ieee80211_local *local = sdata->local;
930 struct ieee80211_sched_scan_ies sched_scan_ies = {}; 933 struct ieee80211_sched_scan_ies sched_scan_ies = {};
931 int ret, i; 934 int ret, i, iebufsz;
935
936 iebufsz = 2 + IEEE80211_MAX_SSID_LEN +
937 local->scan_ies_len + req->ie_len;
932 938
933 mutex_lock(&local->mtx); 939 mutex_lock(&local->mtx);
934 940
@@ -946,10 +952,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
946 if (!local->hw.wiphy->bands[i]) 952 if (!local->hw.wiphy->bands[i])
947 continue; 953 continue;
948 954
949 sched_scan_ies.ie[i] = kzalloc(2 + IEEE80211_MAX_SSID_LEN + 955 sched_scan_ies.ie[i] = kzalloc(iebufsz, GFP_KERNEL);
950 local->scan_ies_len +
951 req->ie_len,
952 GFP_KERNEL);
953 if (!sched_scan_ies.ie[i]) { 956 if (!sched_scan_ies.ie[i]) {
954 ret = -ENOMEM; 957 ret = -ENOMEM;
955 goto out_free; 958 goto out_free;
@@ -957,8 +960,8 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
957 960
958 sched_scan_ies.len[i] = 961 sched_scan_ies.len[i] =
959 ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], 962 ieee80211_build_preq_ies(local, sched_scan_ies.ie[i],
960 req->ie, req->ie_len, i, 963 iebufsz, req->ie, req->ie_len,
961 (u32) -1, 0); 964 i, (u32) -1, 0);
962 } 965 }
963 966
964 ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); 967 ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 6835cea4e40..1489bca9ea9 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -250,6 +250,7 @@ struct sta_ampdu_mlme {
250 * @rx_dropped: number of dropped MPDUs from this STA 250 * @rx_dropped: number of dropped MPDUs from this STA
251 * @last_signal: signal of last received frame from this STA 251 * @last_signal: signal of last received frame from this STA
252 * @avg_signal: moving average of signal of received frames from this STA 252 * @avg_signal: moving average of signal of received frames from this STA
253 * @last_ack_signal: signal of last received Ack frame from this STA
253 * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) 254 * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue)
254 * @tx_filtered_count: number of frames the hardware filtered for this STA 255 * @tx_filtered_count: number of frames the hardware filtered for this STA
255 * @tx_retry_failed: number of frames that failed retry 256 * @tx_retry_failed: number of frames that failed retry
@@ -329,6 +330,7 @@ struct sta_info {
329 unsigned long rx_dropped; 330 unsigned long rx_dropped;
330 int last_signal; 331 int last_signal;
331 struct ewma avg_signal; 332 struct ewma avg_signal;
333 int last_ack_signal;
332 /* Plus 1 for non-QoS frames */ 334 /* Plus 1 for non-QoS frames */
333 __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; 335 __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1];
334 336
@@ -552,6 +554,8 @@ int sta_info_flush(struct ieee80211_local *local,
552void sta_set_rate_info_tx(struct sta_info *sta, 554void sta_set_rate_info_tx(struct sta_info *sta,
553 const struct ieee80211_tx_rate *rate, 555 const struct ieee80211_tx_rate *rate,
554 struct rate_info *rinfo); 556 struct rate_info *rinfo);
557void sta_set_rate_info_rx(struct sta_info *sta,
558 struct rate_info *rinfo);
555void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, 559void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
556 unsigned long exp_time); 560 unsigned long exp_time);
557 561
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index ab63237107c..ab50285fcba 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -539,6 +539,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
539 sta->lost_packets = 0; 539 sta->lost_packets = 0;
540 } 540 }
541 } 541 }
542
543 if (acked)
544 sta->last_ack_signal = info->status.ack_signal;
542 } 545 }
543 546
544 rcu_read_unlock(); 547 rcu_read_unlock();
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index d287a4f2c01..e9eadc40c09 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2623,7 +2623,7 @@ EXPORT_SYMBOL(ieee80211_nullfunc_get);
2623struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, 2623struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
2624 struct ieee80211_vif *vif, 2624 struct ieee80211_vif *vif,
2625 const u8 *ssid, size_t ssid_len, 2625 const u8 *ssid, size_t ssid_len,
2626 const u8 *ie, size_t ie_len) 2626 size_t tailroom)
2627{ 2627{
2628 struct ieee80211_sub_if_data *sdata; 2628 struct ieee80211_sub_if_data *sdata;
2629 struct ieee80211_local *local; 2629 struct ieee80211_local *local;
@@ -2637,7 +2637,7 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
2637 ie_ssid_len = 2 + ssid_len; 2637 ie_ssid_len = 2 + ssid_len;
2638 2638
2639 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + 2639 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
2640 ie_ssid_len + ie_len); 2640 ie_ssid_len + tailroom);
2641 if (!skb) 2641 if (!skb)
2642 return NULL; 2642 return NULL;
2643 2643
@@ -2658,11 +2658,6 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
2658 memcpy(pos, ssid, ssid_len); 2658 memcpy(pos, ssid, ssid_len);
2659 pos += ssid_len; 2659 pos += ssid_len;
2660 2660
2661 if (ie) {
2662 pos = skb_put(skb, ie_len);
2663 memcpy(pos, ie, ie_len);
2664 }
2665
2666 return skb; 2661 return skb;
2667} 2662}
2668EXPORT_SYMBOL(ieee80211_probereq_get); 2663EXPORT_SYMBOL(ieee80211_probereq_get);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 08132ff9815..f11e8c540db 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1107,12 +1107,12 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
1107} 1107}
1108 1108
1109int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 1109int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1110 const u8 *ie, size_t ie_len, 1110 size_t buffer_len, const u8 *ie, size_t ie_len,
1111 enum ieee80211_band band, u32 rate_mask, 1111 enum ieee80211_band band, u32 rate_mask,
1112 u8 channel) 1112 u8 channel)
1113{ 1113{
1114 struct ieee80211_supported_band *sband; 1114 struct ieee80211_supported_band *sband;
1115 u8 *pos; 1115 u8 *pos = buffer, *end = buffer + buffer_len;
1116 size_t offset = 0, noffset; 1116 size_t offset = 0, noffset;
1117 int supp_rates_len, i; 1117 int supp_rates_len, i;
1118 u8 rates[32]; 1118 u8 rates[32];
@@ -1123,8 +1123,6 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1123 if (WARN_ON_ONCE(!sband)) 1123 if (WARN_ON_ONCE(!sband))
1124 return 0; 1124 return 0;
1125 1125
1126 pos = buffer;
1127
1128 num_rates = 0; 1126 num_rates = 0;
1129 for (i = 0; i < sband->n_bitrates; i++) { 1127 for (i = 0; i < sband->n_bitrates; i++) {
1130 if ((BIT(i) & rate_mask) == 0) 1128 if ((BIT(i) & rate_mask) == 0)
@@ -1134,6 +1132,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1134 1132
1135 supp_rates_len = min_t(int, num_rates, 8); 1133 supp_rates_len = min_t(int, num_rates, 8);
1136 1134
1135 if (end - pos < 2 + supp_rates_len)
1136 goto out_err;
1137 *pos++ = WLAN_EID_SUPP_RATES; 1137 *pos++ = WLAN_EID_SUPP_RATES;
1138 *pos++ = supp_rates_len; 1138 *pos++ = supp_rates_len;
1139 memcpy(pos, rates, supp_rates_len); 1139 memcpy(pos, rates, supp_rates_len);
@@ -1150,6 +1150,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1150 before_extrates, 1150 before_extrates,
1151 ARRAY_SIZE(before_extrates), 1151 ARRAY_SIZE(before_extrates),
1152 offset); 1152 offset);
1153 if (end - pos < noffset - offset)
1154 goto out_err;
1153 memcpy(pos, ie + offset, noffset - offset); 1155 memcpy(pos, ie + offset, noffset - offset);
1154 pos += noffset - offset; 1156 pos += noffset - offset;
1155 offset = noffset; 1157 offset = noffset;
@@ -1157,6 +1159,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1157 1159
1158 ext_rates_len = num_rates - supp_rates_len; 1160 ext_rates_len = num_rates - supp_rates_len;
1159 if (ext_rates_len > 0) { 1161 if (ext_rates_len > 0) {
1162 if (end - pos < 2 + ext_rates_len)
1163 goto out_err;
1160 *pos++ = WLAN_EID_EXT_SUPP_RATES; 1164 *pos++ = WLAN_EID_EXT_SUPP_RATES;
1161 *pos++ = ext_rates_len; 1165 *pos++ = ext_rates_len;
1162 memcpy(pos, rates + supp_rates_len, ext_rates_len); 1166 memcpy(pos, rates + supp_rates_len, ext_rates_len);
@@ -1164,6 +1168,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1164 } 1168 }
1165 1169
1166 if (channel && sband->band == IEEE80211_BAND_2GHZ) { 1170 if (channel && sband->band == IEEE80211_BAND_2GHZ) {
1171 if (end - pos < 3)
1172 goto out_err;
1167 *pos++ = WLAN_EID_DS_PARAMS; 1173 *pos++ = WLAN_EID_DS_PARAMS;
1168 *pos++ = 1; 1174 *pos++ = 1;
1169 *pos++ = channel; 1175 *pos++ = channel;
@@ -1182,14 +1188,19 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1182 noffset = ieee80211_ie_split(ie, ie_len, 1188 noffset = ieee80211_ie_split(ie, ie_len,
1183 before_ht, ARRAY_SIZE(before_ht), 1189 before_ht, ARRAY_SIZE(before_ht),
1184 offset); 1190 offset);
1191 if (end - pos < noffset - offset)
1192 goto out_err;
1185 memcpy(pos, ie + offset, noffset - offset); 1193 memcpy(pos, ie + offset, noffset - offset);
1186 pos += noffset - offset; 1194 pos += noffset - offset;
1187 offset = noffset; 1195 offset = noffset;
1188 } 1196 }
1189 1197
1190 if (sband->ht_cap.ht_supported) 1198 if (sband->ht_cap.ht_supported) {
1199 if (end - pos < 2 + sizeof(struct ieee80211_ht_cap))
1200 goto out_err;
1191 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, 1201 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
1192 sband->ht_cap.cap); 1202 sband->ht_cap.cap);
1203 }
1193 1204
1194 /* 1205 /*
1195 * If adding more here, adjust code in main.c 1206 * If adding more here, adjust code in main.c
@@ -1199,15 +1210,23 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1199 /* add any remaining custom IEs */ 1210 /* add any remaining custom IEs */
1200 if (ie && ie_len) { 1211 if (ie && ie_len) {
1201 noffset = ie_len; 1212 noffset = ie_len;
1213 if (end - pos < noffset - offset)
1214 goto out_err;
1202 memcpy(pos, ie + offset, noffset - offset); 1215 memcpy(pos, ie + offset, noffset - offset);
1203 pos += noffset - offset; 1216 pos += noffset - offset;
1204 } 1217 }
1205 1218
1206 if (sband->vht_cap.vht_supported) 1219 if (sband->vht_cap.vht_supported) {
1220 if (end - pos < 2 + sizeof(struct ieee80211_vht_cap))
1221 goto out_err;
1207 pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, 1222 pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
1208 sband->vht_cap.cap); 1223 sband->vht_cap.cap);
1224 }
1209 1225
1210 return pos - buffer; 1226 return pos - buffer;
1227 out_err:
1228 WARN_ONCE(1, "not enough space for preq IEs\n");
1229 return pos - buffer;
1211} 1230}
1212 1231
1213struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, 1232struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
@@ -1220,14 +1239,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1220 struct ieee80211_local *local = sdata->local; 1239 struct ieee80211_local *local = sdata->local;
1221 struct sk_buff *skb; 1240 struct sk_buff *skb;
1222 struct ieee80211_mgmt *mgmt; 1241 struct ieee80211_mgmt *mgmt;
1223 size_t buf_len;
1224 u8 *buf;
1225 u8 chan_no; 1242 u8 chan_no;
1226 1243 int ies_len;
1227 /* FIXME: come up with a proper value */
1228 buf = kmalloc(200 + ie_len, GFP_KERNEL);
1229 if (!buf)
1230 return NULL;
1231 1244
1232 /* 1245 /*
1233 * Do not send DS Channel parameter for directed probe requests 1246 * Do not send DS Channel parameter for directed probe requests
@@ -1239,14 +1252,16 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1239 else 1252 else
1240 chan_no = ieee80211_frequency_to_channel(chan->center_freq); 1253 chan_no = ieee80211_frequency_to_channel(chan->center_freq);
1241 1254
1242 buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, chan->band,
1243 ratemask, chan_no);
1244
1245 skb = ieee80211_probereq_get(&local->hw, &sdata->vif, 1255 skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
1246 ssid, ssid_len, 1256 ssid, ssid_len, 100 + ie_len);
1247 buf, buf_len);
1248 if (!skb) 1257 if (!skb)
1249 goto out; 1258 return NULL;
1259
1260 ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb),
1261 skb_tailroom(skb),
1262 ie, ie_len, chan->band,
1263 ratemask, chan_no);
1264 skb_put(skb, ies_len);
1250 1265
1251 if (dst) { 1266 if (dst) {
1252 mgmt = (struct ieee80211_mgmt *) skb->data; 1267 mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -1256,9 +1271,6 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1256 1271
1257 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 1272 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
1258 1273
1259 out:
1260 kfree(buf);
1261
1262 return skb; 1274 return skb;
1263} 1275}
1264 1276
@@ -1527,7 +1539,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1527 changed |= BSS_CHANGED_IBSS; 1539 changed |= BSS_CHANGED_IBSS;
1528 /* fall through */ 1540 /* fall through */
1529 case NL80211_IFTYPE_AP: 1541 case NL80211_IFTYPE_AP:
1530 changed |= BSS_CHANGED_SSID; 1542 changed |= BSS_CHANGED_SSID | BSS_CHANGED_P2P_PS;
1531 1543
1532 if (sdata->vif.type == NL80211_IFTYPE_AP) { 1544 if (sdata->vif.type == NL80211_IFTYPE_AP) {
1533 changed |= BSS_CHANGED_AP_PROBE_RESP; 1545 changed |= BSS_CHANGED_AP_PROBE_RESP;
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index bf2dfd54ff3..b5f69831e31 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -44,7 +44,7 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
44} 44}
45EXPORT_SYMBOL(cfg80211_chandef_create); 45EXPORT_SYMBOL(cfg80211_chandef_create);
46 46
47bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef) 47bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
48{ 48{
49 u32 control_freq; 49 u32 control_freq;
50 50
@@ -105,6 +105,7 @@ bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef)
105 105
106 return true; 106 return true;
107} 107}
108EXPORT_SYMBOL(cfg80211_chandef_valid);
108 109
109static void chandef_primary_freqs(const struct cfg80211_chan_def *c, 110static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
110 int *pri40, int *pri80) 111 int *pri40, int *pri80)
@@ -187,9 +188,9 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
187} 188}
188EXPORT_SYMBOL(cfg80211_chandef_compatible); 189EXPORT_SYMBOL(cfg80211_chandef_compatible);
189 190
190bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, 191static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
191 u32 center_freq, u32 bandwidth, 192 u32 center_freq, u32 bandwidth,
192 u32 prohibited_flags) 193 u32 prohibited_flags)
193{ 194{
194 struct ieee80211_channel *c; 195 struct ieee80211_channel *c;
195 u32 freq; 196 u32 freq;
@@ -205,55 +206,88 @@ bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
205 return true; 206 return true;
206} 207}
207 208
208static bool cfg80211_check_beacon_chans(struct wiphy *wiphy, 209bool cfg80211_chandef_usable(struct wiphy *wiphy,
209 u32 center_freq, u32 bw) 210 const struct cfg80211_chan_def *chandef,
211 u32 prohibited_flags)
210{ 212{
211 return cfg80211_secondary_chans_ok(wiphy, center_freq, bw, 213 struct ieee80211_sta_ht_cap *ht_cap;
212 IEEE80211_CHAN_DISABLED | 214 struct ieee80211_sta_vht_cap *vht_cap;
213 IEEE80211_CHAN_PASSIVE_SCAN | 215 u32 width, control_freq;
214 IEEE80211_CHAN_NO_IBSS |
215 IEEE80211_CHAN_RADAR);
216}
217 216
218bool cfg80211_reg_can_beacon(struct wiphy *wiphy, 217 if (WARN_ON(!cfg80211_chandef_valid(chandef)))
219 struct cfg80211_chan_def *chandef) 218 return false;
220{
221 u32 width;
222 bool res;
223 219
224 trace_cfg80211_reg_can_beacon(wiphy, chandef); 220 ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
221 vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
225 222
226 if (WARN_ON(!cfg80211_chan_def_valid(chandef))) { 223 control_freq = chandef->chan->center_freq;
227 trace_cfg80211_return_bool(false);
228 return false;
229 }
230 224
231 switch (chandef->width) { 225 switch (chandef->width) {
232 case NL80211_CHAN_WIDTH_20_NOHT:
233 case NL80211_CHAN_WIDTH_20: 226 case NL80211_CHAN_WIDTH_20:
227 if (!ht_cap->ht_supported)
228 return false;
229 case NL80211_CHAN_WIDTH_20_NOHT:
234 width = 20; 230 width = 20;
235 break; 231 break;
236 case NL80211_CHAN_WIDTH_40: 232 case NL80211_CHAN_WIDTH_40:
237 width = 40; 233 width = 40;
234 if (!ht_cap->ht_supported)
235 return false;
236 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
237 ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
238 return false;
239 if (chandef->center_freq1 < control_freq &&
240 chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
241 return false;
242 if (chandef->center_freq1 > control_freq &&
243 chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
244 return false;
238 break; 245 break;
239 case NL80211_CHAN_WIDTH_80:
240 case NL80211_CHAN_WIDTH_80P80: 246 case NL80211_CHAN_WIDTH_80P80:
247 if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
248 return false;
249 case NL80211_CHAN_WIDTH_80:
250 if (!vht_cap->vht_supported)
251 return false;
241 width = 80; 252 width = 80;
242 break; 253 break;
243 case NL80211_CHAN_WIDTH_160: 254 case NL80211_CHAN_WIDTH_160:
255 if (!vht_cap->vht_supported)
256 return false;
257 if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
258 return false;
244 width = 160; 259 width = 160;
245 break; 260 break;
246 default: 261 default:
247 WARN_ON_ONCE(1); 262 WARN_ON_ONCE(1);
248 trace_cfg80211_return_bool(false);
249 return false; 263 return false;
250 } 264 }
251 265
252 res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq1, width); 266 /* TODO: missing regulatory check on 80/160 bandwidth */
267
268 if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1,
269 width, prohibited_flags))
270 return false;
271
272 if (!chandef->center_freq2)
273 return true;
274 return cfg80211_secondary_chans_ok(wiphy, chandef->center_freq2,
275 width, prohibited_flags);
276}
277EXPORT_SYMBOL(cfg80211_chandef_usable);
278
279bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
280 struct cfg80211_chan_def *chandef)
281{
282 bool res;
283
284 trace_cfg80211_reg_can_beacon(wiphy, chandef);
253 285
254 if (res && chandef->center_freq2) 286 res = cfg80211_chandef_usable(wiphy, chandef,
255 res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq2, 287 IEEE80211_CHAN_DISABLED |
256 width); 288 IEEE80211_CHAN_PASSIVE_SCAN |
289 IEEE80211_CHAN_NO_IBSS |
290 IEEE80211_CHAN_RADAR);
257 291
258 trace_cfg80211_return_bool(res); 292 trace_cfg80211_return_bool(res);
259 return res; 293 return res;
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a0c8decf6a4..3563097169c 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -138,8 +138,6 @@ struct cfg80211_internal_bss {
138 unsigned long ts; 138 unsigned long ts;
139 struct kref ref; 139 struct kref ref;
140 atomic_t hold; 140 atomic_t hold;
141 bool beacon_ies_allocated;
142 bool proberesp_ies_allocated;
143 141
144 /* must be last because of priv member */ 142 /* must be last because of priv member */
145 struct cfg80211_bss pub; 143 struct cfg80211_bss pub;
@@ -483,12 +481,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
483void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, 481void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
484 enum nl80211_iftype iftype, int num); 482 enum nl80211_iftype iftype, int num);
485 483
486bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef);
487
488bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
489 u32 center_freq, u32 bandwidth,
490 u32 prohibited_flags);
491
492#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 484#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
493 485
494#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS 486#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 3ee5a728228..f9d6ce5cfab 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -146,7 +146,8 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
146 if (!setup->chandef.chan) 146 if (!setup->chandef.chan)
147 return -EINVAL; 147 return -EINVAL;
148 148
149 setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT;; 149 setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
150 setup->chandef.center_freq1 = setup->chandef.chan->center_freq;
150 } 151 }
151 152
152 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) 153 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d038fa45ecd..f45706adaf3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -363,6 +363,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
363 [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, }, 363 [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
364 [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN }, 364 [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
365 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, 365 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
366 [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
367 [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
366}; 368};
367 369
368/* policy for the key attributes */ 370/* policy for the key attributes */
@@ -1369,9 +1371,7 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
1369 struct genl_info *info, 1371 struct genl_info *info,
1370 struct cfg80211_chan_def *chandef) 1372 struct cfg80211_chan_def *chandef)
1371{ 1373{
1372 struct ieee80211_sta_ht_cap *ht_cap; 1374 u32 control_freq;
1373 struct ieee80211_sta_vht_cap *vht_cap;
1374 u32 control_freq, width;
1375 1375
1376 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) 1376 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
1377 return -EINVAL; 1377 return -EINVAL;
@@ -1417,67 +1417,13 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
1417 info->attrs[NL80211_ATTR_CENTER_FREQ2]); 1417 info->attrs[NL80211_ATTR_CENTER_FREQ2]);
1418 } 1418 }
1419 1419
1420 ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap; 1420 if (!cfg80211_chandef_valid(chandef))
1421 vht_cap = &rdev->wiphy.bands[chandef->chan->band]->vht_cap;
1422
1423 if (!cfg80211_chan_def_valid(chandef))
1424 return -EINVAL; 1421 return -EINVAL;
1425 1422
1426 switch (chandef->width) { 1423 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
1427 case NL80211_CHAN_WIDTH_20: 1424 IEEE80211_CHAN_DISABLED))
1428 if (!ht_cap->ht_supported)
1429 return -EINVAL;
1430 case NL80211_CHAN_WIDTH_20_NOHT:
1431 width = 20;
1432 break;
1433 case NL80211_CHAN_WIDTH_40:
1434 width = 40;
1435 /* quick early regulatory check */
1436 if (chandef->center_freq1 < control_freq &&
1437 chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
1438 return -EINVAL;
1439 if (chandef->center_freq1 > control_freq &&
1440 chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
1441 return -EINVAL;
1442 if (!ht_cap->ht_supported)
1443 return -EINVAL;
1444 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
1445 ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
1446 return -EINVAL;
1447 break;
1448 case NL80211_CHAN_WIDTH_80:
1449 width = 80;
1450 if (!vht_cap->vht_supported)
1451 return -EINVAL;
1452 break;
1453 case NL80211_CHAN_WIDTH_80P80:
1454 width = 80;
1455 if (!vht_cap->vht_supported)
1456 return -EINVAL;
1457 if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
1458 return -EINVAL;
1459 break;
1460 case NL80211_CHAN_WIDTH_160:
1461 width = 160;
1462 if (!vht_cap->vht_supported)
1463 return -EINVAL;
1464 if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
1465 return -EINVAL;
1466 break;
1467 default:
1468 return -EINVAL;
1469 }
1470
1471 if (!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq1,
1472 width, IEEE80211_CHAN_DISABLED))
1473 return -EINVAL;
1474 if (chandef->center_freq2 &&
1475 !cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq2,
1476 width, IEEE80211_CHAN_DISABLED))
1477 return -EINVAL; 1425 return -EINVAL;
1478 1426
1479 /* TODO: missing regulatory check on bandwidth */
1480
1481 return 0; 1427 return 0;
1482} 1428}
1483 1429
@@ -1841,7 +1787,7 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
1841static int nl80211_send_chandef(struct sk_buff *msg, 1787static int nl80211_send_chandef(struct sk_buff *msg,
1842 struct cfg80211_chan_def *chandef) 1788 struct cfg80211_chan_def *chandef)
1843{ 1789{
1844 WARN_ON(!cfg80211_chan_def_valid(chandef)); 1790 WARN_ON(!cfg80211_chandef_valid(chandef));
1845 1791
1846 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, 1792 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
1847 chandef->chan->center_freq)) 1793 chandef->chan->center_freq))
@@ -2732,6 +2678,32 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
2732 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); 2678 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
2733 } 2679 }
2734 2680
2681 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
2682 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2683 return -EINVAL;
2684 params.p2p_ctwindow =
2685 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
2686 if (params.p2p_ctwindow > 127)
2687 return -EINVAL;
2688 if (params.p2p_ctwindow != 0 &&
2689 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
2690 return -EINVAL;
2691 }
2692
2693 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
2694 u8 tmp;
2695
2696 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2697 return -EINVAL;
2698 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
2699 if (tmp > 1)
2700 return -EINVAL;
2701 params.p2p_opp_ps = tmp;
2702 if (params.p2p_opp_ps != 0 &&
2703 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
2704 return -EINVAL;
2705 }
2706
2735 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { 2707 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
2736 err = nl80211_parse_chandef(rdev, info, &params.chandef); 2708 err = nl80211_parse_chandef(rdev, info, &params.chandef);
2737 if (err) 2709 if (err)
@@ -3698,6 +3670,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
3698 params.use_short_slot_time = -1; 3670 params.use_short_slot_time = -1;
3699 params.ap_isolate = -1; 3671 params.ap_isolate = -1;
3700 params.ht_opmode = -1; 3672 params.ht_opmode = -1;
3673 params.p2p_ctwindow = -1;
3674 params.p2p_opp_ps = -1;
3701 3675
3702 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) 3676 if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
3703 params.use_cts_prot = 3677 params.use_cts_prot =
@@ -3720,6 +3694,32 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
3720 params.ht_opmode = 3694 params.ht_opmode =
3721 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]); 3695 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
3722 3696
3697 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
3698 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
3699 return -EINVAL;
3700 params.p2p_ctwindow =
3701 nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
3702 if (params.p2p_ctwindow < 0)
3703 return -EINVAL;
3704 if (params.p2p_ctwindow != 0 &&
3705 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
3706 return -EINVAL;
3707 }
3708
3709 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
3710 u8 tmp;
3711
3712 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
3713 return -EINVAL;
3714 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
3715 if (tmp > 1)
3716 return -EINVAL;
3717 params.p2p_opp_ps = tmp;
3718 if (params.p2p_opp_ps &&
3719 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
3720 return -EINVAL;
3721 }
3722
3723 if (!rdev->ops->change_bss) 3723 if (!rdev->ops->change_bss)
3724 return -EOPNOTSUPP; 3724 return -EOPNOTSUPP;
3725 3725
@@ -4808,6 +4808,7 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
4808 struct cfg80211_internal_bss *intbss) 4808 struct cfg80211_internal_bss *intbss)
4809{ 4809{
4810 struct cfg80211_bss *res = &intbss->pub; 4810 struct cfg80211_bss *res = &intbss->pub;
4811 const struct cfg80211_bss_ies *ies;
4811 void *hdr; 4812 void *hdr;
4812 struct nlattr *bss; 4813 struct nlattr *bss;
4813 4814
@@ -4828,16 +4829,24 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
4828 if (!bss) 4829 if (!bss)
4829 goto nla_put_failure; 4830 goto nla_put_failure;
4830 if ((!is_zero_ether_addr(res->bssid) && 4831 if ((!is_zero_ether_addr(res->bssid) &&
4831 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)) || 4832 nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)))
4832 (res->information_elements && res->len_information_elements && 4833 goto nla_put_failure;
4833 nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, 4834
4834 res->len_information_elements, 4835 rcu_read_lock();
4835 res->information_elements)) || 4836 ies = rcu_dereference(res->ies);
4836 (res->beacon_ies && res->len_beacon_ies && 4837 if (ies && ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
4837 res->beacon_ies != res->information_elements && 4838 ies->len, ies->data)) {
4838 nla_put(msg, NL80211_BSS_BEACON_IES, 4839 rcu_read_unlock();
4839 res->len_beacon_ies, res->beacon_ies))) 4840 goto nla_put_failure;
4841 }
4842 ies = rcu_dereference(res->beacon_ies);
4843 if (ies && ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
4844 ies->len, ies->data)) {
4845 rcu_read_unlock();
4840 goto nla_put_failure; 4846 goto nla_put_failure;
4847 }
4848 rcu_read_unlock();
4849
4841 if (res->tsf && 4850 if (res->tsf &&
4842 nla_put_u64(msg, NL80211_BSS_TSF, res->tsf)) 4851 nla_put_u64(msg, NL80211_BSS_TSF, res->tsf))
4843 goto nla_put_failure; 4852 goto nla_put_failure;
@@ -5502,6 +5511,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
5502 return -EINVAL; 5511 return -EINVAL;
5503 if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && 5512 if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
5504 !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) 5513 !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
5514 return -EINVAL;
5505 5515
5506 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; 5516 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
5507 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; 5517 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
@@ -6529,14 +6539,13 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = {
6529}; 6539};
6530 6540
6531static int nl80211_set_cqm_txe(struct genl_info *info, 6541static int nl80211_set_cqm_txe(struct genl_info *info,
6532 u32 rate, u32 pkts, u32 intvl) 6542 u32 rate, u32 pkts, u32 intvl)
6533{ 6543{
6534 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 6544 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6535 struct wireless_dev *wdev; 6545 struct wireless_dev *wdev;
6536 struct net_device *dev = info->user_ptr[1]; 6546 struct net_device *dev = info->user_ptr[1];
6537 6547
6538 if ((rate < 0 || rate > 100) || 6548 if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
6539 (intvl < 0 || intvl > NL80211_CQM_TXE_MAX_INTVL))
6540 return -EINVAL; 6549 return -EINVAL;
6541 6550
6542 wdev = dev->ieee80211_ptr; 6551 wdev = dev->ieee80211_ptr;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index b75756b05af..6e5308998e3 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1796,7 +1796,7 @@ EXPORT_SYMBOL(regulatory_hint);
1796 */ 1796 */
1797void regulatory_hint_11d(struct wiphy *wiphy, 1797void regulatory_hint_11d(struct wiphy *wiphy,
1798 enum ieee80211_band band, 1798 enum ieee80211_band band,
1799 u8 *country_ie, 1799 const u8 *country_ie,
1800 u8 country_ie_len) 1800 u8 country_ie_len)
1801{ 1801{
1802 char alpha2[2]; 1802 char alpha2[2];
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index f023c8a31c6..4c0a32ffd53 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -81,7 +81,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
81 */ 81 */
82void regulatory_hint_11d(struct wiphy *wiphy, 82void regulatory_hint_11d(struct wiphy *wiphy,
83 enum ieee80211_band band, 83 enum ieee80211_band band,
84 u8 *country_ie, 84 const u8 *country_ie,
85 u8 country_ie_len); 85 u8 country_ie_len);
86 86
87/** 87/**
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 9596015975d..01592d7d478 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -23,18 +23,23 @@
23 23
24static void bss_release(struct kref *ref) 24static void bss_release(struct kref *ref)
25{ 25{
26 struct cfg80211_bss_ies *ies;
26 struct cfg80211_internal_bss *bss; 27 struct cfg80211_internal_bss *bss;
27 28
28 bss = container_of(ref, struct cfg80211_internal_bss, ref); 29 bss = container_of(ref, struct cfg80211_internal_bss, ref);
30
31 if (WARN_ON(atomic_read(&bss->hold)))
32 return;
33
29 if (bss->pub.free_priv) 34 if (bss->pub.free_priv)
30 bss->pub.free_priv(&bss->pub); 35 bss->pub.free_priv(&bss->pub);
31 36
32 if (bss->beacon_ies_allocated) 37 ies = (void *)rcu_access_pointer(bss->pub.beacon_ies);
33 kfree(bss->pub.beacon_ies); 38 if (ies)
34 if (bss->proberesp_ies_allocated) 39 kfree_rcu(ies, rcu_head);
35 kfree(bss->pub.proberesp_ies); 40 ies = (void *)rcu_access_pointer(bss->pub.proberesp_ies);
36 41 if (ies)
37 BUG_ON(atomic_read(&bss->hold)); 42 kfree_rcu(ies, rcu_head);
38 43
39 kfree(bss); 44 kfree(bss);
40} 45}
@@ -236,9 +241,8 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
236 struct cfg80211_internal_bss *bss; 241 struct cfg80211_internal_bss *bss;
237 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); 242 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
238 243
239 list_for_each_entry(bss, &dev->bss_list, list) { 244 list_for_each_entry(bss, &dev->bss_list, list)
240 bss->ts -= age_jiffies; 245 bss->ts -= age_jiffies;
241 }
242} 246}
243 247
244void cfg80211_bss_expire(struct cfg80211_registered_device *dev) 248void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
@@ -287,7 +291,7 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
287} 291}
288EXPORT_SYMBOL(cfg80211_find_vendor_ie); 292EXPORT_SYMBOL(cfg80211_find_vendor_ie);
289 293
290static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) 294static int cmp_ies(u8 num, const u8 *ies1, int len1, const u8 *ies2, int len2)
291{ 295{
292 const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); 296 const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
293 const u8 *ie2 = cfg80211_find_ie(num, ies2, len2); 297 const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);
@@ -307,10 +311,10 @@ static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
307 return memcmp(ie1 + 2, ie2 + 2, ie1[1]); 311 return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
308} 312}
309 313
310static bool is_bss(struct cfg80211_bss *a, 314static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
311 const u8 *bssid,
312 const u8 *ssid, size_t ssid_len) 315 const u8 *ssid, size_t ssid_len)
313{ 316{
317 const struct cfg80211_bss_ies *ies;
314 const u8 *ssidie; 318 const u8 *ssidie;
315 319
316 if (bssid && !ether_addr_equal(a->bssid, bssid)) 320 if (bssid && !ether_addr_equal(a->bssid, bssid))
@@ -319,9 +323,10 @@ static bool is_bss(struct cfg80211_bss *a,
319 if (!ssid) 323 if (!ssid)
320 return true; 324 return true;
321 325
322 ssidie = cfg80211_find_ie(WLAN_EID_SSID, 326 ies = rcu_access_pointer(a->ies);
323 a->information_elements, 327 if (!ies)
324 a->len_information_elements); 328 return false;
329 ssidie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
325 if (!ssidie) 330 if (!ssidie)
326 return false; 331 return false;
327 if (ssidie[1] != ssid_len) 332 if (ssidie[1] != ssid_len)
@@ -331,20 +336,21 @@ static bool is_bss(struct cfg80211_bss *a,
331 336
332static bool is_mesh_bss(struct cfg80211_bss *a) 337static bool is_mesh_bss(struct cfg80211_bss *a)
333{ 338{
339 const struct cfg80211_bss_ies *ies;
334 const u8 *ie; 340 const u8 *ie;
335 341
336 if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) 342 if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
337 return false; 343 return false;
338 344
339 ie = cfg80211_find_ie(WLAN_EID_MESH_ID, 345 ies = rcu_access_pointer(a->ies);
340 a->information_elements, 346 if (!ies)
341 a->len_information_elements); 347 return false;
348
349 ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len);
342 if (!ie) 350 if (!ie)
343 return false; 351 return false;
344 352
345 ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, 353 ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len);
346 a->information_elements,
347 a->len_information_elements);
348 if (!ie) 354 if (!ie)
349 return false; 355 return false;
350 356
@@ -355,14 +361,17 @@ static bool is_mesh(struct cfg80211_bss *a,
355 const u8 *meshid, size_t meshidlen, 361 const u8 *meshid, size_t meshidlen,
356 const u8 *meshcfg) 362 const u8 *meshcfg)
357{ 363{
364 const struct cfg80211_bss_ies *ies;
358 const u8 *ie; 365 const u8 *ie;
359 366
360 if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) 367 if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
361 return false; 368 return false;
362 369
363 ie = cfg80211_find_ie(WLAN_EID_MESH_ID, 370 ies = rcu_access_pointer(a->ies);
364 a->information_elements, 371 if (!ies)
365 a->len_information_elements); 372 return false;
373
374 ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len);
366 if (!ie) 375 if (!ie)
367 return false; 376 return false;
368 if (ie[1] != meshidlen) 377 if (ie[1] != meshidlen)
@@ -370,9 +379,7 @@ static bool is_mesh(struct cfg80211_bss *a,
370 if (memcmp(ie + 2, meshid, meshidlen)) 379 if (memcmp(ie + 2, meshid, meshidlen))
371 return false; 380 return false;
372 381
373 ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, 382 ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len);
374 a->information_elements,
375 a->len_information_elements);
376 if (!ie) 383 if (!ie)
377 return false; 384 return false;
378 if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) 385 if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
@@ -384,30 +391,33 @@ static bool is_mesh(struct cfg80211_bss *a,
384 * part in the same mesh. 391 * part in the same mesh.
385 */ 392 */
386 return memcmp(ie + 2, meshcfg, 393 return memcmp(ie + 2, meshcfg,
387 sizeof(struct ieee80211_meshconf_ie) - 2) == 0; 394 sizeof(struct ieee80211_meshconf_ie) - 2) == 0;
388} 395}
389 396
390static int cmp_bss_core(struct cfg80211_bss *a, 397static int cmp_bss_core(struct cfg80211_bss *a, struct cfg80211_bss *b)
391 struct cfg80211_bss *b)
392{ 398{
399 const struct cfg80211_bss_ies *a_ies, *b_ies;
393 int r; 400 int r;
394 401
395 if (a->channel != b->channel) 402 if (a->channel != b->channel)
396 return b->channel->center_freq - a->channel->center_freq; 403 return b->channel->center_freq - a->channel->center_freq;
397 404
398 if (is_mesh_bss(a) && is_mesh_bss(b)) { 405 if (is_mesh_bss(a) && is_mesh_bss(b)) {
406 a_ies = rcu_access_pointer(a->ies);
407 if (!a_ies)
408 return -1;
409 b_ies = rcu_access_pointer(b->ies);
410 if (!b_ies)
411 return 1;
412
399 r = cmp_ies(WLAN_EID_MESH_ID, 413 r = cmp_ies(WLAN_EID_MESH_ID,
400 a->information_elements, 414 a_ies->data, a_ies->len,
401 a->len_information_elements, 415 b_ies->data, b_ies->len);
402 b->information_elements,
403 b->len_information_elements);
404 if (r) 416 if (r)
405 return r; 417 return r;
406 return cmp_ies(WLAN_EID_MESH_CONFIG, 418 return cmp_ies(WLAN_EID_MESH_CONFIG,
407 a->information_elements, 419 a_ies->data, a_ies->len,
408 a->len_information_elements, 420 b_ies->data, b_ies->len);
409 b->information_elements,
410 b->len_information_elements);
411 } 421 }
412 422
413 /* 423 /*
@@ -420,22 +430,28 @@ static int cmp_bss_core(struct cfg80211_bss *a,
420static int cmp_bss(struct cfg80211_bss *a, 430static int cmp_bss(struct cfg80211_bss *a,
421 struct cfg80211_bss *b) 431 struct cfg80211_bss *b)
422{ 432{
433 const struct cfg80211_bss_ies *a_ies, *b_ies;
423 int r; 434 int r;
424 435
425 r = cmp_bss_core(a, b); 436 r = cmp_bss_core(a, b);
426 if (r) 437 if (r)
427 return r; 438 return r;
428 439
440 a_ies = rcu_access_pointer(a->ies);
441 if (!a_ies)
442 return -1;
443 b_ies = rcu_access_pointer(b->ies);
444 if (!b_ies)
445 return 1;
446
429 return cmp_ies(WLAN_EID_SSID, 447 return cmp_ies(WLAN_EID_SSID,
430 a->information_elements, 448 a_ies->data, a_ies->len,
431 a->len_information_elements, 449 b_ies->data, b_ies->len);
432 b->information_elements,
433 b->len_information_elements);
434} 450}
435 451
436static int cmp_hidden_bss(struct cfg80211_bss *a, 452static int cmp_hidden_bss(struct cfg80211_bss *a, struct cfg80211_bss *b)
437 struct cfg80211_bss *b)
438{ 453{
454 const struct cfg80211_bss_ies *a_ies, *b_ies;
439 const u8 *ie1; 455 const u8 *ie1;
440 const u8 *ie2; 456 const u8 *ie2;
441 int i; 457 int i;
@@ -445,17 +461,26 @@ static int cmp_hidden_bss(struct cfg80211_bss *a,
445 if (r) 461 if (r)
446 return r; 462 return r;
447 463
448 ie1 = cfg80211_find_ie(WLAN_EID_SSID, 464 a_ies = rcu_access_pointer(a->ies);
449 a->information_elements, 465 if (!a_ies)
450 a->len_information_elements); 466 return -1;
451 ie2 = cfg80211_find_ie(WLAN_EID_SSID, 467 b_ies = rcu_access_pointer(b->ies);
452 b->information_elements, 468 if (!b_ies)
453 b->len_information_elements); 469 return 1;
470
471 ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len);
472 ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len);
454 473
455 /* Key comparator must use same algorithm in any rb-tree 474 /*
475 * Key comparator must use same algorithm in any rb-tree
456 * search function (order is important), otherwise ordering 476 * search function (order is important), otherwise ordering
457 * of items in the tree is broken and search gives incorrect 477 * of items in the tree is broken and search gives incorrect
458 * results. This code uses same order as cmp_ies() does. */ 478 * results. This code uses same order as cmp_ies() does.
479 *
480 * Note that due to the differring behaviour with hidden SSIDs
481 * this function only works when "b" is the tree element and
482 * "a" is the key we're looking for.
483 */
459 484
460 /* sort missing IE before (left of) present IE */ 485 /* sort missing IE before (left of) present IE */
461 if (!ie1) 486 if (!ie1)
@@ -471,10 +496,14 @@ static int cmp_hidden_bss(struct cfg80211_bss *a,
471 if (ie1[1] != ie2[1]) 496 if (ie1[1] != ie2[1])
472 return ie2[1] - ie1[1]; 497 return ie2[1] - ie1[1];
473 498
474 /* zeroed SSID ie is another indication of a hidden bss */ 499 /*
500 * zeroed SSID ie is another indication of a hidden bss;
501 * if it isn't zeroed just return the regular sort value
502 * to find the next candidate
503 */
475 for (i = 0; i < ie2[1]; i++) 504 for (i = 0; i < ie2[1]; i++)
476 if (ie2[i + 2]) 505 if (ie2[i + 2])
477 return -1; 506 return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
478 507
479 return 0; 508 return 0;
480} 509}
@@ -600,7 +629,7 @@ rb_find_bss(struct cfg80211_registered_device *dev,
600 629
601static struct cfg80211_internal_bss * 630static struct cfg80211_internal_bss *
602rb_find_hidden_bss(struct cfg80211_registered_device *dev, 631rb_find_hidden_bss(struct cfg80211_registered_device *dev,
603 struct cfg80211_internal_bss *res) 632 struct cfg80211_internal_bss *res)
604{ 633{
605 struct rb_node *n = dev->bss_tree.rb_node; 634 struct rb_node *n = dev->bss_tree.rb_node;
606 struct cfg80211_internal_bss *bss; 635 struct cfg80211_internal_bss *bss;
@@ -623,127 +652,86 @@ rb_find_hidden_bss(struct cfg80211_registered_device *dev,
623 652
624static void 653static void
625copy_hidden_ies(struct cfg80211_internal_bss *res, 654copy_hidden_ies(struct cfg80211_internal_bss *res,
626 struct cfg80211_internal_bss *hidden) 655 struct cfg80211_internal_bss *hidden)
627{ 656{
628 if (unlikely(res->pub.beacon_ies)) 657 const struct cfg80211_bss_ies *ies;
629 return; 658
630 if (WARN_ON(!hidden->pub.beacon_ies)) 659 if (rcu_access_pointer(res->pub.beacon_ies))
631 return; 660 return;
632 661
633 res->pub.beacon_ies = kmalloc(hidden->pub.len_beacon_ies, GFP_ATOMIC); 662 ies = rcu_access_pointer(hidden->pub.beacon_ies);
634 if (unlikely(!res->pub.beacon_ies)) 663 if (WARN_ON(!ies))
635 return; 664 return;
636 665
637 res->beacon_ies_allocated = true; 666 ies = kmemdup(ies, sizeof(*ies) + ies->len, GFP_ATOMIC);
638 res->pub.len_beacon_ies = hidden->pub.len_beacon_ies; 667 if (unlikely(!ies))
639 memcpy(res->pub.beacon_ies, hidden->pub.beacon_ies, 668 return;
640 res->pub.len_beacon_ies); 669 rcu_assign_pointer(res->pub.beacon_ies, ies);
641} 670}
642 671
643static struct cfg80211_internal_bss * 672static struct cfg80211_internal_bss *
644cfg80211_bss_update(struct cfg80211_registered_device *dev, 673cfg80211_bss_update(struct cfg80211_registered_device *dev,
645 struct cfg80211_internal_bss *res) 674 struct cfg80211_internal_bss *tmp)
646{ 675{
647 struct cfg80211_internal_bss *found = NULL; 676 struct cfg80211_internal_bss *found = NULL;
648 677
649 /* 678 if (WARN_ON(!tmp->pub.channel))
650 * The reference to "res" is donated to this function.
651 */
652
653 if (WARN_ON(!res->pub.channel)) {
654 kref_put(&res->ref, bss_release);
655 return NULL; 679 return NULL;
656 }
657 680
658 res->ts = jiffies; 681 tmp->ts = jiffies;
659 682
660 spin_lock_bh(&dev->bss_lock); 683 spin_lock_bh(&dev->bss_lock);
661 684
662 found = rb_find_bss(dev, res); 685 if (WARN_ON(!rcu_access_pointer(tmp->pub.ies))) {
686 spin_unlock_bh(&dev->bss_lock);
687 return NULL;
688 }
689
690 found = rb_find_bss(dev, tmp);
663 691
664 if (found) { 692 if (found) {
665 found->pub.beacon_interval = res->pub.beacon_interval; 693 found->pub.beacon_interval = tmp->pub.beacon_interval;
666 found->pub.tsf = res->pub.tsf; 694 found->pub.tsf = tmp->pub.tsf;
667 found->pub.signal = res->pub.signal; 695 found->pub.signal = tmp->pub.signal;
668 found->pub.capability = res->pub.capability; 696 found->pub.capability = tmp->pub.capability;
669 found->ts = res->ts; 697 found->ts = tmp->ts;
670 698
671 /* Update IEs */ 699 /* Update IEs */
672 if (res->pub.proberesp_ies) { 700 if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
673 size_t used = dev->wiphy.bss_priv_size + sizeof(*res); 701 const struct cfg80211_bss_ies *old;
674 size_t ielen = res->pub.len_proberesp_ies;
675
676 if (found->pub.proberesp_ies &&
677 !found->proberesp_ies_allocated &&
678 ksize(found) >= used + ielen) {
679 memcpy(found->pub.proberesp_ies,
680 res->pub.proberesp_ies, ielen);
681 found->pub.len_proberesp_ies = ielen;
682 } else {
683 u8 *ies = found->pub.proberesp_ies;
684
685 if (found->proberesp_ies_allocated)
686 ies = krealloc(ies, ielen, GFP_ATOMIC);
687 else
688 ies = kmalloc(ielen, GFP_ATOMIC);
689
690 if (ies) {
691 memcpy(ies, res->pub.proberesp_ies,
692 ielen);
693 found->proberesp_ies_allocated = true;
694 found->pub.proberesp_ies = ies;
695 found->pub.len_proberesp_ies = ielen;
696 }
697 }
698 702
703 old = rcu_access_pointer(found->pub.proberesp_ies);
704
705 rcu_assign_pointer(found->pub.proberesp_ies,
706 tmp->pub.proberesp_ies);
699 /* Override possible earlier Beacon frame IEs */ 707 /* Override possible earlier Beacon frame IEs */
700 found->pub.information_elements = 708 rcu_assign_pointer(found->pub.ies,
701 found->pub.proberesp_ies; 709 tmp->pub.proberesp_ies);
702 found->pub.len_information_elements = 710 if (old)
703 found->pub.len_proberesp_ies; 711 kfree_rcu((struct cfg80211_bss_ies *)old,
704 } 712 rcu_head);
705 if (res->pub.beacon_ies) { 713 } else if (rcu_access_pointer(tmp->pub.beacon_ies)) {
706 size_t used = dev->wiphy.bss_priv_size + sizeof(*res); 714 const struct cfg80211_bss_ies *old, *ies;
707 size_t ielen = res->pub.len_beacon_ies; 715
708 bool information_elements_is_beacon_ies = 716 old = rcu_access_pointer(found->pub.beacon_ies);
709 (found->pub.information_elements == 717 ies = rcu_access_pointer(found->pub.ies);
710 found->pub.beacon_ies); 718
711 719 rcu_assign_pointer(found->pub.beacon_ies,
712 if (found->pub.beacon_ies && 720 tmp->pub.beacon_ies);
713 !found->beacon_ies_allocated &&
714 ksize(found) >= used + ielen) {
715 memcpy(found->pub.beacon_ies,
716 res->pub.beacon_ies, ielen);
717 found->pub.len_beacon_ies = ielen;
718 } else {
719 u8 *ies = found->pub.beacon_ies;
720
721 if (found->beacon_ies_allocated)
722 ies = krealloc(ies, ielen, GFP_ATOMIC);
723 else
724 ies = kmalloc(ielen, GFP_ATOMIC);
725
726 if (ies) {
727 memcpy(ies, res->pub.beacon_ies,
728 ielen);
729 found->beacon_ies_allocated = true;
730 found->pub.beacon_ies = ies;
731 found->pub.len_beacon_ies = ielen;
732 }
733 }
734 721
735 /* Override IEs if they were from a beacon before */ 722 /* Override IEs if they were from a beacon before */
736 if (information_elements_is_beacon_ies) { 723 if (old == ies)
737 found->pub.information_elements = 724 rcu_assign_pointer(found->pub.ies,
738 found->pub.beacon_ies; 725 tmp->pub.beacon_ies);
739 found->pub.len_information_elements =
740 found->pub.len_beacon_ies;
741 }
742 }
743 726
744 kref_put(&res->ref, bss_release); 727 if (old)
728 kfree_rcu((struct cfg80211_bss_ies *)old,
729 rcu_head);
730 }
745 } else { 731 } else {
732 struct cfg80211_internal_bss *new;
746 struct cfg80211_internal_bss *hidden; 733 struct cfg80211_internal_bss *hidden;
734 struct cfg80211_bss_ies *ies;
747 735
748 /* First check if the beacon is a probe response from 736 /* First check if the beacon is a probe response from
749 * a hidden bss. If so, copy beacon ies (with nullified 737 * a hidden bss. If so, copy beacon ies (with nullified
@@ -754,14 +742,32 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
754 /* TODO: The code is not trying to update existing probe 742 /* TODO: The code is not trying to update existing probe
755 * response bss entries when beacon ies are 743 * response bss entries when beacon ies are
756 * getting changed. */ 744 * getting changed. */
757 hidden = rb_find_hidden_bss(dev, res); 745 hidden = rb_find_hidden_bss(dev, tmp);
758 if (hidden) 746 if (hidden)
759 copy_hidden_ies(res, hidden); 747 copy_hidden_ies(tmp, hidden);
760 748
761 /* this "consumes" the reference */ 749 /*
762 list_add_tail(&res->list, &dev->bss_list); 750 * create a copy -- the "res" variable that is passed in
763 rb_insert_bss(dev, res); 751 * is allocated on the stack since it's not needed in the
764 found = res; 752 * more common case of an update
753 */
754 new = kzalloc(sizeof(*new) + dev->wiphy.bss_priv_size,
755 GFP_ATOMIC);
756 if (!new) {
757 ies = (void *)rcu_dereference(tmp->pub.beacon_ies);
758 if (ies)
759 kfree_rcu(ies, rcu_head);
760 ies = (void *)rcu_dereference(tmp->pub.proberesp_ies);
761 if (ies)
762 kfree_rcu(ies, rcu_head);
763 spin_unlock_bh(&dev->bss_lock);
764 return NULL;
765 }
766 memcpy(new, tmp, sizeof(*new));
767 kref_init(&new->ref);
768 list_add_tail(&new->list, &dev->bss_list);
769 rb_insert_bss(dev, new);
770 found = new;
765 } 771 }
766 772
767 dev->bss_generation++; 773 dev->bss_generation++;
@@ -810,14 +816,12 @@ cfg80211_inform_bss(struct wiphy *wiphy,
810 u16 beacon_interval, const u8 *ie, size_t ielen, 816 u16 beacon_interval, const u8 *ie, size_t ielen,
811 s32 signal, gfp_t gfp) 817 s32 signal, gfp_t gfp)
812{ 818{
813 struct cfg80211_internal_bss *res; 819 struct cfg80211_bss_ies *ies;
814 size_t privsz; 820 struct cfg80211_internal_bss tmp = {}, *res;
815 821
816 if (WARN_ON(!wiphy)) 822 if (WARN_ON(!wiphy))
817 return NULL; 823 return NULL;
818 824
819 privsz = wiphy->bss_priv_size;
820
821 if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && 825 if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
822 (signal < 0 || signal > 100))) 826 (signal < 0 || signal > 100)))
823 return NULL; 827 return NULL;
@@ -826,36 +830,33 @@ cfg80211_inform_bss(struct wiphy *wiphy,
826 if (!channel) 830 if (!channel)
827 return NULL; 831 return NULL;
828 832
829 res = kzalloc(sizeof(*res) + privsz + ielen, gfp); 833 memcpy(tmp.pub.bssid, bssid, ETH_ALEN);
830 if (!res) 834 tmp.pub.channel = channel;
831 return NULL; 835 tmp.pub.signal = signal;
832 836 tmp.pub.tsf = tsf;
833 memcpy(res->pub.bssid, bssid, ETH_ALEN); 837 tmp.pub.beacon_interval = beacon_interval;
834 res->pub.channel = channel; 838 tmp.pub.capability = capability;
835 res->pub.signal = signal;
836 res->pub.tsf = tsf;
837 res->pub.beacon_interval = beacon_interval;
838 res->pub.capability = capability;
839 /* 839 /*
840 * Since we do not know here whether the IEs are from a Beacon or Probe 840 * Since we do not know here whether the IEs are from a Beacon or Probe
841 * Response frame, we need to pick one of the options and only use it 841 * Response frame, we need to pick one of the options and only use it
842 * with the driver that does not provide the full Beacon/Probe Response 842 * with the driver that does not provide the full Beacon/Probe Response
843 * frame. Use Beacon frame pointer to avoid indicating that this should 843 * frame. Use Beacon frame pointer to avoid indicating that this should
844 * override the information_elements pointer should we have received an 844 * override the iies pointer should we have received an earlier
845 * earlier indication of Probe Response data. 845 * indication of Probe Response data.
846 * 846 *
847 * The initial buffer for the IEs is allocated with the BSS entry and 847 * The initial buffer for the IEs is allocated with the BSS entry and
848 * is located after the private area. 848 * is located after the private area.
849 */ 849 */
850 res->pub.beacon_ies = (u8 *)res + sizeof(*res) + privsz; 850 ies = kmalloc(sizeof(*ies) + ielen, gfp);
851 memcpy(res->pub.beacon_ies, ie, ielen); 851 if (!ies)
852 res->pub.len_beacon_ies = ielen; 852 return NULL;
853 res->pub.information_elements = res->pub.beacon_ies; 853 ies->len = ielen;
854 res->pub.len_information_elements = res->pub.len_beacon_ies; 854 memcpy(ies->data, ie, ielen);
855 855
856 kref_init(&res->ref); 856 rcu_assign_pointer(tmp.pub.beacon_ies, ies);
857 rcu_assign_pointer(tmp.pub.ies, ies);
857 858
858 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res); 859 res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp);
859 if (!res) 860 if (!res)
860 return NULL; 861 return NULL;
861 862
@@ -874,10 +875,10 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
874 struct ieee80211_mgmt *mgmt, size_t len, 875 struct ieee80211_mgmt *mgmt, size_t len,
875 s32 signal, gfp_t gfp) 876 s32 signal, gfp_t gfp)
876{ 877{
877 struct cfg80211_internal_bss *res; 878 struct cfg80211_internal_bss tmp = {}, *res;
879 struct cfg80211_bss_ies *ies;
878 size_t ielen = len - offsetof(struct ieee80211_mgmt, 880 size_t ielen = len - offsetof(struct ieee80211_mgmt,
879 u.probe_resp.variable); 881 u.probe_resp.variable);
880 size_t privsz;
881 882
882 BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != 883 BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
883 offsetof(struct ieee80211_mgmt, u.beacon.variable)); 884 offsetof(struct ieee80211_mgmt, u.beacon.variable));
@@ -897,45 +898,31 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
897 if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable))) 898 if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
898 return NULL; 899 return NULL;
899 900
900 privsz = wiphy->bss_priv_size;
901
902 channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, 901 channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
903 ielen, channel); 902 ielen, channel);
904 if (!channel) 903 if (!channel)
905 return NULL; 904 return NULL;
906 905
907 res = kzalloc(sizeof(*res) + privsz + ielen, gfp); 906 ies = kmalloc(sizeof(*ies) + ielen, gfp);
908 if (!res) 907 if (!ies)
909 return NULL; 908 return NULL;
909 ies->len = ielen;
910 memcpy(ies->data, mgmt->u.probe_resp.variable, ielen);
910 911
911 memcpy(res->pub.bssid, mgmt->bssid, ETH_ALEN); 912 if (ieee80211_is_probe_resp(mgmt->frame_control))
912 res->pub.channel = channel; 913 rcu_assign_pointer(tmp.pub.proberesp_ies, ies);
913 res->pub.signal = signal; 914 else
914 res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); 915 rcu_assign_pointer(tmp.pub.beacon_ies, ies);
915 res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 916 rcu_assign_pointer(tmp.pub.ies, ies);
916 res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); 917
917 /* 918 memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN);
918 * The initial buffer for the IEs is allocated with the BSS entry and 919 tmp.pub.channel = channel;
919 * is located after the private area. 920 tmp.pub.signal = signal;
920 */ 921 tmp.pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
921 if (ieee80211_is_probe_resp(mgmt->frame_control)) { 922 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
922 res->pub.proberesp_ies = (u8 *) res + sizeof(*res) + privsz; 923 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
923 memcpy(res->pub.proberesp_ies, mgmt->u.probe_resp.variable, 924
924 ielen); 925 res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp);
925 res->pub.len_proberesp_ies = ielen;
926 res->pub.information_elements = res->pub.proberesp_ies;
927 res->pub.len_information_elements = res->pub.len_proberesp_ies;
928 } else {
929 res->pub.beacon_ies = (u8 *) res + sizeof(*res) + privsz;
930 memcpy(res->pub.beacon_ies, mgmt->u.beacon.variable, ielen);
931 res->pub.len_beacon_ies = ielen;
932 res->pub.information_elements = res->pub.beacon_ies;
933 res->pub.len_information_elements = res->pub.len_beacon_ies;
934 }
935
936 kref_init(&res->ref);
937
938 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
939 if (!res) 926 if (!res)
940 return NULL; 927 return NULL;
941 928
@@ -1127,22 +1114,21 @@ int cfg80211_wext_siwscan(struct net_device *dev,
1127EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); 1114EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
1128 1115
1129static void ieee80211_scan_add_ies(struct iw_request_info *info, 1116static void ieee80211_scan_add_ies(struct iw_request_info *info,
1130 struct cfg80211_bss *bss, 1117 const struct cfg80211_bss_ies *ies,
1131 char **current_ev, char *end_buf) 1118 char **current_ev, char *end_buf)
1132{ 1119{
1133 u8 *pos, *end, *next; 1120 const u8 *pos, *end, *next;
1134 struct iw_event iwe; 1121 struct iw_event iwe;
1135 1122
1136 if (!bss->information_elements || 1123 if (!ies)
1137 !bss->len_information_elements)
1138 return; 1124 return;
1139 1125
1140 /* 1126 /*
1141 * If needed, fragment the IEs buffer (at IE boundaries) into short 1127 * If needed, fragment the IEs buffer (at IE boundaries) into short
1142 * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. 1128 * enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
1143 */ 1129 */
1144 pos = bss->information_elements; 1130 pos = ies->data;
1145 end = pos + bss->len_information_elements; 1131 end = pos + ies->len;
1146 1132
1147 while (end - pos > IW_GENERIC_IE_MAX) { 1133 while (end - pos > IW_GENERIC_IE_MAX) {
1148 next = pos + 2 + pos[1]; 1134 next = pos + 2 + pos[1];
@@ -1153,7 +1139,8 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info,
1153 iwe.cmd = IWEVGENIE; 1139 iwe.cmd = IWEVGENIE;
1154 iwe.u.data.length = next - pos; 1140 iwe.u.data.length = next - pos;
1155 *current_ev = iwe_stream_add_point(info, *current_ev, 1141 *current_ev = iwe_stream_add_point(info, *current_ev,
1156 end_buf, &iwe, pos); 1142 end_buf, &iwe,
1143 (void *)pos);
1157 1144
1158 pos = next; 1145 pos = next;
1159 } 1146 }
@@ -1163,7 +1150,8 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info,
1163 iwe.cmd = IWEVGENIE; 1150 iwe.cmd = IWEVGENIE;
1164 iwe.u.data.length = end - pos; 1151 iwe.u.data.length = end - pos;
1165 *current_ev = iwe_stream_add_point(info, *current_ev, 1152 *current_ev = iwe_stream_add_point(info, *current_ev,
1166 end_buf, &iwe, pos); 1153 end_buf, &iwe,
1154 (void *)pos);
1167 } 1155 }
1168} 1156}
1169 1157
@@ -1182,10 +1170,11 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
1182 struct cfg80211_internal_bss *bss, char *current_ev, 1170 struct cfg80211_internal_bss *bss, char *current_ev,
1183 char *end_buf) 1171 char *end_buf)
1184{ 1172{
1173 const struct cfg80211_bss_ies *ies;
1185 struct iw_event iwe; 1174 struct iw_event iwe;
1175 const u8 *ie;
1186 u8 *buf, *cfg, *p; 1176 u8 *buf, *cfg, *p;
1187 u8 *ie = bss->pub.information_elements; 1177 int rem, i, sig;
1188 int rem = bss->pub.len_information_elements, i, sig;
1189 bool ismesh = false; 1178 bool ismesh = false;
1190 1179
1191 memset(&iwe, 0, sizeof(iwe)); 1180 memset(&iwe, 0, sizeof(iwe));
@@ -1250,7 +1239,17 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
1250 current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1239 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1251 &iwe, ""); 1240 &iwe, "");
1252 1241
1253 while (rem >= 2) { 1242 rcu_read_lock();
1243 ies = rcu_dereference(bss->pub.ies);
1244 if (ies) {
1245 rem = ies->len;
1246 ie = ies->data;
1247 } else {
1248 rem = 0;
1249 ie = NULL;
1250 }
1251
1252 while (ies && rem >= 2) {
1254 /* invalid data */ 1253 /* invalid data */
1255 if (ie[1] > rem - 2) 1254 if (ie[1] > rem - 2)
1256 break; 1255 break;
@@ -1262,7 +1261,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
1262 iwe.u.data.length = ie[1]; 1261 iwe.u.data.length = ie[1];
1263 iwe.u.data.flags = 1; 1262 iwe.u.data.flags = 1;
1264 current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1263 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1265 &iwe, ie + 2); 1264 &iwe, (u8 *)ie + 2);
1266 break; 1265 break;
1267 case WLAN_EID_MESH_ID: 1266 case WLAN_EID_MESH_ID:
1268 memset(&iwe, 0, sizeof(iwe)); 1267 memset(&iwe, 0, sizeof(iwe));
@@ -1270,7 +1269,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
1270 iwe.u.data.length = ie[1]; 1269 iwe.u.data.length = ie[1];
1271 iwe.u.data.flags = 1; 1270 iwe.u.data.flags = 1;
1272 current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1271 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1273 &iwe, ie + 2); 1272 &iwe, (u8 *)ie + 2);
1274 break; 1273 break;
1275 case WLAN_EID_MESH_CONFIG: 1274 case WLAN_EID_MESH_CONFIG:
1276 ismesh = true; 1275 ismesh = true;
@@ -1279,7 +1278,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
1279 buf = kmalloc(50, GFP_ATOMIC); 1278 buf = kmalloc(50, GFP_ATOMIC);
1280 if (!buf) 1279 if (!buf)
1281 break; 1280 break;
1282 cfg = ie + 2; 1281 cfg = (u8 *)ie + 2;
1283 memset(&iwe, 0, sizeof(iwe)); 1282 memset(&iwe, 0, sizeof(iwe));
1284 iwe.cmd = IWEVCUSTOM; 1283 iwe.cmd = IWEVCUSTOM;
1285 sprintf(buf, "Mesh Network Path Selection Protocol ID: " 1284 sprintf(buf, "Mesh Network Path Selection Protocol ID: "
@@ -1377,7 +1376,8 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
1377 kfree(buf); 1376 kfree(buf);
1378 } 1377 }
1379 1378
1380 ieee80211_scan_add_ies(info, &bss->pub, &current_ev, end_buf); 1379 ieee80211_scan_add_ies(info, ies, &current_ev, end_buf);
1380 rcu_read_unlock();
1381 1381
1382 return current_ev; 1382 return current_ev;
1383} 1383}
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index c7490027237..f2431e41a37 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -417,7 +417,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
417 struct cfg80211_bss *bss) 417 struct cfg80211_bss *bss)
418{ 418{
419 struct wireless_dev *wdev = dev->ieee80211_ptr; 419 struct wireless_dev *wdev = dev->ieee80211_ptr;
420 u8 *country_ie; 420 const u8 *country_ie;
421#ifdef CONFIG_CFG80211_WEXT 421#ifdef CONFIG_CFG80211_WEXT
422 union iwreq_data wrqu; 422 union iwreq_data wrqu;
423#endif 423#endif
@@ -501,7 +501,15 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
501 wdev->sme_state = CFG80211_SME_CONNECTED; 501 wdev->sme_state = CFG80211_SME_CONNECTED;
502 cfg80211_upload_connect_keys(wdev); 502 cfg80211_upload_connect_keys(wdev);
503 503
504 country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); 504 rcu_read_lock();
505 country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
506 if (!country_ie) {
507 rcu_read_unlock();
508 return;
509 }
510
511 country_ie = kmemdup(country_ie, 2 + country_ie[1], GFP_ATOMIC);
512 rcu_read_unlock();
505 513
506 if (!country_ie) 514 if (!country_ie)
507 return; 515 return;
@@ -515,6 +523,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
515 bss->channel->band, 523 bss->channel->band,
516 country_ie + 2, 524 country_ie + 2,
517 country_ie[1]); 525 country_ie[1]);
526 kfree(country_ie);
518} 527}
519 528
520void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 529void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 3cce6e48621..16d76a807c2 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -688,10 +688,13 @@ EXPORT_SYMBOL(cfg80211_classify8021d);
688 688
689const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie) 689const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
690{ 690{
691 if (bss->information_elements == NULL) 691 const struct cfg80211_bss_ies *ies;
692
693 ies = rcu_dereference(bss->ies);
694 if (!ies)
692 return NULL; 695 return NULL;
693 return cfg80211_find_ie(ie, bss->information_elements, 696
694 bss->len_information_elements); 697 return cfg80211_find_ie(ie, ies->data, ies->len);
695} 698}
696EXPORT_SYMBOL(ieee80211_bss_get_ie); 699EXPORT_SYMBOL(ieee80211_bss_get_ie);
697 700
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 873af63187c..fb9622f6d99 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -242,13 +242,17 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
242 242
243 wdev_lock(wdev); 243 wdev_lock(wdev);
244 if (wdev->current_bss) { 244 if (wdev->current_bss) {
245 const u8 *ie = ieee80211_bss_get_ie(&wdev->current_bss->pub, 245 const u8 *ie;
246 WLAN_EID_SSID); 246
247 rcu_read_lock();
248 ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
249 WLAN_EID_SSID);
247 if (ie) { 250 if (ie) {
248 data->flags = 1; 251 data->flags = 1;
249 data->length = ie[1]; 252 data->length = ie[1];
250 memcpy(ssid, ie + 2, data->length); 253 memcpy(ssid, ie + 2, data->length);
251 } 254 }
255 rcu_read_unlock();
252 } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { 256 } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
253 data->flags = 1; 257 data->flags = 1;
254 data->length = wdev->wext.connect.ssid_len; 258 data->length = wdev->wext.connect.ssid_len;