aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
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 /net/mac80211
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
Diffstat (limited to 'net/mac80211')
-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
15 files changed, 580 insertions, 171 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4965aa6424ec..5c61677487cf 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 89281d24b094..49a1c70bbd70 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 5c0d5a6946c1..42d0d0267730 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 5331662489f7..40c36d5d7377 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 f5e4c1f24bf2..1b087fff93e7 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 ca52dfdd5375..4b274e9c91a5 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 0f40086cce18..aa8d1e437385 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 d2a4f78b4b0f..09556303c7e1 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 fb1d4aa65e8c..9f9c453bc45d 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 825f33cf7bbc..db343fa8033c 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 f3340279aba3..f7176ac5a535 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 6835cea4e402..1489bca9ea97 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 ab63237107c8..ab50285fcbab 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 d287a4f2c01b..e9eadc40c09c 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 08132ff98155..f11e8c540db4 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;