aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/Makefile3
-rw-r--r--net/wireless/chan.c89
-rw-r--r--net/wireless/core.c21
-rw-r--r--net/wireless/core.h14
-rw-r--r--net/wireless/ibss.c61
-rw-r--r--net/wireless/mlme.c17
-rw-r--r--net/wireless/nl80211.c88
-rw-r--r--net/wireless/reg.c5
-rw-r--r--net/wireless/scan.c31
-rw-r--r--net/wireless/sme.c104
-rw-r--r--net/wireless/util.c16
-rw-r--r--net/wireless/wext-compat.c55
-rw-r--r--net/wireless/wext-compat.h3
-rw-r--r--net/wireless/wext-sme.c83
14 files changed, 403 insertions, 187 deletions
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index d74cc77fa57a..3ecaa9179977 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -5,7 +5,8 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
5obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o 5obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o 6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
7 7
8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o sme.o 8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
9cfg80211-y += mlme.o ibss.o sme.o chan.o
9cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o 10cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
10cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o 11cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o
11 12
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
new file mode 100644
index 000000000000..a46ac6c9b365
--- /dev/null
+++ b/net/wireless/chan.c
@@ -0,0 +1,89 @@
1/*
2 * This file contains helper code to handle channel
3 * settings and keeping track of what is possible at
4 * any point in time.
5 *
6 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
7 */
8
9#include <net/cfg80211.h>
10#include "core.h"
11
12struct ieee80211_channel *
13rdev_fixed_channel(struct cfg80211_registered_device *rdev,
14 struct wireless_dev *for_wdev)
15{
16 struct wireless_dev *wdev;
17 struct ieee80211_channel *result = NULL;
18
19 WARN_ON(!mutex_is_locked(&rdev->devlist_mtx));
20
21 list_for_each_entry(wdev, &rdev->netdev_list, list) {
22 if (wdev == for_wdev)
23 continue;
24
25 /*
26 * Lock manually to tell lockdep about allowed
27 * nesting here if for_wdev->mtx is held already.
28 * This is ok as it's all under the rdev devlist
29 * mutex and as such can only be done once at any
30 * given time.
31 */
32 mutex_lock_nested(&wdev->mtx, SINGLE_DEPTH_NESTING);
33 if (wdev->current_bss)
34 result = wdev->current_bss->pub.channel;
35 wdev_unlock(wdev);
36
37 if (result)
38 break;
39 }
40
41 return result;
42}
43
44int rdev_set_freq(struct cfg80211_registered_device *rdev,
45 struct wireless_dev *for_wdev,
46 int freq, enum nl80211_channel_type channel_type)
47{
48 struct ieee80211_channel *chan;
49 struct ieee80211_sta_ht_cap *ht_cap;
50 int result;
51
52 if (rdev_fixed_channel(rdev, for_wdev))
53 return -EBUSY;
54
55 if (!rdev->ops->set_channel)
56 return -EOPNOTSUPP;
57
58 chan = ieee80211_get_channel(&rdev->wiphy, freq);
59
60 /* Primary channel not allowed */
61 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
62 return -EINVAL;
63
64 if (channel_type == NL80211_CHAN_HT40MINUS &&
65 chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
66 return -EINVAL;
67 else if (channel_type == NL80211_CHAN_HT40PLUS &&
68 chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
69 return -EINVAL;
70
71 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
72
73 if (channel_type != NL80211_CHAN_NO_HT) {
74 if (!ht_cap->ht_supported)
75 return -EINVAL;
76
77 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
78 ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
79 return -EINVAL;
80 }
81
82 result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
83 if (result)
84 return result;
85
86 rdev->channel = chan;
87
88 return 0;
89}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 1e189306560d..bc99e4ec7463 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -32,6 +32,7 @@ MODULE_DESCRIPTION("wireless configuration support");
32 * only read the list, and that can happen quite 32 * only read the list, and that can happen quite
33 * often because we need to do it for each command */ 33 * often because we need to do it for each command */
34LIST_HEAD(cfg80211_rdev_list); 34LIST_HEAD(cfg80211_rdev_list);
35int cfg80211_rdev_list_generation;
35 36
36/* 37/*
37 * This is used to protect the cfg80211_rdev_list 38 * This is used to protect the cfg80211_rdev_list
@@ -411,6 +412,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
411 rdev->wiphy.dev.class = &ieee80211_class; 412 rdev->wiphy.dev.class = &ieee80211_class;
412 rdev->wiphy.dev.platform_data = rdev; 413 rdev->wiphy.dev.platform_data = rdev;
413 414
415 rdev->wiphy.ps_default = CONFIG_CFG80211_DEFAULT_PS_VALUE;
416
414 wiphy_net_set(&rdev->wiphy, &init_net); 417 wiphy_net_set(&rdev->wiphy, &init_net);
415 418
416 rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block; 419 rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block;
@@ -511,6 +514,7 @@ int wiphy_register(struct wiphy *wiphy)
511 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); 514 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
512 515
513 list_add(&rdev->list, &cfg80211_rdev_list); 516 list_add(&rdev->list, &cfg80211_rdev_list);
517 cfg80211_rdev_list_generation++;
514 518
515 mutex_unlock(&cfg80211_mutex); 519 mutex_unlock(&cfg80211_mutex);
516 520
@@ -593,13 +597,14 @@ void wiphy_unregister(struct wiphy *wiphy)
593 reg_device_remove(wiphy); 597 reg_device_remove(wiphy);
594 598
595 list_del(&rdev->list); 599 list_del(&rdev->list);
600 cfg80211_rdev_list_generation++;
596 device_del(&rdev->wiphy.dev); 601 device_del(&rdev->wiphy.dev);
597 debugfs_remove(rdev->wiphy.debugfsdir); 602 debugfs_remove(rdev->wiphy.debugfsdir);
598 603
599 mutex_unlock(&cfg80211_mutex); 604 mutex_unlock(&cfg80211_mutex);
600 605
606 flush_work(&rdev->scan_done_wk);
601 cancel_work_sync(&rdev->conn_work); 607 cancel_work_sync(&rdev->conn_work);
602 cancel_work_sync(&rdev->scan_done_wk);
603 kfree(rdev->scan_req); 608 kfree(rdev->scan_req);
604 flush_work(&rdev->event_work); 609 flush_work(&rdev->event_work);
605} 610}
@@ -653,6 +658,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
653 spin_lock_init(&wdev->event_lock); 658 spin_lock_init(&wdev->event_lock);
654 mutex_lock(&rdev->devlist_mtx); 659 mutex_lock(&rdev->devlist_mtx);
655 list_add(&wdev->list, &rdev->netdev_list); 660 list_add(&wdev->list, &rdev->netdev_list);
661 rdev->devlist_generation++;
656 /* can only change netns with wiphy */ 662 /* can only change netns with wiphy */
657 dev->features |= NETIF_F_NETNS_LOCAL; 663 dev->features |= NETIF_F_NETNS_LOCAL;
658 664
@@ -670,7 +676,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
670 wdev->wext.default_key = -1; 676 wdev->wext.default_key = -1;
671 wdev->wext.default_mgmt_key = -1; 677 wdev->wext.default_mgmt_key = -1;
672 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; 678 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
673 wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE; 679 wdev->wext.ps = wdev->wiphy->ps_default;
674 wdev->wext.ps_timeout = 100; 680 wdev->wext.ps_timeout = 100;
675 if (rdev->ops->set_power_mgmt) 681 if (rdev->ops->set_power_mgmt)
676 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, 682 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
@@ -706,6 +712,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
706 case NETDEV_UP: 712 case NETDEV_UP:
707#ifdef CONFIG_WIRELESS_EXT 713#ifdef CONFIG_WIRELESS_EXT
708 cfg80211_lock_rdev(rdev); 714 cfg80211_lock_rdev(rdev);
715 mutex_lock(&rdev->devlist_mtx);
709 wdev_lock(wdev); 716 wdev_lock(wdev);
710 switch (wdev->iftype) { 717 switch (wdev->iftype) {
711 case NL80211_IFTYPE_ADHOC: 718 case NL80211_IFTYPE_ADHOC:
@@ -718,10 +725,18 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
718 break; 725 break;
719 } 726 }
720 wdev_unlock(wdev); 727 wdev_unlock(wdev);
728 mutex_unlock(&rdev->devlist_mtx);
721 cfg80211_unlock_rdev(rdev); 729 cfg80211_unlock_rdev(rdev);
722#endif 730#endif
723 break; 731 break;
724 case NETDEV_UNREGISTER: 732 case NETDEV_UNREGISTER:
733 cfg80211_lock_rdev(rdev);
734
735 if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == dev)) {
736 rdev->scan_req->aborted = true;
737 ___cfg80211_scan_done(rdev);
738 }
739
725 mutex_lock(&rdev->devlist_mtx); 740 mutex_lock(&rdev->devlist_mtx);
726 /* 741 /*
727 * It is possible to get NETDEV_UNREGISTER 742 * It is possible to get NETDEV_UNREGISTER
@@ -733,12 +748,14 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
733 if (!list_empty(&wdev->list)) { 748 if (!list_empty(&wdev->list)) {
734 sysfs_remove_link(&dev->dev.kobj, "phy80211"); 749 sysfs_remove_link(&dev->dev.kobj, "phy80211");
735 list_del_init(&wdev->list); 750 list_del_init(&wdev->list);
751 rdev->devlist_generation++;
736 mutex_destroy(&wdev->mtx); 752 mutex_destroy(&wdev->mtx);
737#ifdef CONFIG_WIRELESS_EXT 753#ifdef CONFIG_WIRELESS_EXT
738 kfree(wdev->wext.keys); 754 kfree(wdev->wext.keys);
739#endif 755#endif
740 } 756 }
741 mutex_unlock(&rdev->devlist_mtx); 757 mutex_unlock(&rdev->devlist_mtx);
758 cfg80211_unlock_rdev(rdev);
742 break; 759 break;
743 case NETDEV_PRE_UP: 760 case NETDEV_PRE_UP:
744 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) 761 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 325c17e6198c..c603f5286326 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -49,6 +49,7 @@ struct cfg80211_registered_device {
49 /* associate netdev list */ 49 /* associate netdev list */
50 struct mutex devlist_mtx; 50 struct mutex devlist_mtx;
51 struct list_head netdev_list; 51 struct list_head netdev_list;
52 int devlist_generation;
52 53
53 /* BSSes/scanning */ 54 /* BSSes/scanning */
54 spinlock_t bss_lock; 55 spinlock_t bss_lock;
@@ -101,6 +102,7 @@ bool wiphy_idx_valid(int wiphy_idx)
101 102
102extern struct mutex cfg80211_mutex; 103extern struct mutex cfg80211_mutex;
103extern struct list_head cfg80211_rdev_list; 104extern struct list_head cfg80211_rdev_list;
105extern int cfg80211_rdev_list_generation;
104 106
105#define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex)) 107#define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex))
106 108
@@ -335,7 +337,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
335int __cfg80211_connect(struct cfg80211_registered_device *rdev, 337int __cfg80211_connect(struct cfg80211_registered_device *rdev,
336 struct net_device *dev, 338 struct net_device *dev,
337 struct cfg80211_connect_params *connect, 339 struct cfg80211_connect_params *connect,
338 struct cfg80211_cached_keys *connkeys); 340 struct cfg80211_cached_keys *connkeys,
341 const u8 *prev_bssid);
339int cfg80211_connect(struct cfg80211_registered_device *rdev, 342int cfg80211_connect(struct cfg80211_registered_device *rdev,
340 struct net_device *dev, 343 struct net_device *dev,
341 struct cfg80211_connect_params *connect, 344 struct cfg80211_connect_params *connect,
@@ -353,6 +356,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
353 struct wireless_dev *wdev); 356 struct wireless_dev *wdev);
354 357
355void cfg80211_conn_work(struct work_struct *work); 358void cfg80211_conn_work(struct work_struct *work);
359bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);
356 360
357/* internal helpers */ 361/* internal helpers */
358int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, 362int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
@@ -364,6 +368,14 @@ void cfg80211_sme_scan_done(struct net_device *dev);
364void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); 368void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
365void cfg80211_sme_disassoc(struct net_device *dev, int idx); 369void cfg80211_sme_disassoc(struct net_device *dev, int idx);
366void __cfg80211_scan_done(struct work_struct *wk); 370void __cfg80211_scan_done(struct work_struct *wk);
371void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
367void cfg80211_upload_connect_keys(struct wireless_dev *wdev); 372void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
368 373
374struct ieee80211_channel *
375rdev_fixed_channel(struct cfg80211_registered_device *rdev,
376 struct wireless_dev *for_wdev);
377int rdev_set_freq(struct cfg80211_registered_device *rdev,
378 struct wireless_dev *for_wdev,
379 int freq, enum nl80211_channel_type channel_type);
380
369#endif /* __NET_WIRELESS_CORE_H */ 381#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 4d7a084b35e2..42840a01be74 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -78,10 +78,15 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
78 struct cfg80211_cached_keys *connkeys) 78 struct cfg80211_cached_keys *connkeys)
79{ 79{
80 struct wireless_dev *wdev = dev->ieee80211_ptr; 80 struct wireless_dev *wdev = dev->ieee80211_ptr;
81 struct ieee80211_channel *chan;
81 int err; 82 int err;
82 83
83 ASSERT_WDEV_LOCK(wdev); 84 ASSERT_WDEV_LOCK(wdev);
84 85
86 chan = rdev_fixed_channel(rdev, wdev);
87 if (chan && chan != params->channel)
88 return -EBUSY;
89
85 if (wdev->ssid_len) 90 if (wdev->ssid_len)
86 return -EALREADY; 91 return -EALREADY;
87 92
@@ -112,9 +117,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
112 struct wireless_dev *wdev = dev->ieee80211_ptr; 117 struct wireless_dev *wdev = dev->ieee80211_ptr;
113 int err; 118 int err;
114 119
120 mutex_lock(&rdev->devlist_mtx);
115 wdev_lock(wdev); 121 wdev_lock(wdev);
116 err = __cfg80211_join_ibss(rdev, dev, params, connkeys); 122 err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
117 wdev_unlock(wdev); 123 wdev_unlock(wdev);
124 mutex_unlock(&rdev->devlist_mtx);
118 125
119 return err; 126 return err;
120} 127}
@@ -264,27 +271,32 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
264 271
265int cfg80211_ibss_wext_siwfreq(struct net_device *dev, 272int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
266 struct iw_request_info *info, 273 struct iw_request_info *info,
267 struct iw_freq *freq, char *extra) 274 struct iw_freq *wextfreq, char *extra)
268{ 275{
269 struct wireless_dev *wdev = dev->ieee80211_ptr; 276 struct wireless_dev *wdev = dev->ieee80211_ptr;
270 struct ieee80211_channel *chan; 277 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
271 int err; 278 struct ieee80211_channel *chan = NULL;
279 int err, freq;
272 280
273 /* call only for ibss! */ 281 /* call only for ibss! */
274 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 282 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
275 return -EINVAL; 283 return -EINVAL;
276 284
277 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) 285 if (!rdev->ops->join_ibss)
278 return -EOPNOTSUPP; 286 return -EOPNOTSUPP;
279 287
280 chan = cfg80211_wext_freq(wdev->wiphy, freq); 288 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
281 if (chan && IS_ERR(chan)) 289 if (freq < 0)
282 return PTR_ERR(chan); 290 return freq;
283 291
284 if (chan && 292 if (freq) {
285 (chan->flags & IEEE80211_CHAN_NO_IBSS || 293 chan = ieee80211_get_channel(wdev->wiphy, freq);
286 chan->flags & IEEE80211_CHAN_DISABLED)) 294 if (!chan)
287 return -EINVAL; 295 return -EINVAL;
296 if (chan->flags & IEEE80211_CHAN_NO_IBSS ||
297 chan->flags & IEEE80211_CHAN_DISABLED)
298 return -EINVAL;
299 }
288 300
289 if (wdev->wext.ibss.channel == chan) 301 if (wdev->wext.ibss.channel == chan)
290 return 0; 302 return 0;
@@ -292,8 +304,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
292 wdev_lock(wdev); 304 wdev_lock(wdev);
293 err = 0; 305 err = 0;
294 if (wdev->ssid_len) 306 if (wdev->ssid_len)
295 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 307 err = __cfg80211_leave_ibss(rdev, dev, true);
296 dev, true);
297 wdev_unlock(wdev); 308 wdev_unlock(wdev);
298 309
299 if (err) 310 if (err)
@@ -307,9 +318,11 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
307 wdev->wext.ibss.channel_fixed = false; 318 wdev->wext.ibss.channel_fixed = false;
308 } 319 }
309 320
321 mutex_lock(&rdev->devlist_mtx);
310 wdev_lock(wdev); 322 wdev_lock(wdev);
311 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 323 err = cfg80211_ibss_wext_join(rdev, wdev);
312 wdev_unlock(wdev); 324 wdev_unlock(wdev);
325 mutex_unlock(&rdev->devlist_mtx);
313 326
314 return err; 327 return err;
315} 328}
@@ -347,6 +360,7 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
347 struct iw_point *data, char *ssid) 360 struct iw_point *data, char *ssid)
348{ 361{
349 struct wireless_dev *wdev = dev->ieee80211_ptr; 362 struct wireless_dev *wdev = dev->ieee80211_ptr;
363 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
350 size_t len = data->length; 364 size_t len = data->length;
351 int err; 365 int err;
352 366
@@ -354,14 +368,13 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
354 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 368 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
355 return -EINVAL; 369 return -EINVAL;
356 370
357 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) 371 if (!rdev->ops->join_ibss)
358 return -EOPNOTSUPP; 372 return -EOPNOTSUPP;
359 373
360 wdev_lock(wdev); 374 wdev_lock(wdev);
361 err = 0; 375 err = 0;
362 if (wdev->ssid_len) 376 if (wdev->ssid_len)
363 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 377 err = __cfg80211_leave_ibss(rdev, dev, true);
364 dev, true);
365 wdev_unlock(wdev); 378 wdev_unlock(wdev);
366 379
367 if (err) 380 if (err)
@@ -375,9 +388,11 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
375 memcpy(wdev->wext.ibss.ssid, ssid, len); 388 memcpy(wdev->wext.ibss.ssid, ssid, len);
376 wdev->wext.ibss.ssid_len = len; 389 wdev->wext.ibss.ssid_len = len;
377 390
391 mutex_lock(&rdev->devlist_mtx);
378 wdev_lock(wdev); 392 wdev_lock(wdev);
379 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 393 err = cfg80211_ibss_wext_join(rdev, wdev);
380 wdev_unlock(wdev); 394 wdev_unlock(wdev);
395 mutex_unlock(&rdev->devlist_mtx);
381 396
382 return err; 397 return err;
383} 398}
@@ -414,6 +429,7 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
414 struct sockaddr *ap_addr, char *extra) 429 struct sockaddr *ap_addr, char *extra)
415{ 430{
416 struct wireless_dev *wdev = dev->ieee80211_ptr; 431 struct wireless_dev *wdev = dev->ieee80211_ptr;
432 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
417 u8 *bssid = ap_addr->sa_data; 433 u8 *bssid = ap_addr->sa_data;
418 int err; 434 int err;
419 435
@@ -421,7 +437,7 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
421 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 437 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
422 return -EINVAL; 438 return -EINVAL;
423 439
424 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) 440 if (!rdev->ops->join_ibss)
425 return -EOPNOTSUPP; 441 return -EOPNOTSUPP;
426 442
427 if (ap_addr->sa_family != ARPHRD_ETHER) 443 if (ap_addr->sa_family != ARPHRD_ETHER)
@@ -443,8 +459,7 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
443 wdev_lock(wdev); 459 wdev_lock(wdev);
444 err = 0; 460 err = 0;
445 if (wdev->ssid_len) 461 if (wdev->ssid_len)
446 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 462 err = __cfg80211_leave_ibss(rdev, dev, true);
447 dev, true);
448 wdev_unlock(wdev); 463 wdev_unlock(wdev);
449 464
450 if (err) 465 if (err)
@@ -456,9 +471,11 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
456 } else 471 } else
457 wdev->wext.ibss.bssid = NULL; 472 wdev->wext.ibss.bssid = NULL;
458 473
474 mutex_lock(&rdev->devlist_mtx);
459 wdev_lock(wdev); 475 wdev_lock(wdev);
460 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 476 err = cfg80211_ibss_wext_join(rdev, wdev);
461 wdev_unlock(wdev); 477 wdev_unlock(wdev);
478 mutex_unlock(&rdev->devlist_mtx);
462 479
463 return err; 480 return err;
464} 481}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 525e8e247b30..da64071ceb84 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -67,6 +67,16 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
67 67
68 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); 68 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
69 69
70 /*
71 * This is a bit of a hack, we don't notify userspace of
72 * a (re-)association reply if we tried to send a reassoc
73 * and got a reject -- we only try again with an assoc
74 * frame instead of reassoc.
75 */
76 if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
77 cfg80211_sme_failed_reassoc(wdev))
78 goto out;
79
70 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); 80 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
71 81
72 if (status_code == WLAN_STATUS_SUCCESS) { 82 if (status_code == WLAN_STATUS_SUCCESS) {
@@ -97,6 +107,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
97 cfg80211_put_bss(&bss->pub); 107 cfg80211_put_bss(&bss->pub);
98 } 108 }
99 109
110 out:
100 wdev_unlock(wdev); 111 wdev_unlock(wdev);
101} 112}
102EXPORT_SYMBOL(cfg80211_send_rx_assoc); 113EXPORT_SYMBOL(cfg80211_send_rx_assoc);
@@ -149,7 +160,7 @@ static void __cfg80211_send_deauth(struct net_device *dev,
149 160
150 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); 161 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
151 162
152 from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; 163 from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
153 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); 164 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
154 } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { 165 } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
155 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, 166 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
@@ -198,7 +209,7 @@ static void __cfg80211_send_disassoc(struct net_device *dev,
198 return; 209 return;
199 210
200 if (wdev->current_bss && 211 if (wdev->current_bss &&
201 memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) { 212 memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
202 for (i = 0; i < MAX_AUTH_BSSES; i++) { 213 for (i = 0; i < MAX_AUTH_BSSES; i++) {
203 if (wdev->authtry_bsses[i] || wdev->auth_bsses[i]) 214 if (wdev->authtry_bsses[i] || wdev->auth_bsses[i])
204 continue; 215 continue;
@@ -215,7 +226,7 @@ static void __cfg80211_send_disassoc(struct net_device *dev,
215 226
216 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); 227 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
217 228
218 from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; 229 from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
219 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); 230 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
220} 231}
221 232
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0cd548267d4a..a8aaadeb6773 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -408,6 +408,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
408 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); 408 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
409 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); 409 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
410 410
411 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION,
412 cfg80211_rdev_list_generation);
413
411 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, 414 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
412 dev->wiphy.retry_short); 415 dev->wiphy.retry_short);
413 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, 416 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
@@ -701,15 +704,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
701 704
702 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { 705 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
703 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 706 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
704 struct ieee80211_channel *chan;
705 struct ieee80211_sta_ht_cap *ht_cap;
706 u32 freq; 707 u32 freq;
707 708
708 if (!rdev->ops->set_channel) {
709 result = -EOPNOTSUPP;
710 goto bad_res;
711 }
712
713 result = -EINVAL; 709 result = -EINVAL;
714 710
715 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { 711 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
@@ -723,42 +719,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
723 } 719 }
724 720
725 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 721 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
726 chan = ieee80211_get_channel(&rdev->wiphy, freq);
727
728 /* Primary channel not allowed */
729 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
730 goto bad_res;
731
732 if (channel_type == NL80211_CHAN_HT40MINUS &&
733 (chan->flags & IEEE80211_CHAN_NO_HT40MINUS))
734 goto bad_res;
735 else if (channel_type == NL80211_CHAN_HT40PLUS &&
736 (chan->flags & IEEE80211_CHAN_NO_HT40PLUS))
737 goto bad_res;
738
739 /*
740 * At this point we know if that if HT40 was requested
741 * we are allowed to use it and the extension channel
742 * exists.
743 */
744
745 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
746
747 /* no HT capabilities or intolerant */
748 if (channel_type != NL80211_CHAN_NO_HT) {
749 if (!ht_cap->ht_supported)
750 goto bad_res;
751 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
752 (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
753 goto bad_res;
754 }
755 722
756 result = rdev->ops->set_channel(&rdev->wiphy, chan, 723 mutex_lock(&rdev->devlist_mtx);
757 channel_type); 724 result = rdev_set_freq(rdev, NULL, freq, channel_type);
725 mutex_unlock(&rdev->devlist_mtx);
758 if (result) 726 if (result)
759 goto bad_res; 727 goto bad_res;
760
761 rdev->channel = chan;
762 } 728 }
763 729
764 changed = 0; 730 changed = 0;
@@ -862,6 +828,11 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
862 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); 828 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
863 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); 829 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
864 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); 830 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype);
831
832 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION,
833 rdev->devlist_generation ^
834 (cfg80211_rdev_list_generation << 2));
835
865 return genlmsg_end(msg, hdr); 836 return genlmsg_end(msg, hdr);
866 837
867 nla_put_failure: 838 nla_put_failure:
@@ -875,12 +846,12 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
875 int if_idx = 0; 846 int if_idx = 0;
876 int wp_start = cb->args[0]; 847 int wp_start = cb->args[0];
877 int if_start = cb->args[1]; 848 int if_start = cb->args[1];
878 struct cfg80211_registered_device *dev; 849 struct cfg80211_registered_device *rdev;
879 struct wireless_dev *wdev; 850 struct wireless_dev *wdev;
880 851
881 mutex_lock(&cfg80211_mutex); 852 mutex_lock(&cfg80211_mutex);
882 list_for_each_entry(dev, &cfg80211_rdev_list, list) { 853 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
883 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) 854 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
884 continue; 855 continue;
885 if (wp_idx < wp_start) { 856 if (wp_idx < wp_start) {
886 wp_idx++; 857 wp_idx++;
@@ -888,21 +859,21 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
888 } 859 }
889 if_idx = 0; 860 if_idx = 0;
890 861
891 mutex_lock(&dev->devlist_mtx); 862 mutex_lock(&rdev->devlist_mtx);
892 list_for_each_entry(wdev, &dev->netdev_list, list) { 863 list_for_each_entry(wdev, &rdev->netdev_list, list) {
893 if (if_idx < if_start) { 864 if (if_idx < if_start) {
894 if_idx++; 865 if_idx++;
895 continue; 866 continue;
896 } 867 }
897 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, 868 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
898 cb->nlh->nlmsg_seq, NLM_F_MULTI, 869 cb->nlh->nlmsg_seq, NLM_F_MULTI,
899 dev, wdev->netdev) < 0) { 870 rdev, wdev->netdev) < 0) {
900 mutex_unlock(&dev->devlist_mtx); 871 mutex_unlock(&rdev->devlist_mtx);
901 goto out; 872 goto out;
902 } 873 }
903 if_idx++; 874 if_idx++;
904 } 875 }
905 mutex_unlock(&dev->devlist_mtx); 876 mutex_unlock(&rdev->devlist_mtx);
906 877
907 wp_idx++; 878 wp_idx++;
908 } 879 }
@@ -1653,6 +1624,8 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1653 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); 1624 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1654 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); 1625 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
1655 1626
1627 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, sinfo->generation);
1628
1656 sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); 1629 sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
1657 if (!sinfoattr) 1630 if (!sinfoattr)
1658 goto nla_put_failure; 1631 goto nla_put_failure;
@@ -2138,6 +2111,8 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
2138 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst); 2111 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
2139 NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop); 2112 NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
2140 2113
2114 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, pinfo->generation);
2115
2141 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO); 2116 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
2142 if (!pinfoattr) 2117 if (!pinfoattr)
2143 goto nla_put_failure; 2118 goto nla_put_failure;
@@ -3027,10 +3002,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3027 goto out; 3002 goto out;
3028 } 3003 }
3029 3004
3030 request->channels = (void *)((char *)request + sizeof(*request));
3031 request->n_channels = n_channels; 3005 request->n_channels = n_channels;
3032 if (n_ssids) 3006 if (n_ssids)
3033 request->ssids = (void *)(request->channels + n_channels); 3007 request->ssids = (void *)&request->channels[n_channels];
3034 request->n_ssids = n_ssids; 3008 request->n_ssids = n_ssids;
3035 if (ie_len) { 3009 if (ie_len) {
3036 if (request->ssids) 3010 if (request->ssids)
@@ -3127,8 +3101,7 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
3127 if (!hdr) 3101 if (!hdr)
3128 return -1; 3102 return -1;
3129 3103
3130 NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION, 3104 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation);
3131 rdev->bss_generation);
3132 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex); 3105 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex);
3133 3106
3134 bss = nla_nest_start(msg, NL80211_ATTR_BSS); 3107 bss = nla_nest_start(msg, NL80211_ATTR_BSS);
@@ -3453,7 +3426,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3453 struct cfg80211_registered_device *rdev; 3426 struct cfg80211_registered_device *rdev;
3454 struct net_device *dev; 3427 struct net_device *dev;
3455 struct cfg80211_crypto_settings crypto; 3428 struct cfg80211_crypto_settings crypto;
3456 struct ieee80211_channel *chan; 3429 struct ieee80211_channel *chan, *fixedchan;
3457 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; 3430 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
3458 int err, ssid_len, ie_len = 0; 3431 int err, ssid_len, ie_len = 0;
3459 bool use_mfp = false; 3432 bool use_mfp = false;
@@ -3496,6 +3469,15 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3496 goto out; 3469 goto out;
3497 } 3470 }
3498 3471
3472 mutex_lock(&rdev->devlist_mtx);
3473 fixedchan = rdev_fixed_channel(rdev, NULL);
3474 if (fixedchan && chan != fixedchan) {
3475 err = -EBUSY;
3476 mutex_unlock(&rdev->devlist_mtx);
3477 goto out;
3478 }
3479 mutex_unlock(&rdev->devlist_mtx);
3480
3499 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); 3481 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3500 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); 3482 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
3501 3483
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 0f61ae613f3b..f256dfffbf46 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1018,7 +1018,6 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
1018 map_regdom_flags(reg_rule->flags) | bw_flags; 1018 map_regdom_flags(reg_rule->flags) | bw_flags;
1019 chan->max_antenna_gain = chan->orig_mag = 1019 chan->max_antenna_gain = chan->orig_mag =
1020 (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1020 (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1021 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1022 chan->max_power = chan->orig_mpwr = 1021 chan->max_power = chan->orig_mpwr =
1023 (int) MBM_TO_DBM(power_rule->max_eirp); 1022 (int) MBM_TO_DBM(power_rule->max_eirp);
1024 return; 1023 return;
@@ -1027,7 +1026,6 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
1027 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); 1026 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
1028 chan->max_antenna_gain = min(chan->orig_mag, 1027 chan->max_antenna_gain = min(chan->orig_mag,
1029 (int) MBI_TO_DBI(power_rule->max_antenna_gain)); 1028 (int) MBI_TO_DBI(power_rule->max_antenna_gain));
1030 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1031 if (chan->orig_mpwr) 1029 if (chan->orig_mpwr)
1032 chan->max_power = min(chan->orig_mpwr, 1030 chan->max_power = min(chan->orig_mpwr,
1033 (int) MBM_TO_DBM(power_rule->max_eirp)); 1031 (int) MBM_TO_DBM(power_rule->max_eirp));
@@ -1329,7 +1327,6 @@ static void handle_channel_custom(struct wiphy *wiphy,
1329 1327
1330 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; 1328 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
1331 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1329 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1332 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1333 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); 1330 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
1334} 1331}
1335 1332
@@ -1427,7 +1424,7 @@ static int ignore_request(struct wiphy *wiphy,
1427 if (last_wiphy != wiphy) { 1424 if (last_wiphy != wiphy) {
1428 /* 1425 /*
1429 * Two cards with two APs claiming different 1426 * Two cards with two APs claiming different
1430 * different Country IE alpha2s. We could 1427 * Country IE alpha2s. We could
1431 * intersect them, but that seems unlikely 1428 * intersect them, but that seems unlikely
1432 * to be correct. Reject second one for now. 1429 * to be correct. Reject second one for now.
1433 */ 1430 */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 0ccf3a07dc02..fe575a24c95c 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -18,19 +18,14 @@
18 18
19#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ) 19#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
20 20
21void __cfg80211_scan_done(struct work_struct *wk) 21void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
22{ 22{
23 struct cfg80211_registered_device *rdev;
24 struct cfg80211_scan_request *request; 23 struct cfg80211_scan_request *request;
25 struct net_device *dev; 24 struct net_device *dev;
26#ifdef CONFIG_WIRELESS_EXT 25#ifdef CONFIG_WIRELESS_EXT
27 union iwreq_data wrqu; 26 union iwreq_data wrqu;
28#endif 27#endif
29 28
30 rdev = container_of(wk, struct cfg80211_registered_device,
31 scan_done_wk);
32
33 mutex_lock(&rdev->mtx);
34 request = rdev->scan_req; 29 request = rdev->scan_req;
35 30
36 dev = request->dev; 31 dev = request->dev;
@@ -43,9 +38,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
43 cfg80211_sme_scan_done(dev); 38 cfg80211_sme_scan_done(dev);
44 39
45 if (request->aborted) 40 if (request->aborted)
46 nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev); 41 nl80211_send_scan_aborted(rdev, dev);
47 else 42 else
48 nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev); 43 nl80211_send_scan_done(rdev, dev);
49 44
50#ifdef CONFIG_WIRELESS_EXT 45#ifdef CONFIG_WIRELESS_EXT
51 if (!request->aborted) { 46 if (!request->aborted) {
@@ -57,11 +52,22 @@ void __cfg80211_scan_done(struct work_struct *wk)
57 52
58 dev_put(dev); 53 dev_put(dev);
59 54
60 cfg80211_unlock_rdev(rdev); 55 rdev->scan_req = NULL;
61 wiphy_to_dev(request->wiphy)->scan_req = NULL;
62 kfree(request); 56 kfree(request);
63} 57}
64 58
59void __cfg80211_scan_done(struct work_struct *wk)
60{
61 struct cfg80211_registered_device *rdev;
62
63 rdev = container_of(wk, struct cfg80211_registered_device,
64 scan_done_wk);
65
66 cfg80211_lock_rdev(rdev);
67 ___cfg80211_scan_done(rdev);
68 cfg80211_unlock_rdev(rdev);
69}
70
65void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 71void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
66{ 72{
67 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); 73 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
@@ -562,6 +568,7 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
562 spin_lock_bh(&dev->bss_lock); 568 spin_lock_bh(&dev->bss_lock);
563 569
564 list_del(&bss->list); 570 list_del(&bss->list);
571 dev->bss_generation++;
565 rb_erase(&bss->rbn, &dev->bss_tree); 572 rb_erase(&bss->rbn, &dev->bss_tree);
566 573
567 spin_unlock_bh(&dev->bss_lock); 574 spin_unlock_bh(&dev->bss_lock);
@@ -611,8 +618,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
611 618
612 creq->wiphy = wiphy; 619 creq->wiphy = wiphy;
613 creq->dev = dev; 620 creq->dev = dev;
614 creq->ssids = (void *)(creq + 1); 621 /* SSIDs come after channels */
615 creq->channels = (void *)(creq->ssids + 1); 622 creq->ssids = (void *)&creq->channels[n_channels];
616 creq->n_channels = n_channels; 623 creq->n_channels = n_channels;
617 creq->n_ssids = 1; 624 creq->n_ssids = 1;
618 625
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 8a7dcbf90602..8e2ef54ea714 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -27,10 +27,10 @@ struct cfg80211_conn {
27 CFG80211_CONN_ASSOCIATE_NEXT, 27 CFG80211_CONN_ASSOCIATE_NEXT,
28 CFG80211_CONN_ASSOCIATING, 28 CFG80211_CONN_ASSOCIATING,
29 } state; 29 } state;
30 u8 bssid[ETH_ALEN]; 30 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
31 u8 *ie; 31 u8 *ie;
32 size_t ie_len; 32 size_t ie_len;
33 bool auto_auth; 33 bool auto_auth, prev_bssid_valid;
34}; 34};
35 35
36 36
@@ -65,7 +65,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
65 if (!request) 65 if (!request)
66 return -ENOMEM; 66 return -ENOMEM;
67 67
68 request->channels = (void *)((char *)request + sizeof(*request));
69 if (wdev->conn->params.channel) 68 if (wdev->conn->params.channel)
70 request->channels[0] = wdev->conn->params.channel; 69 request->channels[0] = wdev->conn->params.channel;
71 else { 70 else {
@@ -82,7 +81,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
82 } 81 }
83 } 82 }
84 request->n_channels = n_channels; 83 request->n_channels = n_channels;
85 request->ssids = (void *)(request->channels + n_channels); 84 request->ssids = (void *)&request->channels[n_channels];
86 request->n_ssids = 1; 85 request->n_ssids = 1;
87 86
88 memcpy(request->ssids[0].ssid, wdev->conn->params.ssid, 87 memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
@@ -110,6 +109,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
110{ 109{
111 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 110 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
112 struct cfg80211_connect_params *params; 111 struct cfg80211_connect_params *params;
112 const u8 *prev_bssid = NULL;
113 int err; 113 int err;
114 114
115 ASSERT_WDEV_LOCK(wdev); 115 ASSERT_WDEV_LOCK(wdev);
@@ -135,15 +135,11 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
135 case CFG80211_CONN_ASSOCIATE_NEXT: 135 case CFG80211_CONN_ASSOCIATE_NEXT:
136 BUG_ON(!rdev->ops->assoc); 136 BUG_ON(!rdev->ops->assoc);
137 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 137 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
138 /* 138 if (wdev->conn->prev_bssid_valid)
139 * We could, later, implement roaming here and then actually 139 prev_bssid = wdev->conn->prev_bssid;
140 * set prev_bssid to non-NULL. But then we need to be aware
141 * that some APs don't like that -- so we'd need to retry
142 * the association.
143 */
144 err = __cfg80211_mlme_assoc(rdev, wdev->netdev, 140 err = __cfg80211_mlme_assoc(rdev, wdev->netdev,
145 params->channel, params->bssid, 141 params->channel, params->bssid,
146 NULL, 142 prev_bssid,
147 params->ssid, params->ssid_len, 143 params->ssid, params->ssid_len,
148 params->ie, params->ie_len, 144 params->ie, params->ie_len,
149 false, &params->crypto); 145 false, &params->crypto);
@@ -256,9 +252,11 @@ void cfg80211_sme_scan_done(struct net_device *dev)
256{ 252{
257 struct wireless_dev *wdev = dev->ieee80211_ptr; 253 struct wireless_dev *wdev = dev->ieee80211_ptr;
258 254
255 mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
259 wdev_lock(wdev); 256 wdev_lock(wdev);
260 __cfg80211_sme_scan_done(dev); 257 __cfg80211_sme_scan_done(dev);
261 wdev_unlock(wdev); 258 wdev_unlock(wdev);
259 mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
262} 260}
263 261
264void cfg80211_sme_rx_auth(struct net_device *dev, 262void cfg80211_sme_rx_auth(struct net_device *dev,
@@ -314,6 +312,28 @@ void cfg80211_sme_rx_auth(struct net_device *dev,
314 } 312 }
315} 313}
316 314
315bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev)
316{
317 struct wiphy *wiphy = wdev->wiphy;
318 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
319
320 if (WARN_ON(!wdev->conn))
321 return false;
322
323 if (!wdev->conn->prev_bssid_valid)
324 return false;
325
326 /*
327 * Some stupid APs don't accept reassoc, so we
328 * need to fall back to trying regular assoc.
329 */
330 wdev->conn->prev_bssid_valid = false;
331 wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
332 schedule_work(&rdev->conn_work);
333
334 return true;
335}
336
317void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 337void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
318 const u8 *req_ie, size_t req_ie_len, 338 const u8 *req_ie, size_t req_ie_len,
319 const u8 *resp_ie, size_t resp_ie_len, 339 const u8 *resp_ie, size_t resp_ie_len,
@@ -357,8 +377,11 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
357 377
358 memset(&wrqu, 0, sizeof(wrqu)); 378 memset(&wrqu, 0, sizeof(wrqu));
359 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 379 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
360 if (bssid && status == WLAN_STATUS_SUCCESS) 380 if (bssid && status == WLAN_STATUS_SUCCESS) {
361 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 381 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
382 memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
383 wdev->wext.prev_bssid_valid = true;
384 }
362 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 385 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
363 } 386 }
364#endif 387#endif
@@ -509,6 +532,8 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
509 memset(&wrqu, 0, sizeof(wrqu)); 532 memset(&wrqu, 0, sizeof(wrqu));
510 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 533 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
511 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 534 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
535 memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
536 wdev->wext.prev_bssid_valid = true;
512 wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL); 537 wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
513#endif 538#endif
514} 539}
@@ -570,10 +595,30 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
570 wdev->ssid_len = 0; 595 wdev->ssid_len = 0;
571 596
572 if (wdev->conn) { 597 if (wdev->conn) {
598 const u8 *bssid;
599 int ret;
600
573 kfree(wdev->conn->ie); 601 kfree(wdev->conn->ie);
574 wdev->conn->ie = NULL; 602 wdev->conn->ie = NULL;
575 kfree(wdev->conn); 603 kfree(wdev->conn);
576 wdev->conn = NULL; 604 wdev->conn = NULL;
605
606 /*
607 * If this disconnect was due to a disassoc, we
608 * we might still have an auth BSS around. For
609 * the userspace SME that's currently expected,
610 * but for the kernel SME (nl80211 CONNECT or
611 * wireless extensions) we want to clear up all
612 * state.
613 */
614 for (i = 0; i < MAX_AUTH_BSSES; i++) {
615 if (!wdev->auth_bsses[i])
616 continue;
617 bssid = wdev->auth_bsses[i]->pub.bssid;
618 ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
619 WLAN_REASON_DEAUTH_LEAVING);
620 WARN(ret, "deauth failed: %d\n", ret);
621 }
577 } 622 }
578 623
579 nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); 624 nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
@@ -621,9 +666,11 @@ EXPORT_SYMBOL(cfg80211_disconnected);
621int __cfg80211_connect(struct cfg80211_registered_device *rdev, 666int __cfg80211_connect(struct cfg80211_registered_device *rdev,
622 struct net_device *dev, 667 struct net_device *dev,
623 struct cfg80211_connect_params *connect, 668 struct cfg80211_connect_params *connect,
624 struct cfg80211_cached_keys *connkeys) 669 struct cfg80211_cached_keys *connkeys,
670 const u8 *prev_bssid)
625{ 671{
626 struct wireless_dev *wdev = dev->ieee80211_ptr; 672 struct wireless_dev *wdev = dev->ieee80211_ptr;
673 struct ieee80211_channel *chan;
627 int err; 674 int err;
628 675
629 ASSERT_WDEV_LOCK(wdev); 676 ASSERT_WDEV_LOCK(wdev);
@@ -631,6 +678,10 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
631 if (wdev->sme_state != CFG80211_SME_IDLE) 678 if (wdev->sme_state != CFG80211_SME_IDLE)
632 return -EALREADY; 679 return -EALREADY;
633 680
681 chan = rdev_fixed_channel(rdev, wdev);
682 if (chan && chan != connect->channel)
683 return -EBUSY;
684
634 if (WARN_ON(wdev->connect_keys)) { 685 if (WARN_ON(wdev->connect_keys)) {
635 kfree(wdev->connect_keys); 686 kfree(wdev->connect_keys);
636 wdev->connect_keys = NULL; 687 wdev->connect_keys = NULL;
@@ -638,14 +689,28 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
638 689
639 if (connkeys && connkeys->def >= 0) { 690 if (connkeys && connkeys->def >= 0) {
640 int idx; 691 int idx;
692 u32 cipher;
641 693
642 idx = connkeys->def; 694 idx = connkeys->def;
695 cipher = connkeys->params[idx].cipher;
643 /* If given a WEP key we may need it for shared key auth */ 696 /* If given a WEP key we may need it for shared key auth */
644 if (connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP40 || 697 if (cipher == WLAN_CIPHER_SUITE_WEP40 ||
645 connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP104) { 698 cipher == WLAN_CIPHER_SUITE_WEP104) {
646 connect->key_idx = idx; 699 connect->key_idx = idx;
647 connect->key = connkeys->params[idx].key; 700 connect->key = connkeys->params[idx].key;
648 connect->key_len = connkeys->params[idx].key_len; 701 connect->key_len = connkeys->params[idx].key_len;
702
703 /*
704 * If ciphers are not set (e.g. when going through
705 * iwconfig), we have to set them appropriately here.
706 */
707 if (connect->crypto.cipher_group == 0)
708 connect->crypto.cipher_group = cipher;
709
710 if (connect->crypto.n_ciphers_pairwise == 0) {
711 connect->crypto.n_ciphers_pairwise = 1;
712 connect->crypto.ciphers_pairwise[0] = cipher;
713 }
649 } 714 }
650 } 715 }
651 716
@@ -701,6 +766,11 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
701 wdev->sme_state = CFG80211_SME_CONNECTING; 766 wdev->sme_state = CFG80211_SME_CONNECTING;
702 wdev->connect_keys = connkeys; 767 wdev->connect_keys = connkeys;
703 768
769 if (prev_bssid) {
770 memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
771 wdev->conn->prev_bssid_valid = true;
772 }
773
704 /* we're good if we have both BSSID and channel */ 774 /* we're good if we have both BSSID and channel */
705 if (wdev->conn->params.bssid && wdev->conn->params.channel) { 775 if (wdev->conn->params.bssid && wdev->conn->params.channel) {
706 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; 776 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
@@ -751,9 +821,11 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
751{ 821{
752 int err; 822 int err;
753 823
824 mutex_lock(&rdev->devlist_mtx);
754 wdev_lock(dev->ieee80211_ptr); 825 wdev_lock(dev->ieee80211_ptr);
755 err = __cfg80211_connect(rdev, dev, connect, connkeys); 826 err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
756 wdev_unlock(dev->ieee80211_ptr); 827 wdev_unlock(dev->ieee80211_ptr);
828 mutex_unlock(&rdev->devlist_mtx);
757 829
758 return err; 830 return err;
759} 831}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index ba387d85dcfd..693275a16a26 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -274,11 +274,11 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
274 switch (ae) { 274 switch (ae) {
275 case 0: 275 case 0:
276 return 6; 276 return 6;
277 case 1: 277 case MESH_FLAGS_AE_A4:
278 return 12; 278 return 12;
279 case 2: 279 case MESH_FLAGS_AE_A5_A6:
280 return 18; 280 return 18;
281 case 3: 281 case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
282 return 24; 282 return 24;
283 default: 283 default:
284 return 6; 284 return 6;
@@ -333,10 +333,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
333 } 333 }
334 break; 334 break;
335 case cpu_to_le16(IEEE80211_FCTL_FROMDS): 335 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
336 if (iftype != NL80211_IFTYPE_STATION || 336 if ((iftype != NL80211_IFTYPE_STATION &&
337 iftype != NL80211_IFTYPE_MESH_POINT) ||
337 (is_multicast_ether_addr(dst) && 338 (is_multicast_ether_addr(dst) &&
338 !compare_ether_addr(src, addr))) 339 !compare_ether_addr(src, addr)))
339 return -1; 340 return -1;
341 if (iftype == NL80211_IFTYPE_MESH_POINT) {
342 struct ieee80211s_hdr *meshdr =
343 (struct ieee80211s_hdr *) (skb->data + hdrlen);
344 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
345 if (meshdr->flags & MESH_FLAGS_AE_A4)
346 memcpy(src, meshdr->eaddr1, ETH_ALEN);
347 }
340 break; 348 break;
341 case cpu_to_le16(0): 349 case cpu_to_le16(0):
342 if (iftype != NL80211_IFTYPE_ADHOC) 350 if (iftype != NL80211_IFTYPE_ADHOC)
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index e4e90e249bab..c44917492210 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -267,39 +267,26 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
267 * @wiphy: the wiphy 267 * @wiphy: the wiphy
268 * @freq: the wext freq encoding 268 * @freq: the wext freq encoding
269 * 269 *
270 * Returns a channel, %NULL for auto, or an ERR_PTR for errors! 270 * Returns a frequency, or a negative error code, or 0 for auto.
271 */ 271 */
272struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, 272int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
273 struct iw_freq *freq)
274{ 273{
275 struct ieee80211_channel *chan;
276 int f;
277
278 /* 274 /*
279 * Parse frequency - return NULL for auto and 275 * Parse frequency - return 0 for auto and
280 * -EINVAL for impossible things. 276 * -EINVAL for impossible things.
281 */ 277 */
282 if (freq->e == 0) { 278 if (freq->e == 0) {
283 if (freq->m < 0) 279 if (freq->m < 0)
284 return NULL; 280 return 0;
285 f = ieee80211_channel_to_frequency(freq->m); 281 return ieee80211_channel_to_frequency(freq->m);
286 } else { 282 } else {
287 int i, div = 1000000; 283 int i, div = 1000000;
288 for (i = 0; i < freq->e; i++) 284 for (i = 0; i < freq->e; i++)
289 div /= 10; 285 div /= 10;
290 if (div <= 0) 286 if (div <= 0)
291 return ERR_PTR(-EINVAL); 287 return -EINVAL;
292 f = freq->m / div; 288 return freq->m / div;
293 } 289 }
294
295 /*
296 * Look up channel struct and return -EINVAL when
297 * it cannot be found.
298 */
299 chan = ieee80211_get_channel(wiphy, f);
300 if (!chan)
301 return ERR_PTR(-EINVAL);
302 return chan;
303} 290}
304 291
305int cfg80211_wext_siwrts(struct net_device *dev, 292int cfg80211_wext_siwrts(struct net_device *dev,
@@ -761,33 +748,29 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
761 748
762int cfg80211_wext_siwfreq(struct net_device *dev, 749int cfg80211_wext_siwfreq(struct net_device *dev,
763 struct iw_request_info *info, 750 struct iw_request_info *info,
764 struct iw_freq *freq, char *extra) 751 struct iw_freq *wextfreq, char *extra)
765{ 752{
766 struct wireless_dev *wdev = dev->ieee80211_ptr; 753 struct wireless_dev *wdev = dev->ieee80211_ptr;
767 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 754 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
768 struct ieee80211_channel *chan; 755 int freq, err;
769 int err;
770 756
771 switch (wdev->iftype) { 757 switch (wdev->iftype) {
772 case NL80211_IFTYPE_STATION: 758 case NL80211_IFTYPE_STATION:
773 return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra); 759 return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
774 case NL80211_IFTYPE_ADHOC: 760 case NL80211_IFTYPE_ADHOC:
775 return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); 761 return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
776 default: 762 default:
777 chan = cfg80211_wext_freq(wdev->wiphy, freq); 763 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
778 if (!chan) 764 if (freq < 0)
765 return freq;
766 if (freq == 0)
779 return -EINVAL; 767 return -EINVAL;
780 if (IS_ERR(chan)) 768 mutex_lock(&rdev->devlist_mtx);
781 return PTR_ERR(chan); 769 err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
782 err = rdev->ops->set_channel(wdev->wiphy, chan, 770 mutex_unlock(&rdev->devlist_mtx);
783 NL80211_CHAN_NO_HT); 771 return err;
784 if (err)
785 return err;
786 rdev->channel = chan;
787 return 0;
788 } 772 }
789} 773}
790EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
791 774
792int cfg80211_wext_giwfreq(struct net_device *dev, 775int cfg80211_wext_giwfreq(struct net_device *dev,
793 struct iw_request_info *info, 776 struct iw_request_info *info,
diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h
index 9a3774749589..20b3daef6964 100644
--- a/net/wireless/wext-compat.h
+++ b/net/wireless/wext-compat.h
@@ -42,8 +42,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
42 struct iw_request_info *info, 42 struct iw_request_info *info,
43 struct iw_point *data, char *ssid); 43 struct iw_point *data, char *ssid);
44 44
45struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, 45int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq);
46 struct iw_freq *freq);
47 46
48 47
49extern const struct iw_handler_def cfg80211_wext_handler; 48extern const struct iw_handler_def cfg80211_wext_handler;
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 7bacbd1c2af6..d16cd9ea4d00 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -15,6 +15,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
15 struct wireless_dev *wdev) 15 struct wireless_dev *wdev)
16{ 16{
17 struct cfg80211_cached_keys *ck = NULL; 17 struct cfg80211_cached_keys *ck = NULL;
18 const u8 *prev_bssid = NULL;
18 int err, i; 19 int err, i;
19 20
20 ASSERT_RDEV_LOCK(rdev); 21 ASSERT_RDEV_LOCK(rdev);
@@ -42,8 +43,12 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
42 for (i = 0; i < 6; i++) 43 for (i = 0; i < 6; i++)
43 ck->params[i].key = ck->data[i]; 44 ck->params[i].key = ck->data[i];
44 } 45 }
46
47 if (wdev->wext.prev_bssid_valid)
48 prev_bssid = wdev->wext.prev_bssid;
49
45 err = __cfg80211_connect(rdev, wdev->netdev, 50 err = __cfg80211_connect(rdev, wdev->netdev,
46 &wdev->wext.connect, ck); 51 &wdev->wext.connect, ck, prev_bssid);
47 if (err) 52 if (err)
48 kfree(ck); 53 kfree(ck);
49 54
@@ -52,25 +57,31 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
52 57
53int cfg80211_mgd_wext_siwfreq(struct net_device *dev, 58int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
54 struct iw_request_info *info, 59 struct iw_request_info *info,
55 struct iw_freq *freq, char *extra) 60 struct iw_freq *wextfreq, char *extra)
56{ 61{
57 struct wireless_dev *wdev = dev->ieee80211_ptr; 62 struct wireless_dev *wdev = dev->ieee80211_ptr;
58 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 63 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
59 struct ieee80211_channel *chan; 64 struct ieee80211_channel *chan = NULL;
60 int err; 65 int err, freq;
61 66
62 /* call only for station! */ 67 /* call only for station! */
63 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 68 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
64 return -EINVAL; 69 return -EINVAL;
65 70
66 chan = cfg80211_wext_freq(wdev->wiphy, freq); 71 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
67 if (chan && IS_ERR(chan)) 72 if (freq < 0)
68 return PTR_ERR(chan); 73 return freq;
69 74
70 if (chan && (chan->flags & IEEE80211_CHAN_DISABLED)) 75 if (freq) {
71 return -EINVAL; 76 chan = ieee80211_get_channel(wdev->wiphy, freq);
77 if (!chan)
78 return -EINVAL;
79 if (chan->flags & IEEE80211_CHAN_DISABLED)
80 return -EINVAL;
81 }
72 82
73 cfg80211_lock_rdev(rdev); 83 cfg80211_lock_rdev(rdev);
84 mutex_lock(&rdev->devlist_mtx);
74 wdev_lock(wdev); 85 wdev_lock(wdev);
75 86
76 if (wdev->sme_state != CFG80211_SME_IDLE) { 87 if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -84,9 +95,8 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
84 /* if SSID set, we'll try right again, avoid event */ 95 /* if SSID set, we'll try right again, avoid event */
85 if (wdev->wext.connect.ssid_len) 96 if (wdev->wext.connect.ssid_len)
86 event = false; 97 event = false;
87 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 98 err = __cfg80211_disconnect(rdev, dev,
88 dev, WLAN_REASON_DEAUTH_LEAVING, 99 WLAN_REASON_DEAUTH_LEAVING, event);
89 event);
90 if (err) 100 if (err)
91 goto out; 101 goto out;
92 } 102 }
@@ -95,17 +105,15 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
95 wdev->wext.connect.channel = chan; 105 wdev->wext.connect.channel = chan;
96 106
97 /* SSID is not set, we just want to switch channel */ 107 /* SSID is not set, we just want to switch channel */
98 if (wdev->wext.connect.ssid_len && chan) { 108 if (chan && !wdev->wext.connect.ssid_len) {
99 err = -EOPNOTSUPP; 109 err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
100 if (rdev->ops->set_channel)
101 err = rdev->ops->set_channel(wdev->wiphy, chan,
102 NL80211_CHAN_NO_HT);
103 goto out; 110 goto out;
104 } 111 }
105 112
106 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 113 err = cfg80211_mgd_wext_connect(rdev, wdev);
107 out: 114 out:
108 wdev_unlock(wdev); 115 wdev_unlock(wdev);
116 mutex_unlock(&rdev->devlist_mtx);
109 cfg80211_unlock_rdev(rdev); 117 cfg80211_unlock_rdev(rdev);
110 return err; 118 return err;
111} 119}
@@ -143,6 +151,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
143 struct iw_point *data, char *ssid) 151 struct iw_point *data, char *ssid)
144{ 152{
145 struct wireless_dev *wdev = dev->ieee80211_ptr; 153 struct wireless_dev *wdev = dev->ieee80211_ptr;
154 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
146 size_t len = data->length; 155 size_t len = data->length;
147 int err; 156 int err;
148 157
@@ -157,7 +166,8 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
157 if (len > 0 && ssid[len - 1] == '\0') 166 if (len > 0 && ssid[len - 1] == '\0')
158 len--; 167 len--;
159 168
160 cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy)); 169 cfg80211_lock_rdev(rdev);
170 mutex_lock(&rdev->devlist_mtx);
161 wdev_lock(wdev); 171 wdev_lock(wdev);
162 172
163 err = 0; 173 err = 0;
@@ -173,23 +183,24 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
173 /* if SSID set now, we'll try to connect, avoid event */ 183 /* if SSID set now, we'll try to connect, avoid event */
174 if (len) 184 if (len)
175 event = false; 185 event = false;
176 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 186 err = __cfg80211_disconnect(rdev, dev,
177 dev, WLAN_REASON_DEAUTH_LEAVING, 187 WLAN_REASON_DEAUTH_LEAVING, event);
178 event);
179 if (err) 188 if (err)
180 goto out; 189 goto out;
181 } 190 }
182 191
192 wdev->wext.prev_bssid_valid = false;
183 wdev->wext.connect.ssid = wdev->wext.ssid; 193 wdev->wext.connect.ssid = wdev->wext.ssid;
184 memcpy(wdev->wext.ssid, ssid, len); 194 memcpy(wdev->wext.ssid, ssid, len);
185 wdev->wext.connect.ssid_len = len; 195 wdev->wext.connect.ssid_len = len;
186 196
187 wdev->wext.connect.crypto.control_port = false; 197 wdev->wext.connect.crypto.control_port = false;
188 198
189 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 199 err = cfg80211_mgd_wext_connect(rdev, wdev);
190 out: 200 out:
191 wdev_unlock(wdev); 201 wdev_unlock(wdev);
192 cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); 202 mutex_unlock(&rdev->devlist_mtx);
203 cfg80211_unlock_rdev(rdev);
193 return err; 204 return err;
194} 205}
195 206
@@ -206,7 +217,15 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
206 data->flags = 0; 217 data->flags = 0;
207 218
208 wdev_lock(wdev); 219 wdev_lock(wdev);
209 if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { 220 if (wdev->current_bss) {
221 const u8 *ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
222 WLAN_EID_SSID);
223 if (ie) {
224 data->flags = 1;
225 data->length = ie[1];
226 memcpy(ssid, ie + 2, data->length);
227 }
228 } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
210 data->flags = 1; 229 data->flags = 1;
211 data->length = wdev->wext.connect.ssid_len; 230 data->length = wdev->wext.connect.ssid_len;
212 memcpy(ssid, wdev->wext.connect.ssid, data->length); 231 memcpy(ssid, wdev->wext.connect.ssid, data->length);
@@ -222,6 +241,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
222 struct sockaddr *ap_addr, char *extra) 241 struct sockaddr *ap_addr, char *extra)
223{ 242{
224 struct wireless_dev *wdev = dev->ieee80211_ptr; 243 struct wireless_dev *wdev = dev->ieee80211_ptr;
244 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
225 u8 *bssid = ap_addr->sa_data; 245 u8 *bssid = ap_addr->sa_data;
226 int err; 246 int err;
227 247
@@ -236,7 +256,8 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
236 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) 256 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
237 bssid = NULL; 257 bssid = NULL;
238 258
239 cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy)); 259 cfg80211_lock_rdev(rdev);
260 mutex_lock(&rdev->devlist_mtx);
240 wdev_lock(wdev); 261 wdev_lock(wdev);
241 262
242 if (wdev->sme_state != CFG80211_SME_IDLE) { 263 if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -250,9 +271,8 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
250 compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0) 271 compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0)
251 goto out; 272 goto out;
252 273
253 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 274 err = __cfg80211_disconnect(rdev, dev,
254 dev, WLAN_REASON_DEAUTH_LEAVING, 275 WLAN_REASON_DEAUTH_LEAVING, false);
255 false);
256 if (err) 276 if (err)
257 goto out; 277 goto out;
258 } 278 }
@@ -263,10 +283,11 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
263 } else 283 } else
264 wdev->wext.connect.bssid = NULL; 284 wdev->wext.connect.bssid = NULL;
265 285
266 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 286 err = cfg80211_mgd_wext_connect(rdev, wdev);
267 out: 287 out:
268 wdev_unlock(wdev); 288 wdev_unlock(wdev);
269 cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); 289 mutex_unlock(&rdev->devlist_mtx);
290 cfg80211_unlock_rdev(rdev);
270 return err; 291 return err;
271} 292}
272 293