aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-08-14 15:29:17 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-14 15:29:17 -0400
commita8519de4a030d130e0d18147a2af3112b7951e0b (patch)
tree59f89418cf7f311d896c38ff774398e052b709d8 /net
parent5c16807d3d196203d2d3c9fae51ac7e422091904 (diff)
parent560ad81b6c90e0fddc4d6c280f16ddf18d47eeb1 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/Kconfig8
-rw-r--r--net/mac80211/cfg.c4
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/main.c16
-rw-r--r--net/mac80211/mesh.c145
-rw-r--r--net/mac80211/mesh.h30
-rw-r--r--net/mac80211/mesh_hwmp.c17
-rw-r--r--net/mac80211/mesh_pathtbl.c151
-rw-r--r--net/mac80211/mesh_plink.c2
-rw-r--r--net/mac80211/mlme.c31
-rw-r--r--net/mac80211/rc80211_minstrel.c16
-rw-r--r--net/mac80211/rx.c45
-rw-r--r--net/mac80211/scan.c10
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/tx.c158
-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
29 files changed, 801 insertions, 430 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 7dd77b6d4c9a..9db4ff836a3d 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -66,12 +66,12 @@ endmenu
66config MAC80211_MESH 66config MAC80211_MESH
67 bool "Enable mac80211 mesh networking (pre-802.11s) support" 67 bool "Enable mac80211 mesh networking (pre-802.11s) support"
68 depends on MAC80211 && EXPERIMENTAL 68 depends on MAC80211 && EXPERIMENTAL
69 depends on BROKEN
70 ---help--- 69 ---help---
71 This options enables support of Draft 802.11s mesh networking. 70 This options enables support of Draft 802.11s mesh networking.
72 The implementation is based on Draft 1.08 of the Mesh Networking 71 The implementation is based on Draft 2.08 of the Mesh Networking
73 amendment. For more information visit http://o11s.org/. 72 amendment. However, no compliance with that draft is claimed or even
74 73 possible, as drafts leave a number of identifiers to be defined after
74 ratification. For more information visit http://o11s.org/.
75 75
76config MAC80211_LEDS 76config MAC80211_LEDS
77 bool "Enable LED triggers" 77 bool "Enable LED triggers"
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4bbf5007799b..5608f6c68413 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -323,6 +323,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
323{ 323{
324 struct ieee80211_sub_if_data *sdata = sta->sdata; 324 struct ieee80211_sub_if_data *sdata = sta->sdata;
325 325
326 sinfo->generation = sdata->local->sta_generation;
327
326 sinfo->filled = STATION_INFO_INACTIVE_TIME | 328 sinfo->filled = STATION_INFO_INACTIVE_TIME |
327 STATION_INFO_RX_BYTES | 329 STATION_INFO_RX_BYTES |
328 STATION_INFO_TX_BYTES | 330 STATION_INFO_TX_BYTES |
@@ -909,6 +911,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
909 else 911 else
910 memset(next_hop, 0, ETH_ALEN); 912 memset(next_hop, 0, ETH_ALEN);
911 913
914 pinfo->generation = mesh_paths_generation;
915
912 pinfo->filled = MPATH_INFO_FRAME_QLEN | 916 pinfo->filled = MPATH_INFO_FRAME_QLEN |
913 MPATH_INFO_DSN | 917 MPATH_INFO_DSN |
914 MPATH_INFO_METRIC | 918 MPATH_INFO_METRIC |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 630a438180fd..a6abc7dfd903 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -284,6 +284,7 @@ struct ieee80211_if_managed {
284 284
285 struct mutex mtx; 285 struct mutex mtx;
286 struct ieee80211_bss *associated; 286 struct ieee80211_bss *associated;
287 struct ieee80211_mgd_work *old_associate_work;
287 struct list_head work_list; 288 struct list_head work_list;
288 289
289 u8 bssid[ETH_ALEN]; 290 u8 bssid[ETH_ALEN];
@@ -354,7 +355,7 @@ struct ieee80211_if_mesh {
354 355
355 unsigned long timers_running; 356 unsigned long timers_running;
356 357
357 bool housekeeping; 358 unsigned long wrkq_flags;
358 359
359 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; 360 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
360 size_t mesh_id_len; 361 size_t mesh_id_len;
@@ -677,6 +678,7 @@ struct ieee80211_local {
677 struct list_head sta_list; 678 struct list_head sta_list;
678 struct sta_info *sta_hash[STA_HASH_SIZE]; 679 struct sta_info *sta_hash[STA_HASH_SIZE];
679 struct timer_list sta_cleanup; 680 struct timer_list sta_cleanup;
681 int sta_generation;
680 682
681 struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; 683 struct sk_buff_head pending[IEEE80211_MAX_QUEUES];
682 struct tasklet_struct tx_pending_tasklet; 684 struct tasklet_struct tx_pending_tasklet;
@@ -713,7 +715,7 @@ struct ieee80211_local {
713 struct mutex scan_mtx; 715 struct mutex scan_mtx;
714 unsigned long scanning; 716 unsigned long scanning;
715 struct cfg80211_ssid scan_ssid; 717 struct cfg80211_ssid scan_ssid;
716 struct cfg80211_scan_request int_scan_req; 718 struct cfg80211_scan_request *int_scan_req;
717 struct cfg80211_scan_request *scan_req; 719 struct cfg80211_scan_request *scan_req;
718 struct ieee80211_channel *scan_channel; 720 struct ieee80211_channel *scan_channel;
719 const u8 *orig_ies; 721 const u8 *orig_ies;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0c4f8e122ed6..b03fd84777fa 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -765,9 +765,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
765 supp_ht = supp_ht || sband->ht_cap.ht_supported; 765 supp_ht = supp_ht || sband->ht_cap.ht_supported;
766 } 766 }
767 767
768 local->int_scan_req.n_channels = channels; 768 local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
769 local->int_scan_req.channels = kzalloc(sizeof(void *) * channels, GFP_KERNEL); 769 sizeof(void *) * channels, GFP_KERNEL);
770 if (!local->int_scan_req.channels) 770 if (!local->int_scan_req)
771 return -ENOMEM; 771 return -ENOMEM;
772 772
773 /* if low-level driver supports AP, we also support VLAN */ 773 /* if low-level driver supports AP, we also support VLAN */
@@ -882,13 +882,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
882 882
883 /* alloc internal scan request */ 883 /* alloc internal scan request */
884 i = 0; 884 i = 0;
885 local->int_scan_req.ssids = &local->scan_ssid; 885 local->int_scan_req->ssids = &local->scan_ssid;
886 local->int_scan_req.n_ssids = 1; 886 local->int_scan_req->n_ssids = 1;
887 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 887 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
888 if (!hw->wiphy->bands[band]) 888 if (!hw->wiphy->bands[band])
889 continue; 889 continue;
890 for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) { 890 for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
891 local->int_scan_req.channels[i] = 891 local->int_scan_req->channels[i] =
892 &hw->wiphy->bands[band]->channels[j]; 892 &hw->wiphy->bands[band]->channels[j];
893 i++; 893 i++;
894 } 894 }
@@ -920,7 +920,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
920 fail_workqueue: 920 fail_workqueue:
921 wiphy_unregister(local->hw.wiphy); 921 wiphy_unregister(local->hw.wiphy);
922 fail_wiphy_register: 922 fail_wiphy_register:
923 kfree(local->int_scan_req.channels); 923 kfree(local->int_scan_req->channels);
924 return result; 924 return result;
925} 925}
926EXPORT_SYMBOL(ieee80211_register_hw); 926EXPORT_SYMBOL(ieee80211_register_hw);
@@ -962,7 +962,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
962 wiphy_unregister(local->hw.wiphy); 962 wiphy_unregister(local->hw.wiphy);
963 ieee80211_wep_free(local); 963 ieee80211_wep_free(local);
964 ieee80211_led_exit(local); 964 ieee80211_led_exit(local);
965 kfree(local->int_scan_req.channels); 965 kfree(local->int_scan_req);
966} 966}
967EXPORT_SYMBOL(ieee80211_unregister_hw); 967EXPORT_SYMBOL(ieee80211_unregister_hw);
968 968
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 2f4f518ab45c..3185e18c8214 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -47,14 +47,14 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
47 struct ieee80211_local *local = sdata->local; 47 struct ieee80211_local *local = sdata->local;
48 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 48 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
49 49
50 ifmsh->housekeeping = true; 50 ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
51 51
52 if (local->quiescing) { 52 if (local->quiescing) {
53 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); 53 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
54 return; 54 return;
55 } 55 }
56 56
57 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); 57 ieee80211_queue_work(&local->hw, &ifmsh->work);
58} 58}
59 59
60/** 60/**
@@ -320,30 +320,6 @@ struct mesh_table *mesh_table_alloc(int size_order)
320 return newtbl; 320 return newtbl;
321} 321}
322 322
323static void __mesh_table_free(struct mesh_table *tbl)
324{
325 kfree(tbl->hash_buckets);
326 kfree(tbl->hashwlock);
327 kfree(tbl);
328}
329
330void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
331{
332 struct hlist_head *mesh_hash;
333 struct hlist_node *p, *q;
334 int i;
335
336 mesh_hash = tbl->hash_buckets;
337 for (i = 0; i <= tbl->hash_mask; i++) {
338 spin_lock(&tbl->hashwlock[i]);
339 hlist_for_each_safe(p, q, &mesh_hash[i]) {
340 tbl->free_node(p, free_leafs);
341 atomic_dec(&tbl->entries);
342 }
343 spin_unlock(&tbl->hashwlock[i]);
344 }
345 __mesh_table_free(tbl);
346}
347 323
348static void ieee80211_mesh_path_timer(unsigned long data) 324static void ieee80211_mesh_path_timer(unsigned long data)
349{ 325{
@@ -357,63 +333,79 @@ static void ieee80211_mesh_path_timer(unsigned long data)
357 return; 333 return;
358 } 334 }
359 335
360 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); 336 ieee80211_queue_work(&local->hw, &ifmsh->work);
361} 337}
362 338
363struct mesh_table *mesh_table_grow(struct mesh_table *tbl) 339/**
364{ 340 * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
365 struct mesh_table *newtbl; 341 * @hdr: 802.11 frame header
366 struct hlist_head *oldhash; 342 * @fc: frame control field
367 struct hlist_node *p, *q; 343 * @meshda: destination address in the mesh
368 int i; 344 * @meshsa: source address address in the mesh. Same as TA, as frame is
369 345 * locally originated.
370 if (atomic_read(&tbl->entries) 346 *
371 < tbl->mean_chain_len * (tbl->hash_mask + 1)) 347 * Return the length of the 802.11 (does not include a mesh control header)
372 goto endgrow; 348 */
373 349int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char
374 newtbl = mesh_table_alloc(tbl->size_order + 1); 350 *meshda, char *meshsa) {
375 if (!newtbl) 351 if (is_multicast_ether_addr(meshda)) {
376 goto endgrow; 352 *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
377 353 /* DA TA SA */
378 newtbl->free_node = tbl->free_node; 354 memcpy(hdr->addr1, meshda, ETH_ALEN);
379 newtbl->mean_chain_len = tbl->mean_chain_len; 355 memcpy(hdr->addr2, meshsa, ETH_ALEN);
380 newtbl->copy_node = tbl->copy_node; 356 memcpy(hdr->addr3, meshsa, ETH_ALEN);
381 atomic_set(&newtbl->entries, atomic_read(&tbl->entries)); 357 return 24;
382 358 } else {
383 oldhash = tbl->hash_buckets; 359 *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
384 for (i = 0; i <= tbl->hash_mask; i++) 360 IEEE80211_FCTL_TODS);
385 hlist_for_each(p, &oldhash[i]) 361 /* RA TA DA SA */
386 if (tbl->copy_node(p, newtbl) < 0) 362 memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */
387 goto errcopy; 363 memcpy(hdr->addr2, meshsa, ETH_ALEN);
388 364 memcpy(hdr->addr3, meshda, ETH_ALEN);
389 return newtbl; 365 memcpy(hdr->addr4, meshsa, ETH_ALEN);
390 366 return 30;
391errcopy:
392 for (i = 0; i <= newtbl->hash_mask; i++) {
393 hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
394 tbl->free_node(p, 0);
395 } 367 }
396 __mesh_table_free(newtbl);
397endgrow:
398 return NULL;
399} 368}
400 369
401/** 370/**
402 * ieee80211_new_mesh_header - create a new mesh header 371 * ieee80211_new_mesh_header - create a new mesh header
403 * @meshhdr: uninitialized mesh header 372 * @meshhdr: uninitialized mesh header
404 * @sdata: mesh interface to be used 373 * @sdata: mesh interface to be used
374 * @addr4: addr4 of the mesh frame (1st in ae header)
375 * may be NULL
376 * @addr5: addr5 of the mesh frame (1st or 2nd in ae header)
377 * may be NULL unless addr6 is present
378 * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header)
379 * may be NULL unless addr5 is present
405 * 380 *
406 * Return the header length. 381 * Return the header length.
407 */ 382 */
408int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, 383int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
409 struct ieee80211_sub_if_data *sdata) 384 struct ieee80211_sub_if_data *sdata, char *addr4,
385 char *addr5, char *addr6)
410{ 386{
411 meshhdr->flags = 0; 387 int aelen = 0;
388 memset(meshhdr, 0, sizeof(meshhdr));
412 meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; 389 meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
413 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); 390 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
414 sdata->u.mesh.mesh_seqnum++; 391 sdata->u.mesh.mesh_seqnum++;
415 392 if (addr4) {
416 return 6; 393 meshhdr->flags |= MESH_FLAGS_AE_A4;
394 aelen += ETH_ALEN;
395 memcpy(meshhdr->eaddr1, addr4, ETH_ALEN);
396 }
397 if (addr5 && addr6) {
398 meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
399 aelen += 2 * ETH_ALEN;
400 if (!addr4) {
401 memcpy(meshhdr->eaddr1, addr5, ETH_ALEN);
402 memcpy(meshhdr->eaddr2, addr6, ETH_ALEN);
403 } else {
404 memcpy(meshhdr->eaddr2, addr5, ETH_ALEN);
405 memcpy(meshhdr->eaddr3, addr6, ETH_ALEN);
406 }
407 }
408 return 6 + aelen;
417} 409}
418 410
419static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, 411static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
@@ -433,7 +425,6 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
433 if (free_plinks != sdata->u.mesh.accepting_plinks) 425 if (free_plinks != sdata->u.mesh.accepting_plinks)
434 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); 426 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
435 427
436 ifmsh->housekeeping = false;
437 mod_timer(&ifmsh->housekeeping_timer, 428 mod_timer(&ifmsh->housekeeping_timer,
438 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); 429 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
439} 430}
@@ -470,10 +461,12 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
470 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 461 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
471 struct ieee80211_local *local = sdata->local; 462 struct ieee80211_local *local = sdata->local;
472 463
473 ifmsh->housekeeping = true; 464 ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
474 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); 465 ieee80211_queue_work(&local->hw, &ifmsh->work);
466 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
475 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | 467 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
476 BSS_CHANGED_BEACON_ENABLED); 468 BSS_CHANGED_BEACON_ENABLED |
469 BSS_CHANGED_BEACON_INT);
477} 470}
478 471
479void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) 472void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
@@ -608,7 +601,13 @@ static void ieee80211_mesh_work(struct work_struct *work)
608 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) 601 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
609 mesh_path_start_discovery(sdata); 602 mesh_path_start_discovery(sdata);
610 603
611 if (ifmsh->housekeeping) 604 if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
605 mesh_mpath_table_grow();
606
607 if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
608 mesh_mpp_table_grow();
609
610 if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
612 ieee80211_mesh_housekeeping(sdata, ifmsh); 611 ieee80211_mesh_housekeeping(sdata, ifmsh);
613} 612}
614 613
@@ -619,7 +618,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
619 rcu_read_lock(); 618 rcu_read_lock();
620 list_for_each_entry_rcu(sdata, &local->interfaces, list) 619 list_for_each_entry_rcu(sdata, &local->interfaces, list)
621 if (ieee80211_vif_is_mesh(&sdata->vif)) 620 if (ieee80211_vif_is_mesh(&sdata->vif))
622 ieee80211_queue_work(local->hw.workqueue, &sdata->u.mesh.work); 621 ieee80211_queue_work(&local->hw, &sdata->u.mesh.work);
623 rcu_read_unlock(); 622 rcu_read_unlock();
624} 623}
625 624
@@ -692,7 +691,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
692 case IEEE80211_STYPE_PROBE_RESP: 691 case IEEE80211_STYPE_PROBE_RESP:
693 case IEEE80211_STYPE_BEACON: 692 case IEEE80211_STYPE_BEACON:
694 skb_queue_tail(&ifmsh->skb_queue, skb); 693 skb_queue_tail(&ifmsh->skb_queue, skb);
695 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); 694 ieee80211_queue_work(&local->hw, &ifmsh->work);
696 return RX_QUEUED; 695 return RX_QUEUED;
697 } 696 }
698 697
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 2a2ed182cb7e..eb23fc639b2b 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -44,6 +44,23 @@ enum mesh_path_flags {
44}; 44};
45 45
46/** 46/**
47 * enum mesh_deferred_task_flags - mac80211 mesh deferred tasks
48 *
49 *
50 *
51 * @MESH_WORK_HOUSEKEEPING: run the periodic mesh housekeeping tasks
52 * @MESH_WORK_GROW_MPATH_TABLE: the mesh path table is full and needs
53 * to grow.
54 * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to
55 * grow
56 */
57enum mesh_deferred_task_flags {
58 MESH_WORK_HOUSEKEEPING,
59 MESH_WORK_GROW_MPATH_TABLE,
60 MESH_WORK_GROW_MPP_TABLE,
61};
62
63/**
47 * struct mesh_path - mac80211 mesh path structure 64 * struct mesh_path - mac80211 mesh path structure
48 * 65 *
49 * @dst: mesh path destination mac address 66 * @dst: mesh path destination mac address
@@ -61,7 +78,7 @@ enum mesh_path_flags {
61 * retry 78 * retry
62 * @discovery_retries: number of discovery retries 79 * @discovery_retries: number of discovery retries
63 * @flags: mesh path flags, as specified on &enum mesh_path_flags 80 * @flags: mesh path flags, as specified on &enum mesh_path_flags
64 * @state_lock: mesh pat state lock 81 * @state_lock: mesh path state lock
65 * 82 *
66 * 83 *
67 * The combination of dst and sdata is unique in the mesh path table. Since the 84 * The combination of dst and sdata is unique in the mesh path table. Since the
@@ -174,6 +191,7 @@ struct mesh_rmc {
174 */ 191 */
175#define MESH_PATH_REFRESH_TIME 1000 192#define MESH_PATH_REFRESH_TIME 1000
176#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME) 193#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
194#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */
177 195
178#define MESH_MAX_PREQ_RETRIES 4 196#define MESH_MAX_PREQ_RETRIES 4
179#define MESH_PATH_EXPIRE (600 * HZ) 197#define MESH_PATH_EXPIRE (600 * HZ)
@@ -193,8 +211,11 @@ struct mesh_rmc {
193 211
194/* Public interfaces */ 212/* Public interfaces */
195/* Various */ 213/* Various */
214int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
215 char *da, char *sa);
196int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, 216int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
197 struct ieee80211_sub_if_data *sdata); 217 struct ieee80211_sub_if_data *sdata, char *addr4,
218 char *addr5, char *addr6);
198int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, 219int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
199 struct ieee80211_sub_if_data *sdata); 220 struct ieee80211_sub_if_data *sdata);
200bool mesh_matches_local(struct ieee802_11_elems *ie, 221bool mesh_matches_local(struct ieee802_11_elems *ie,
@@ -246,7 +267,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
246/* Mesh tables */ 267/* Mesh tables */
247struct mesh_table *mesh_table_alloc(int size_order); 268struct mesh_table *mesh_table_alloc(int size_order);
248void mesh_table_free(struct mesh_table *tbl, bool free_leafs); 269void mesh_table_free(struct mesh_table *tbl, bool free_leafs);
249struct mesh_table *mesh_table_grow(struct mesh_table *tbl); 270void mesh_mpath_table_grow(void);
271void mesh_mpp_table_grow(void);
250u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, 272u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata,
251 struct mesh_table *tbl); 273 struct mesh_table *tbl);
252/* Mesh paths */ 274/* Mesh paths */
@@ -265,6 +287,8 @@ void mesh_path_discard_frame(struct sk_buff *skb,
265void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); 287void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
266void mesh_path_restart(struct ieee80211_sub_if_data *sdata); 288void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
267 289
290extern int mesh_paths_generation;
291
268#ifdef CONFIG_MAC80211_MESH 292#ifdef CONFIG_MAC80211_MESH
269extern int mesh_allocated; 293extern int mesh_allocated;
270 294
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 11ab71a68ff9..ef1efd362691 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -397,7 +397,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
397 397
398static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, 398static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
399 struct ieee80211_mgmt *mgmt, 399 struct ieee80211_mgmt *mgmt,
400 u8 *preq_elem, u32 metric) { 400 u8 *preq_elem, u32 metric)
401{
401 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 402 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
402 struct mesh_path *mpath; 403 struct mesh_path *mpath;
403 u8 *dst_addr, *orig_addr; 404 u8 *dst_addr, *orig_addr;
@@ -430,7 +431,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
430 if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || 431 if ((!(mpath->flags & MESH_PATH_DSN_VALID)) ||
431 DSN_LT(mpath->dsn, dst_dsn)) { 432 DSN_LT(mpath->dsn, dst_dsn)) {
432 mpath->dsn = dst_dsn; 433 mpath->dsn = dst_dsn;
433 mpath->flags &= MESH_PATH_DSN_VALID; 434 mpath->flags |= MESH_PATH_DSN_VALID;
434 } else if ((!(dst_flags & MP_F_DO)) && 435 } else if ((!(dst_flags & MP_F_DO)) &&
435 (mpath->flags & MESH_PATH_ACTIVE)) { 436 (mpath->flags & MESH_PATH_ACTIVE)) {
436 reply = true; 437 reply = true;
@@ -660,14 +661,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
660 spin_unlock(&ifmsh->mesh_preq_queue_lock); 661 spin_unlock(&ifmsh->mesh_preq_queue_lock);
661 662
662 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) 663 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
663 ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work); 664 ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
664 665
665 else if (time_before(jiffies, ifmsh->last_preq)) { 666 else if (time_before(jiffies, ifmsh->last_preq)) {
666 /* avoid long wait if did not send preqs for a long time 667 /* avoid long wait if did not send preqs for a long time
667 * and jiffies wrapped around 668 * and jiffies wrapped around
668 */ 669 */
669 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; 670 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
670 ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work); 671 ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
671 } else 672 } else
672 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + 673 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
673 min_preq_int_jiff(sdata)); 674 min_preq_int_jiff(sdata));
@@ -791,7 +792,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
791 } 792 }
792 793
793 if (mpath->flags & MESH_PATH_ACTIVE) { 794 if (mpath->flags & MESH_PATH_ACTIVE) {
794 if (time_after(jiffies, mpath->exp_time - 795 if (time_after(jiffies, mpath->exp_time +
795 msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) 796 msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
796 && !memcmp(sdata->dev->dev_addr, hdr->addr4, 797 && !memcmp(sdata->dev->dev_addr, hdr->addr4,
797 ETH_ALEN) 798 ETH_ALEN)
@@ -810,10 +811,8 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
810 } 811 }
811 812
812 if (skb_queue_len(&mpath->frame_queue) >= 813 if (skb_queue_len(&mpath->frame_queue) >=
813 MESH_FRAME_QUEUE_LEN) { 814 MESH_FRAME_QUEUE_LEN)
814 skb_to_free = mpath->frame_queue.next; 815 skb_to_free = skb_dequeue(&mpath->frame_queue);
815 skb_unlink(skb_to_free, &mpath->frame_queue);
816 }
817 816
818 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 817 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
819 skb_queue_tail(&mpath->frame_queue, skb); 818 skb_queue_tail(&mpath->frame_queue, skb);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 04b9e4d61b8e..751c4d0e2b36 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -38,6 +38,71 @@ struct mpath_node {
38static struct mesh_table *mesh_paths; 38static struct mesh_table *mesh_paths;
39static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ 39static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
40 40
41int mesh_paths_generation;
42static void __mesh_table_free(struct mesh_table *tbl)
43{
44 kfree(tbl->hash_buckets);
45 kfree(tbl->hashwlock);
46 kfree(tbl);
47}
48
49void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
50{
51 struct hlist_head *mesh_hash;
52 struct hlist_node *p, *q;
53 int i;
54
55 mesh_hash = tbl->hash_buckets;
56 for (i = 0; i <= tbl->hash_mask; i++) {
57 spin_lock(&tbl->hashwlock[i]);
58 hlist_for_each_safe(p, q, &mesh_hash[i]) {
59 tbl->free_node(p, free_leafs);
60 atomic_dec(&tbl->entries);
61 }
62 spin_unlock(&tbl->hashwlock[i]);
63 }
64 __mesh_table_free(tbl);
65}
66
67static struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
68{
69 struct mesh_table *newtbl;
70 struct hlist_head *oldhash;
71 struct hlist_node *p, *q;
72 int i;
73
74 if (atomic_read(&tbl->entries)
75 < tbl->mean_chain_len * (tbl->hash_mask + 1))
76 goto endgrow;
77
78 newtbl = mesh_table_alloc(tbl->size_order + 1);
79 if (!newtbl)
80 goto endgrow;
81
82 newtbl->free_node = tbl->free_node;
83 newtbl->mean_chain_len = tbl->mean_chain_len;
84 newtbl->copy_node = tbl->copy_node;
85 atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
86
87 oldhash = tbl->hash_buckets;
88 for (i = 0; i <= tbl->hash_mask; i++)
89 hlist_for_each(p, &oldhash[i])
90 if (tbl->copy_node(p, newtbl) < 0)
91 goto errcopy;
92
93 return newtbl;
94
95errcopy:
96 for (i = 0; i <= newtbl->hash_mask; i++) {
97 hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
98 tbl->free_node(p, 0);
99 }
100 __mesh_table_free(newtbl);
101endgrow:
102 return NULL;
103}
104
105
41/* This lock will have the grow table function as writer and add / delete nodes 106/* This lock will have the grow table function as writer and add / delete nodes
42 * as readers. When reading the table (i.e. doing lookups) we are well protected 107 * as readers. When reading the table (i.e. doing lookups) we are well protected
43 * by RCU 108 * by RCU
@@ -185,6 +250,8 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
185 */ 250 */
186int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) 251int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
187{ 252{
253 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
254 struct ieee80211_local *local = sdata->local;
188 struct mesh_path *mpath, *new_mpath; 255 struct mesh_path *mpath, *new_mpath;
189 struct mpath_node *node, *new_node; 256 struct mpath_node *node, *new_node;
190 struct hlist_head *bucket; 257 struct hlist_head *bucket;
@@ -193,8 +260,6 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
193 int err = 0; 260 int err = 0;
194 u32 hash_idx; 261 u32 hash_idx;
195 262
196 might_sleep();
197
198 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) 263 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
199 /* never add ourselves as neighbours */ 264 /* never add ourselves as neighbours */
200 return -ENOTSUPP; 265 return -ENOTSUPP;
@@ -206,11 +271,11 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
206 return -ENOSPC; 271 return -ENOSPC;
207 272
208 err = -ENOMEM; 273 err = -ENOMEM;
209 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); 274 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
210 if (!new_mpath) 275 if (!new_mpath)
211 goto err_path_alloc; 276 goto err_path_alloc;
212 277
213 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); 278 new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
214 if (!new_node) 279 if (!new_node)
215 goto err_node_alloc; 280 goto err_node_alloc;
216 281
@@ -243,23 +308,13 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
243 mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1)) 308 mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1))
244 grow = 1; 309 grow = 1;
245 310
311 mesh_paths_generation++;
312
246 spin_unlock(&mesh_paths->hashwlock[hash_idx]); 313 spin_unlock(&mesh_paths->hashwlock[hash_idx]);
247 read_unlock(&pathtbl_resize_lock); 314 read_unlock(&pathtbl_resize_lock);
248 if (grow) { 315 if (grow) {
249 struct mesh_table *oldtbl, *newtbl; 316 set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
250 317 ieee80211_queue_work(&local->hw, &ifmsh->work);
251 write_lock(&pathtbl_resize_lock);
252 oldtbl = mesh_paths;
253 newtbl = mesh_table_grow(mesh_paths);
254 if (!newtbl) {
255 write_unlock(&pathtbl_resize_lock);
256 return 0;
257 }
258 rcu_assign_pointer(mesh_paths, newtbl);
259 write_unlock(&pathtbl_resize_lock);
260
261 synchronize_rcu();
262 mesh_table_free(oldtbl, false);
263 } 318 }
264 return 0; 319 return 0;
265 320
@@ -274,9 +329,46 @@ err_path_alloc:
274 return err; 329 return err;
275} 330}
276 331
332void mesh_mpath_table_grow(void)
333{
334 struct mesh_table *oldtbl, *newtbl;
335
336 write_lock(&pathtbl_resize_lock);
337 oldtbl = mesh_paths;
338 newtbl = mesh_table_grow(mesh_paths);
339 if (!newtbl) {
340 write_unlock(&pathtbl_resize_lock);
341 return;
342 }
343 rcu_assign_pointer(mesh_paths, newtbl);
344 write_unlock(&pathtbl_resize_lock);
345
346 synchronize_rcu();
347 mesh_table_free(oldtbl, false);
348}
349
350void mesh_mpp_table_grow(void)
351{
352 struct mesh_table *oldtbl, *newtbl;
353
354 write_lock(&pathtbl_resize_lock);
355 oldtbl = mpp_paths;
356 newtbl = mesh_table_grow(mpp_paths);
357 if (!newtbl) {
358 write_unlock(&pathtbl_resize_lock);
359 return;
360 }
361 rcu_assign_pointer(mpp_paths, newtbl);
362 write_unlock(&pathtbl_resize_lock);
363
364 synchronize_rcu();
365 mesh_table_free(oldtbl, false);
366}
277 367
278int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) 368int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
279{ 369{
370 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
371 struct ieee80211_local *local = sdata->local;
280 struct mesh_path *mpath, *new_mpath; 372 struct mesh_path *mpath, *new_mpath;
281 struct mpath_node *node, *new_node; 373 struct mpath_node *node, *new_node;
282 struct hlist_head *bucket; 374 struct hlist_head *bucket;
@@ -285,8 +377,6 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
285 int err = 0; 377 int err = 0;
286 u32 hash_idx; 378 u32 hash_idx;
287 379
288 might_sleep();
289
290 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) 380 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
291 /* never add ourselves as neighbours */ 381 /* never add ourselves as neighbours */
292 return -ENOTSUPP; 382 return -ENOTSUPP;
@@ -295,11 +385,11 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
295 return -ENOTSUPP; 385 return -ENOTSUPP;
296 386
297 err = -ENOMEM; 387 err = -ENOMEM;
298 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); 388 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
299 if (!new_mpath) 389 if (!new_mpath)
300 goto err_path_alloc; 390 goto err_path_alloc;
301 391
302 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); 392 new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
303 if (!new_node) 393 if (!new_node)
304 goto err_node_alloc; 394 goto err_node_alloc;
305 395
@@ -333,20 +423,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
333 spin_unlock(&mpp_paths->hashwlock[hash_idx]); 423 spin_unlock(&mpp_paths->hashwlock[hash_idx]);
334 read_unlock(&pathtbl_resize_lock); 424 read_unlock(&pathtbl_resize_lock);
335 if (grow) { 425 if (grow) {
336 struct mesh_table *oldtbl, *newtbl; 426 set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
337 427 ieee80211_queue_work(&local->hw, &ifmsh->work);
338 write_lock(&pathtbl_resize_lock);
339 oldtbl = mpp_paths;
340 newtbl = mesh_table_grow(mpp_paths);
341 if (!newtbl) {
342 write_unlock(&pathtbl_resize_lock);
343 return 0;
344 }
345 rcu_assign_pointer(mpp_paths, newtbl);
346 write_unlock(&pathtbl_resize_lock);
347
348 synchronize_rcu();
349 mesh_table_free(oldtbl, false);
350 } 428 }
351 return 0; 429 return 0;
352 430
@@ -484,6 +562,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
484 562
485 err = -ENXIO; 563 err = -ENXIO;
486enddel: 564enddel:
565 mesh_paths_generation++;
487 spin_unlock(&mesh_paths->hashwlock[hash_idx]); 566 spin_unlock(&mesh_paths->hashwlock[hash_idx]);
488 read_unlock(&pathtbl_resize_lock); 567 read_unlock(&pathtbl_resize_lock);
489 return err; 568 return err;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index cb14253587f1..ffcbad75e09b 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -409,7 +409,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
409 baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt; 409 baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;
410 if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) { 410 if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {
411 baseaddr += 4; 411 baseaddr += 4;
412 baselen -= 4; 412 baselen += 4;
413 } 413 }
414 ieee802_11_parse_elems(baseaddr, len - baselen, &elems); 414 ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
415 if (!elems.peer_link) { 415 if (!elems.peer_link) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6d5a1ee0445f..c374d2d73fa4 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -880,10 +880,11 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
880} 880}
881 881
882static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, 882static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
883 struct ieee80211_bss *bss, 883 struct ieee80211_mgd_work *wk,
884 u32 bss_info_changed) 884 u32 bss_info_changed)
885{ 885{
886 struct ieee80211_local *local = sdata->local; 886 struct ieee80211_local *local = sdata->local;
887 struct ieee80211_bss *bss = wk->bss;
887 888
888 bss_info_changed |= BSS_CHANGED_ASSOC; 889 bss_info_changed |= BSS_CHANGED_ASSOC;
889 /* set timing information */ 890 /* set timing information */
@@ -896,6 +897,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
896 bss->cbss.capability, bss->has_erp_value, bss->erp_value); 897 bss->cbss.capability, bss->has_erp_value, bss->erp_value);
897 898
898 sdata->u.mgd.associated = bss; 899 sdata->u.mgd.associated = bss;
900 sdata->u.mgd.old_associate_work = wk;
899 memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); 901 memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
900 902
901 /* just to be sure */ 903 /* just to be sure */
@@ -1010,7 +1012,8 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
1010 return RX_MGMT_NONE; 1012 return RX_MGMT_NONE;
1011} 1013}
1012 1014
1013static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) 1015static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1016 bool deauth)
1014{ 1017{
1015 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1018 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1016 struct ieee80211_local *local = sdata->local; 1019 struct ieee80211_local *local = sdata->local;
@@ -1028,6 +1031,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
1028 ifmgd->associated = NULL; 1031 ifmgd->associated = NULL;
1029 memset(ifmgd->bssid, 0, ETH_ALEN); 1032 memset(ifmgd->bssid, 0, ETH_ALEN);
1030 1033
1034 if (deauth) {
1035 kfree(ifmgd->old_associate_work);
1036 ifmgd->old_associate_work = NULL;
1037 } else {
1038 struct ieee80211_mgd_work *wk = ifmgd->old_associate_work;
1039
1040 wk->state = IEEE80211_MGD_STATE_IDLE;
1041 list_add(&wk->list, &ifmgd->work_list);
1042 }
1043
1031 /* 1044 /*
1032 * we need to commit the associated = NULL change because the 1045 * we need to commit the associated = NULL change because the
1033 * scan code uses that to determine whether this iface should 1046 * scan code uses that to determine whether this iface should
@@ -1345,7 +1358,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1345 sdata->dev->name, bssid, reason_code); 1358 sdata->dev->name, bssid, reason_code);
1346 1359
1347 if (!wk) { 1360 if (!wk) {
1348 ieee80211_set_disassoc(sdata); 1361 ieee80211_set_disassoc(sdata, true);
1349 } else { 1362 } else {
1350 list_del(&wk->list); 1363 list_del(&wk->list);
1351 kfree(wk); 1364 kfree(wk);
@@ -1378,7 +1391,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1378 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", 1391 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
1379 sdata->dev->name, reason_code); 1392 sdata->dev->name, reason_code);
1380 1393
1381 ieee80211_set_disassoc(sdata); 1394 ieee80211_set_disassoc(sdata, false);
1382 return RX_MGMT_CFG80211_DISASSOC; 1395 return RX_MGMT_CFG80211_DISASSOC;
1383} 1396}
1384 1397
@@ -1581,7 +1594,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1581 * ieee80211_set_associated() will tell the driver */ 1594 * ieee80211_set_associated() will tell the driver */
1582 bss_conf->aid = aid; 1595 bss_conf->aid = aid;
1583 bss_conf->assoc_capability = capab_info; 1596 bss_conf->assoc_capability = capab_info;
1584 ieee80211_set_associated(sdata, wk->bss, changed); 1597 /* this will take ownership of wk */
1598 ieee80211_set_associated(sdata, wk, changed);
1585 1599
1586 /* 1600 /*
1587 * Start timer to probe the connection to the AP now. 1601 * Start timer to probe the connection to the AP now.
@@ -1590,7 +1604,6 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1590 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); 1604 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
1591 mod_beacon_timer(sdata); 1605 mod_beacon_timer(sdata);
1592 1606
1593 kfree(wk);
1594 return RX_MGMT_CFG80211_ASSOC; 1607 return RX_MGMT_CFG80211_ASSOC;
1595} 1608}
1596 1609
@@ -2096,7 +2109,7 @@ static void ieee80211_sta_work(struct work_struct *work)
2096 printk(KERN_DEBUG "No probe response from AP %pM" 2109 printk(KERN_DEBUG "No probe response from AP %pM"
2097 " after %dms, disconnecting.\n", 2110 " after %dms, disconnecting.\n",
2098 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); 2111 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
2099 ieee80211_set_disassoc(sdata); 2112 ieee80211_set_disassoc(sdata, true);
2100 mutex_unlock(&ifmgd->mtx); 2113 mutex_unlock(&ifmgd->mtx);
2101 /* 2114 /*
2102 * must be outside lock due to cfg80211, 2115 * must be outside lock due to cfg80211,
@@ -2500,7 +2513,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2500 2513
2501 if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { 2514 if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
2502 bssid = req->bss->bssid; 2515 bssid = req->bss->bssid;
2503 ieee80211_set_disassoc(sdata); 2516 ieee80211_set_disassoc(sdata, true);
2504 } else list_for_each_entry(wk, &ifmgd->work_list, list) { 2517 } else list_for_each_entry(wk, &ifmgd->work_list, list) {
2505 if (&wk->bss->cbss == req->bss) { 2518 if (&wk->bss->cbss == req->bss) {
2506 bssid = req->bss->bssid; 2519 bssid = req->bss->bssid;
@@ -2552,7 +2565,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2552 return -ENOLINK; 2565 return -ENOLINK;
2553 } 2566 }
2554 2567
2555 ieee80211_set_disassoc(sdata); 2568 ieee80211_set_disassoc(sdata, false);
2556 2569
2557 mutex_unlock(&ifmgd->mtx); 2570 mutex_unlock(&ifmgd->mtx);
2558 2571
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 7c5142988bbb..007164919e02 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -51,6 +51,7 @@
51#include <linux/random.h> 51#include <linux/random.h>
52#include <linux/ieee80211.h> 52#include <linux/ieee80211.h>
53#include <net/mac80211.h> 53#include <net/mac80211.h>
54#include "mesh.h"
54#include "rate.h" 55#include "rate.h"
55#include "rc80211_minstrel.h" 56#include "rc80211_minstrel.h"
56 57
@@ -155,12 +156,16 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
155 struct sk_buff *skb) 156 struct sk_buff *skb)
156{ 157{
157 struct minstrel_sta_info *mi = priv_sta; 158 struct minstrel_sta_info *mi = priv_sta;
159 struct minstrel_priv *mp = (struct minstrel_priv *)priv;
158 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 160 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
159 struct ieee80211_tx_rate *ar = info->status.rates; 161 struct ieee80211_tx_rate *ar = info->status.rates;
162 struct ieee80211_local *local = hw_to_local(mp->hw);
163 struct sta_info *si;
160 int i, ndx; 164 int i, ndx;
161 int success; 165 int success;
162 166
163 success = !!(info->flags & IEEE80211_TX_STAT_ACK); 167 success = !!(info->flags & IEEE80211_TX_STAT_ACK);
168 si = sta_info_get(local, sta->addr);
164 169
165 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 170 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
166 if (ar[i].idx < 0) 171 if (ar[i].idx < 0)
@@ -172,8 +177,17 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
172 177
173 mi->r[ndx].attempts += ar[i].count; 178 mi->r[ndx].attempts += ar[i].count;
174 179
175 if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) 180 if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
176 mi->r[ndx].success += success; 181 mi->r[ndx].success += success;
182 if (si) {
183 si->fail_avg = (18050 - mi->r[ndx].probability)
184 / 180;
185 WARN_ON(si->fail_avg > 100);
186 if (si->fail_avg == 100 &&
187 ieee80211_vif_is_mesh(&si->sdata->vif))
188 mesh_plink_broken(si);
189 }
190 }
177 } 191 }
178 192
179 if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) 193 if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 25a669c86e14..4cd9e45b1443 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -489,12 +489,21 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
489{ 489{
490 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 490 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
491 unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); 491 unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
492 char *dev_addr = rx->dev->dev_addr;
492 493
493 if (ieee80211_is_data(hdr->frame_control)) { 494 if (ieee80211_is_data(hdr->frame_control)) {
494 if (!ieee80211_has_a4(hdr->frame_control)) 495 if (is_multicast_ether_addr(hdr->addr1)) {
495 return RX_DROP_MONITOR; 496 if (ieee80211_has_tods(hdr->frame_control) ||
496 if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0) 497 !ieee80211_has_fromds(hdr->frame_control))
497 return RX_DROP_MONITOR; 498 return RX_DROP_MONITOR;
499 if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0)
500 return RX_DROP_MONITOR;
501 } else {
502 if (!ieee80211_has_a4(hdr->frame_control))
503 return RX_DROP_MONITOR;
504 if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0)
505 return RX_DROP_MONITOR;
506 }
498 } 507 }
499 508
500 /* If there is not an established peer link and this is not a peer link 509 /* If there is not an established peer link and this is not a peer link
@@ -527,7 +536,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
527 536
528 if (ieee80211_is_data(hdr->frame_control) && 537 if (ieee80211_is_data(hdr->frame_control) &&
529 is_multicast_ether_addr(hdr->addr1) && 538 is_multicast_ether_addr(hdr->addr1) &&
530 mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) 539 mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata))
531 return RX_DROP_MONITOR; 540 return RX_DROP_MONITOR;
532#undef msh_h_get 541#undef msh_h_get
533 542
@@ -1495,7 +1504,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1495 /* illegal frame */ 1504 /* illegal frame */
1496 return RX_DROP_MONITOR; 1505 return RX_DROP_MONITOR;
1497 1506
1498 if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ 1507 if (!is_multicast_ether_addr(hdr->addr1) &&
1508 (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6)) {
1499 struct mesh_path *mppath; 1509 struct mesh_path *mppath;
1500 1510
1501 rcu_read_lock(); 1511 rcu_read_lock();
@@ -1512,7 +1522,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1512 rcu_read_unlock(); 1522 rcu_read_unlock();
1513 } 1523 }
1514 1524
1515 if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) 1525 /* Frame has reached destination. Don't forward */
1526 if (!is_multicast_ether_addr(hdr->addr1) &&
1527 compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
1516 return RX_CONTINUE; 1528 return RX_CONTINUE;
1517 1529
1518 mesh_hdr->ttl--; 1530 mesh_hdr->ttl--;
@@ -1532,22 +1544,21 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1532 rx->dev->name); 1544 rx->dev->name);
1533 1545
1534 fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; 1546 fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
1535 /*
1536 * Save TA to addr1 to send TA a path error if a
1537 * suitable next hop is not found
1538 */
1539 memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN);
1540 memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); 1547 memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN);
1541 info = IEEE80211_SKB_CB(fwd_skb); 1548 info = IEEE80211_SKB_CB(fwd_skb);
1542 memset(info, 0, sizeof(*info)); 1549 memset(info, 0, sizeof(*info));
1543 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 1550 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
1544 info->control.vif = &rx->sdata->vif; 1551 info->control.vif = &rx->sdata->vif;
1545 ieee80211_select_queue(local, fwd_skb); 1552 ieee80211_select_queue(local, fwd_skb);
1546 if (is_multicast_ether_addr(fwd_hdr->addr3)) 1553 if (!is_multicast_ether_addr(fwd_hdr->addr1)) {
1547 memcpy(fwd_hdr->addr1, fwd_hdr->addr3, 1554 int err;
1555 /*
1556 * Save TA to addr1 to send TA a path error if a
1557 * suitable next hop is not found
1558 */
1559 memcpy(fwd_hdr->addr1, fwd_hdr->addr2,
1548 ETH_ALEN); 1560 ETH_ALEN);
1549 else { 1561 err = mesh_nexthop_lookup(fwd_skb, sdata);
1550 int err = mesh_nexthop_lookup(fwd_skb, sdata);
1551 /* Failed to immediately resolve next hop: 1562 /* Failed to immediately resolve next hop:
1552 * fwded frame was dropped or will be added 1563 * fwded frame was dropped or will be added
1553 * later to the pending skb queue. */ 1564 * later to the pending skb queue. */
@@ -1560,7 +1571,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1560 } 1571 }
1561 } 1572 }
1562 1573
1563 if (is_multicast_ether_addr(hdr->addr3) || 1574 if (is_multicast_ether_addr(hdr->addr1) ||
1564 rx->dev->flags & IFF_PROMISC) 1575 rx->dev->flags & IFF_PROMISC)
1565 return RX_CONTINUE; 1576 return RX_CONTINUE;
1566 else 1577 else
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 244f53f3c8b4..e091cbc3434f 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -277,7 +277,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
277 if (test_bit(SCAN_HW_SCANNING, &local->scanning)) 277 if (test_bit(SCAN_HW_SCANNING, &local->scanning))
278 ieee80211_restore_scan_ies(local); 278 ieee80211_restore_scan_ies(local);
279 279
280 if (local->scan_req != &local->int_scan_req) 280 if (local->scan_req != local->int_scan_req)
281 cfg80211_scan_done(local->scan_req, aborted); 281 cfg80211_scan_done(local->scan_req, aborted);
282 local->scan_req = NULL; 282 local->scan_req = NULL;
283 283
@@ -423,7 +423,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
423 local->scan_req = req; 423 local->scan_req = req;
424 local->scan_sdata = sdata; 424 local->scan_sdata = sdata;
425 425
426 if (req != &local->int_scan_req && 426 if (req != local->int_scan_req &&
427 sdata->vif.type == NL80211_IFTYPE_STATION && 427 sdata->vif.type == NL80211_IFTYPE_STATION &&
428 !list_empty(&ifmgd->work_list)) { 428 !list_empty(&ifmgd->work_list)) {
429 /* actually wait for the work it's doing to finish/time out */ 429 /* actually wait for the work it's doing to finish/time out */
@@ -743,10 +743,10 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
743 if (local->scan_req) 743 if (local->scan_req)
744 goto unlock; 744 goto unlock;
745 745
746 memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); 746 memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
747 local->int_scan_req.ssids[0].ssid_len = ssid_len; 747 local->int_scan_req->ssids[0].ssid_len = ssid_len;
748 748
749 ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req); 749 ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
750 unlock: 750 unlock:
751 mutex_unlock(&local->scan_mtx); 751 mutex_unlock(&local->scan_mtx);
752 return ret; 752 return ret;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a360bceeba59..eec001491e66 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -349,6 +349,7 @@ int sta_info_insert(struct sta_info *sta)
349 goto out_free; 349 goto out_free;
350 } 350 }
351 list_add(&sta->list, &local->sta_list); 351 list_add(&sta->list, &local->sta_list);
352 local->sta_generation++;
352 local->num_sta++; 353 local->num_sta++;
353 sta_info_hash_add(local, sta); 354 sta_info_hash_add(local, sta);
354 355
@@ -485,6 +486,7 @@ static void __sta_info_unlink(struct sta_info **sta)
485 } 486 }
486 487
487 local->num_sta--; 488 local->num_sta--;
489 local->sta_generation++;
488 490
489 if (local->ops->sta_notify) { 491 if (local->ops->sta_notify) {
490 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 492 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 7cffaa046b33..0c08d1e60cb5 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -317,30 +317,30 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
317 if (!atomic_read(&tx->sdata->bss->num_sta_ps)) 317 if (!atomic_read(&tx->sdata->bss->num_sta_ps))
318 return TX_CONTINUE; 318 return TX_CONTINUE;
319 319
320 /* buffered in hardware */
321 if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) {
322 info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
323
324 return TX_CONTINUE;
325 }
326
320 /* buffered in mac80211 */ 327 /* buffered in mac80211 */
321 if (tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) { 328 if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
322 if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) 329 purge_old_ps_buffers(tx->local);
323 purge_old_ps_buffers(tx->local); 330
324 if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= 331 if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= AP_MAX_BC_BUFFER) {
325 AP_MAX_BC_BUFFER) {
326#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG 332#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
327 if (net_ratelimit()) { 333 if (net_ratelimit())
328 printk(KERN_DEBUG "%s: BC TX buffer full - " 334 printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n",
329 "dropping the oldest frame\n", 335 tx->dev->name);
330 tx->dev->name);
331 }
332#endif 336#endif
333 dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); 337 dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
334 } else 338 } else
335 tx->local->total_ps_buffered++; 339 tx->local->total_ps_buffered++;
336 skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
337 return TX_QUEUED;
338 }
339 340
340 /* buffered in hardware */ 341 skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
341 info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
342 342
343 return TX_CONTINUE; 343 return TX_QUEUED;
344} 344}
345 345
346static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, 346static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
@@ -700,7 +700,6 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
700 /* for pure STA mode without beacons, we can do it */ 700 /* for pure STA mode without beacons, we can do it */
701 hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); 701 hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number);
702 tx->sdata->sequence_number += 0x10; 702 tx->sdata->sequence_number += 0x10;
703 tx->sdata->sequence_number &= IEEE80211_SCTL_SEQ;
704 return TX_CONTINUE; 703 return TX_CONTINUE;
705 } 704 }
706 705
@@ -844,6 +843,23 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
844} 843}
845 844
846static ieee80211_tx_result debug_noinline 845static ieee80211_tx_result debug_noinline
846ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
847{
848 struct sk_buff *skb = tx->skb;
849
850 if (!tx->sta)
851 return TX_CONTINUE;
852
853 tx->sta->tx_packets++;
854 do {
855 tx->sta->tx_fragments++;
856 tx->sta->tx_bytes += skb->len;
857 } while ((skb = skb->next));
858
859 return TX_CONTINUE;
860}
861
862static ieee80211_tx_result debug_noinline
847ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) 863ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
848{ 864{
849 if (!tx->key) 865 if (!tx->key)
@@ -887,23 +903,6 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
887 return TX_CONTINUE; 903 return TX_CONTINUE;
888} 904}
889 905
890static ieee80211_tx_result debug_noinline
891ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
892{
893 struct sk_buff *skb = tx->skb;
894
895 if (!tx->sta)
896 return TX_CONTINUE;
897
898 tx->sta->tx_packets++;
899 do {
900 tx->sta->tx_fragments++;
901 tx->sta->tx_bytes += skb->len;
902 } while ((skb = skb->next));
903
904 return TX_CONTINUE;
905}
906
907/* actual transmit path */ 906/* actual transmit path */
908 907
909/* 908/*
@@ -1154,6 +1153,9 @@ static int __ieee80211_tx(struct ieee80211_local *local,
1154 next = skb->next; 1153 next = skb->next;
1155 len = skb->len; 1154 len = skb->len;
1156 1155
1156 if (next)
1157 info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
1158
1157 sdata = vif_to_sdata(info->control.vif); 1159 sdata = vif_to_sdata(info->control.vif);
1158 1160
1159 switch (sdata->vif.type) { 1161 switch (sdata->vif.type) {
@@ -1210,9 +1212,9 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1210 CALL_TXH(ieee80211_tx_h_sequence) 1212 CALL_TXH(ieee80211_tx_h_sequence)
1211 CALL_TXH(ieee80211_tx_h_fragment) 1213 CALL_TXH(ieee80211_tx_h_fragment)
1212 /* handlers after fragment must be aware of tx info fragmentation! */ 1214 /* handlers after fragment must be aware of tx info fragmentation! */
1215 CALL_TXH(ieee80211_tx_h_stats)
1213 CALL_TXH(ieee80211_tx_h_encrypt) 1216 CALL_TXH(ieee80211_tx_h_encrypt)
1214 CALL_TXH(ieee80211_tx_h_calculate_duration) 1217 CALL_TXH(ieee80211_tx_h_calculate_duration)
1215 CALL_TXH(ieee80211_tx_h_stats)
1216#undef CALL_TXH 1218#undef CALL_TXH
1217 1219
1218 txh_done: 1220 txh_done:
@@ -1410,16 +1412,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1410 1412
1411 info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 1413 info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
1412 1414
1413 if (ieee80211_vif_is_mesh(&sdata->vif) && 1415 if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
1414 ieee80211_is_data(hdr->frame_control)) {
1415 if (is_multicast_ether_addr(hdr->addr3))
1416 memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
1417 else
1418 if (mesh_nexthop_lookup(skb, sdata)) {
1419 dev_put(sdata->dev);
1420 return;
1421 }
1422 } else if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
1423 int hdrlen; 1416 int hdrlen;
1424 u16 len_rthdr; 1417 u16 len_rthdr;
1425 1418
@@ -1476,6 +1469,15 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1476 1469
1477 info->control.vif = &sdata->vif; 1470 info->control.vif = &sdata->vif;
1478 1471
1472 if (ieee80211_vif_is_mesh(&sdata->vif) &&
1473 ieee80211_is_data(hdr->frame_control) &&
1474 !is_multicast_ether_addr(hdr->addr1))
1475 if (mesh_nexthop_lookup(skb, sdata)) {
1476 /* skb queued: don't free */
1477 dev_put(sdata->dev);
1478 return;
1479 }
1480
1479 ieee80211_select_queue(local, skb); 1481 ieee80211_select_queue(local, skb);
1480 ieee80211_tx(sdata, skb, false); 1482 ieee80211_tx(sdata, skb, false);
1481 dev_put(sdata->dev); 1483 dev_put(sdata->dev);
@@ -1617,52 +1619,58 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
1617 break; 1619 break;
1618#ifdef CONFIG_MAC80211_MESH 1620#ifdef CONFIG_MAC80211_MESH
1619 case NL80211_IFTYPE_MESH_POINT: 1621 case NL80211_IFTYPE_MESH_POINT:
1620 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1621 if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { 1622 if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
1622 /* Do not send frames with mesh_ttl == 0 */ 1623 /* Do not send frames with mesh_ttl == 0 */
1623 sdata->u.mesh.mshstats.dropped_frames_ttl++; 1624 sdata->u.mesh.mshstats.dropped_frames_ttl++;
1624 ret = NETDEV_TX_OK; 1625 ret = NETDEV_TX_OK;
1625 goto fail; 1626 goto fail;
1626 } 1627 }
1627 memset(&mesh_hdr, 0, sizeof(mesh_hdr));
1628 1628
1629 if (compare_ether_addr(dev->dev_addr, 1629 if (compare_ether_addr(dev->dev_addr,
1630 skb->data + ETH_ALEN) == 0) { 1630 skb->data + ETH_ALEN) == 0) {
1631 /* RA TA DA SA */ 1631 hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
1632 memset(hdr.addr1, 0, ETH_ALEN); 1632 skb->data, skb->data + ETH_ALEN);
1633 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); 1633 meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
1634 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1634 sdata, NULL, NULL, NULL);
1635 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
1636 meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
1637 } else { 1635 } else {
1638 /* packet from other interface */ 1636 /* packet from other interface */
1639 struct mesh_path *mppath; 1637 struct mesh_path *mppath;
1638 int is_mesh_mcast = 1;
1639 char *mesh_da;
1640 1640
1641 memset(hdr.addr1, 0, ETH_ALEN); 1641 rcu_read_lock();
1642 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
1643 memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN);
1644
1645 if (is_multicast_ether_addr(skb->data)) 1642 if (is_multicast_ether_addr(skb->data))
1646 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1643 /* DA TA mSA AE:SA */
1644 mesh_da = skb->data;
1647 else { 1645 else {
1648 rcu_read_lock();
1649 mppath = mpp_path_lookup(skb->data, sdata); 1646 mppath = mpp_path_lookup(skb->data, sdata);
1650 if (mppath) 1647 if (mppath) {
1651 memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); 1648 /* RA TA mDA mSA AE:DA SA */
1652 else 1649 mesh_da = mppath->mpp;
1653 memset(hdr.addr3, 0xff, ETH_ALEN); 1650 is_mesh_mcast = 0;
1654 rcu_read_unlock(); 1651 } else
1652 /* DA TA mSA AE:SA */
1653 mesh_da = dev->broadcast;
1655 } 1654 }
1655 hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
1656 mesh_da, dev->dev_addr);
1657 rcu_read_unlock();
1658 if (is_mesh_mcast)
1659 meshhdrlen =
1660 ieee80211_new_mesh_header(&mesh_hdr,
1661 sdata,
1662 skb->data + ETH_ALEN,
1663 NULL,
1664 NULL);
1665 else
1666 meshhdrlen =
1667 ieee80211_new_mesh_header(&mesh_hdr,
1668 sdata,
1669 NULL,
1670 skb->data,
1671 skb->data + ETH_ALEN);
1656 1672
1657 mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6;
1658 mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
1659 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum);
1660 memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN);
1661 memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN);
1662 sdata->u.mesh.mesh_seqnum++;
1663 meshhdrlen = 18;
1664 } 1673 }
1665 hdrlen = 30;
1666 break; 1674 break;
1667#endif 1675#endif
1668 case NL80211_IFTYPE_STATION: 1676 case NL80211_IFTYPE_STATION:
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