diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-04-26 15:03:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-04-26 15:03:48 -0400 |
commit | d9b8ae6bd8c3304569a25079fcdbebaa28a48ee4 (patch) | |
tree | 9ce3e4eb355685f970dd7333a0a935109aff0583 /net/mac80211 | |
parent | 872f24dbc604ef585ea7eec73020dcdfaffd1956 (diff) | |
parent | 94c514fe240fc0dd02187b78facefde8b6744634 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/iwlwifi/iwl-testmode.c
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 19 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 4 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 5 | ||||
-rw-r--r-- | net/mac80211/iface.c | 19 | ||||
-rw-r--r-- | net/mac80211/main.c | 4 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 19 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 14 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 138 | ||||
-rw-r--r-- | net/mac80211/mesh_sync.c | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 2 | ||||
-rw-r--r-- | net/mac80211/scan.c | 95 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 12 | ||||
-rw-r--r-- | net/mac80211/tx.c | 2 | ||||
-rw-r--r-- | net/mac80211/util.c | 9 |
14 files changed, 226 insertions, 118 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 510a745c310..70b2af2315a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1005,6 +1005,9 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | if (params->vlan && params->vlan != sta->sdata->dev) { | 1007 | if (params->vlan && params->vlan != sta->sdata->dev) { |
1008 | bool prev_4addr = false; | ||
1009 | bool new_4addr = false; | ||
1010 | |||
1008 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 1011 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
1009 | 1012 | ||
1010 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1013 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
@@ -1020,9 +1023,25 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1020 | } | 1023 | } |
1021 | 1024 | ||
1022 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); | 1025 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); |
1026 | new_4addr = true; | ||
1027 | } | ||
1028 | |||
1029 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | ||
1030 | sta->sdata->u.vlan.sta) { | ||
1031 | rcu_assign_pointer(sta->sdata->u.vlan.sta, NULL); | ||
1032 | prev_4addr = true; | ||
1023 | } | 1033 | } |
1024 | 1034 | ||
1025 | sta->sdata = vlansdata; | 1035 | sta->sdata = vlansdata; |
1036 | |||
1037 | if (sta->sta_state == IEEE80211_STA_AUTHORIZED && | ||
1038 | prev_4addr != new_4addr) { | ||
1039 | if (new_4addr) | ||
1040 | atomic_dec(&sta->sdata->bss->num_mcast_sta); | ||
1041 | else | ||
1042 | atomic_inc(&sta->sdata->bss->num_mcast_sta); | ||
1043 | } | ||
1044 | |||
1026 | ieee80211_send_layer2_update(sta); | 1045 | ieee80211_send_layer2_update(sta); |
1027 | } | 1046 | } |
1028 | 1047 | ||
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index e7af5227e32..ea0122dbd2b 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -394,7 +394,7 @@ static ssize_t ieee80211_if_parse_uapsd_max_sp_len( | |||
394 | __IEEE80211_IF_FILE_W(uapsd_max_sp_len); | 394 | __IEEE80211_IF_FILE_W(uapsd_max_sp_len); |
395 | 395 | ||
396 | /* AP attributes */ | 396 | /* AP attributes */ |
397 | IEEE80211_IF_FILE(num_sta_authorized, u.ap.num_sta_authorized, ATOMIC); | 397 | IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC); |
398 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 398 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
399 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 399 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
400 | 400 | ||
@@ -540,7 +540,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
540 | 540 | ||
541 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 541 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
542 | { | 542 | { |
543 | DEBUGFS_ADD(num_sta_authorized); | 543 | DEBUGFS_ADD(num_mcast_sta); |
544 | DEBUGFS_ADD(num_sta_ps); | 544 | DEBUGFS_ADD(num_sta_ps); |
545 | DEBUGFS_ADD(dtim_count); | 545 | DEBUGFS_ADD(dtim_count); |
546 | DEBUGFS_ADD(num_buffered_multicast); | 546 | DEBUGFS_ADD(num_buffered_multicast); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index bd7a451b084..851fb7dc893 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -282,7 +282,7 @@ struct ieee80211_if_ap { | |||
282 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; | 282 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; |
283 | struct sk_buff_head ps_bc_buf; | 283 | struct sk_buff_head ps_bc_buf; |
284 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 284 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
285 | atomic_t num_sta_authorized; /* number of authorized stations */ | 285 | atomic_t num_mcast_sta; /* number of stations receiving multicast */ |
286 | int dtim_count; | 286 | int dtim_count; |
287 | bool dtim_bc_mc; | 287 | bool dtim_bc_mc; |
288 | }; | 288 | }; |
@@ -803,6 +803,8 @@ struct tpt_led_trigger { | |||
803 | * well be on the operating channel | 803 | * well be on the operating channel |
804 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to | 804 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to |
805 | * determine if we are on the operating channel or not | 805 | * determine if we are on the operating channel or not |
806 | * @SCAN_ONCHANNEL_SCANNING: Do a software scan on only the current operating | ||
807 | * channel. This should not interrupt normal traffic. | ||
806 | * @SCAN_COMPLETED: Set for our scan work function when the driver reported | 808 | * @SCAN_COMPLETED: Set for our scan work function when the driver reported |
807 | * that the scan completed. | 809 | * that the scan completed. |
808 | * @SCAN_ABORTED: Set for our scan work function when the driver reported | 810 | * @SCAN_ABORTED: Set for our scan work function when the driver reported |
@@ -811,6 +813,7 @@ struct tpt_led_trigger { | |||
811 | enum { | 813 | enum { |
812 | SCAN_SW_SCANNING, | 814 | SCAN_SW_SCANNING, |
813 | SCAN_HW_SCANNING, | 815 | SCAN_HW_SCANNING, |
816 | SCAN_ONCHANNEL_SCANNING, | ||
814 | SCAN_COMPLETED, | 817 | SCAN_COMPLETED, |
815 | SCAN_ABORTED, | 818 | SCAN_ABORTED, |
816 | }; | 819 | }; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 23d1da376eb..ba86978dd56 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1031,6 +1031,18 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1031 | ieee80211_debugfs_add_netdev(sdata); | 1031 | ieee80211_debugfs_add_netdev(sdata); |
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | static void ieee80211_clean_sdata(struct ieee80211_sub_if_data *sdata) | ||
1035 | { | ||
1036 | switch (sdata->vif.type) { | ||
1037 | case NL80211_IFTYPE_MESH_POINT: | ||
1038 | mesh_path_flush_by_iface(sdata); | ||
1039 | break; | ||
1040 | |||
1041 | default: | ||
1042 | break; | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1034 | static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | 1046 | static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, |
1035 | enum nl80211_iftype type) | 1047 | enum nl80211_iftype type) |
1036 | { | 1048 | { |
@@ -1364,8 +1376,8 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | |||
1364 | list_del_rcu(&sdata->list); | 1376 | list_del_rcu(&sdata->list); |
1365 | mutex_unlock(&sdata->local->iflist_mtx); | 1377 | mutex_unlock(&sdata->local->iflist_mtx); |
1366 | 1378 | ||
1367 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1379 | /* clean up type-dependent data */ |
1368 | mesh_path_flush_by_iface(sdata); | 1380 | ieee80211_clean_sdata(sdata); |
1369 | 1381 | ||
1370 | synchronize_rcu(); | 1382 | synchronize_rcu(); |
1371 | unregister_netdevice(sdata->dev); | 1383 | unregister_netdevice(sdata->dev); |
@@ -1386,8 +1398,7 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1386 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | 1398 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { |
1387 | list_del(&sdata->list); | 1399 | list_del(&sdata->list); |
1388 | 1400 | ||
1389 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1401 | ieee80211_clean_sdata(sdata); |
1390 | mesh_path_flush_by_iface(sdata); | ||
1391 | 1402 | ||
1392 | unregister_netdevice_queue(sdata->dev, &unreg_list); | 1403 | unregister_netdevice_queue(sdata->dev, &unreg_list); |
1393 | } | 1404 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ac79d5e8e0d..b70f7f09da6 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -47,7 +47,8 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
47 | if (atomic_read(&local->iff_allmultis)) | 47 | if (atomic_read(&local->iff_allmultis)) |
48 | new_flags |= FIF_ALLMULTI; | 48 | new_flags |= FIF_ALLMULTI; |
49 | 49 | ||
50 | if (local->monitors || test_bit(SCAN_SW_SCANNING, &local->scanning)) | 50 | if (local->monitors || test_bit(SCAN_SW_SCANNING, &local->scanning) || |
51 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) | ||
51 | new_flags |= FIF_BCN_PRBRESP_PROMISC; | 52 | new_flags |= FIF_BCN_PRBRESP_PROMISC; |
52 | 53 | ||
53 | if (local->fif_probe_req || local->probe_req_reg) | 54 | if (local->fif_probe_req || local->probe_req_reg) |
@@ -148,6 +149,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
148 | } | 149 | } |
149 | 150 | ||
150 | if (test_bit(SCAN_SW_SCANNING, &local->scanning) || | 151 | if (test_bit(SCAN_SW_SCANNING, &local->scanning) || |
152 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || | ||
151 | test_bit(SCAN_HW_SCANNING, &local->scanning)) | 153 | test_bit(SCAN_HW_SCANNING, &local->scanning)) |
152 | power = chan->max_power; | 154 | power = chan->max_power; |
153 | else | 155 | else |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 133c118526f..598a96a3a05 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -64,18 +64,18 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) | |||
64 | /** | 64 | /** |
65 | * mesh_matches_local - check if the config of a mesh point matches ours | 65 | * mesh_matches_local - check if the config of a mesh point matches ours |
66 | * | 66 | * |
67 | * @ie: information elements of a management frame from the mesh peer | ||
68 | * @sdata: local mesh subif | 67 | * @sdata: local mesh subif |
69 | * @basic_rates: BSSBasicRateSet of the peer candidate | 68 | * @ie: information elements of a management frame from the mesh peer |
70 | * | 69 | * |
71 | * This function checks if the mesh configuration of a mesh point matches the | 70 | * This function checks if the mesh configuration of a mesh point matches the |
72 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. | 71 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. |
73 | */ | 72 | */ |
74 | bool mesh_matches_local(struct ieee802_11_elems *ie, | 73 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, |
75 | struct ieee80211_sub_if_data *sdata, u32 basic_rates) | 74 | struct ieee802_11_elems *ie) |
76 | { | 75 | { |
77 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 76 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
78 | struct ieee80211_local *local = sdata->local; | 77 | struct ieee80211_local *local = sdata->local; |
78 | u32 basic_rates = 0; | ||
79 | 79 | ||
80 | /* | 80 | /* |
81 | * As support for each feature is added, check for matching | 81 | * As support for each feature is added, check for matching |
@@ -96,6 +96,9 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, | |||
96 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) | 96 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) |
97 | goto mismatch; | 97 | goto mismatch; |
98 | 98 | ||
99 | ieee80211_sta_get_rates(local, ie, local->oper_channel->band, | ||
100 | &basic_rates); | ||
101 | |||
99 | if (sdata->vif.bss_conf.basic_rates != basic_rates) | 102 | if (sdata->vif.bss_conf.basic_rates != basic_rates) |
100 | goto mismatch; | 103 | goto mismatch; |
101 | 104 | ||
@@ -630,7 +633,6 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
630 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 633 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
631 | struct ieee802_11_elems elems; | 634 | struct ieee802_11_elems elems; |
632 | struct ieee80211_channel *channel; | 635 | struct ieee80211_channel *channel; |
633 | u32 supp_rates = 0, basic_rates = 0; | ||
634 | size_t baselen; | 636 | size_t baselen; |
635 | int freq; | 637 | int freq; |
636 | enum ieee80211_band band = rx_status->band; | 638 | enum ieee80211_band band = rx_status->band; |
@@ -661,12 +663,9 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
661 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 663 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
662 | return; | 664 | return; |
663 | 665 | ||
664 | supp_rates = ieee80211_sta_get_rates(local, &elems, | ||
665 | band, &basic_rates); | ||
666 | |||
667 | if (elems.mesh_id && elems.mesh_config && | 666 | if (elems.mesh_id && elems.mesh_config && |
668 | mesh_matches_local(&elems, sdata, basic_rates)) | 667 | mesh_matches_local(sdata, &elems)) |
669 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems); | 668 | mesh_neighbour_update(sdata, mgmt->sa, &elems); |
670 | 669 | ||
671 | if (ifmsh->sync_ops) | 670 | if (ifmsh->sync_ops) |
672 | ifmsh->sync_ops->rx_bcn_presp(sdata, | 671 | ifmsh->sync_ops->rx_bcn_presp(sdata, |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 4ad73898880..e3642756f8f 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -222,8 +222,8 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | |||
222 | char *addr6); | 222 | char *addr6); |
223 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | 223 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, |
224 | struct ieee80211_sub_if_data *sdata); | 224 | struct ieee80211_sub_if_data *sdata); |
225 | bool mesh_matches_local(struct ieee802_11_elems *ie, | 225 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, |
226 | struct ieee80211_sub_if_data *sdata, u32 basic_rates); | 226 | struct ieee802_11_elems *ie); |
227 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); | 227 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
228 | void mesh_mgmt_ies_add(struct sk_buff *skb, | 228 | void mesh_mgmt_ies_add(struct sk_buff *skb, |
229 | struct ieee80211_sub_if_data *sdata); | 229 | struct ieee80211_sub_if_data *sdata); |
@@ -276,9 +276,9 @@ int mesh_path_add_gate(struct mesh_path *mpath); | |||
276 | int mesh_path_send_to_gates(struct mesh_path *mpath); | 276 | int mesh_path_send_to_gates(struct mesh_path *mpath); |
277 | int mesh_gate_num(struct ieee80211_sub_if_data *sdata); | 277 | int mesh_gate_num(struct ieee80211_sub_if_data *sdata); |
278 | /* Mesh plinks */ | 278 | /* Mesh plinks */ |
279 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, | 279 | void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, |
280 | struct ieee80211_sub_if_data *sdata, | 280 | u8 *hw_addr, |
281 | struct ieee802_11_elems *ie); | 281 | struct ieee802_11_elems *ie); |
282 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); | 282 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
283 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 283 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
284 | void mesh_plink_broken(struct sta_info *sta); | 284 | void mesh_plink_broken(struct sta_info *sta); |
@@ -304,7 +304,6 @@ void mesh_pathtbl_unregister(void); | |||
304 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); | 304 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); |
305 | void mesh_path_timer(unsigned long data); | 305 | void mesh_path_timer(unsigned long data); |
306 | void mesh_path_flush_by_nexthop(struct sta_info *sta); | 306 | void mesh_path_flush_by_nexthop(struct sta_info *sta); |
307 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); | ||
308 | void mesh_path_discard_frame(struct sk_buff *skb, | 307 | void mesh_path_discard_frame(struct sk_buff *skb, |
309 | struct ieee80211_sub_if_data *sdata); | 308 | struct ieee80211_sub_if_data *sdata); |
310 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); | 309 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); |
@@ -345,6 +344,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata); | |||
345 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata); | 344 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata); |
346 | void mesh_plink_quiesce(struct sta_info *sta); | 345 | void mesh_plink_quiesce(struct sta_info *sta); |
347 | void mesh_plink_restart(struct sta_info *sta); | 346 | void mesh_plink_restart(struct sta_info *sta); |
347 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); | ||
348 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); | 348 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); |
349 | #else | 349 | #else |
350 | #define mesh_allocated 0 | 350 | #define mesh_allocated 0 |
@@ -358,6 +358,8 @@ static inline void mesh_plink_quiesce(struct sta_info *sta) {} | |||
358 | static inline void mesh_plink_restart(struct sta_info *sta) {} | 358 | static inline void mesh_plink_restart(struct sta_info *sta) {} |
359 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | 359 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) |
360 | { return false; } | 360 | { return false; } |
361 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) | ||
362 | {} | ||
361 | #endif | 363 | #endif |
362 | 364 | ||
363 | #endif /* IEEE80211S_H */ | 365 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 9c836e774fb..1ff2a5c63e4 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -82,20 +82,14 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) | |||
82 | } | 82 | } |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * NOTE: This is just an alias for sta_info_alloc(), see notes | 85 | * Allocate mesh sta entry and insert into station table |
86 | * on it in the lifecycle management section! | ||
87 | */ | 86 | */ |
88 | static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | 87 | static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, |
89 | u8 *hw_addr, u32 rates, | 88 | u8 *hw_addr) |
90 | struct ieee802_11_elems *elems) | ||
91 | { | 89 | { |
92 | struct ieee80211_local *local = sdata->local; | ||
93 | struct ieee80211_supported_band *sband; | ||
94 | struct sta_info *sta; | 90 | struct sta_info *sta; |
95 | 91 | ||
96 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 92 | if (sdata->local->num_sta >= MESH_MAX_PLINKS) |
97 | |||
98 | if (local->num_sta >= MESH_MAX_PLINKS) | ||
99 | return NULL; | 93 | return NULL; |
100 | 94 | ||
101 | sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); | 95 | sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); |
@@ -108,12 +102,8 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
108 | 102 | ||
109 | set_sta_flag(sta, WLAN_STA_WME); | 103 | set_sta_flag(sta, WLAN_STA_WME); |
110 | 104 | ||
111 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 105 | if (sta_info_insert(sta)) |
112 | if (elems->ht_cap_elem) | 106 | return NULL; |
113 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | ||
114 | elems->ht_cap_elem, | ||
115 | &sta->sta.ht_cap); | ||
116 | rate_control_rate_init(sta); | ||
117 | 107 | ||
118 | return sta; | 108 | return sta; |
119 | } | 109 | } |
@@ -274,43 +264,79 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
274 | return 0; | 264 | return 0; |
275 | } | 265 | } |
276 | 266 | ||
277 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, | 267 | /* mesh_peer_init - initialize new mesh peer and return resulting sta_info |
278 | struct ieee80211_sub_if_data *sdata, | 268 | * |
279 | struct ieee802_11_elems *elems) | 269 | * @sdata: local meshif |
270 | * @addr: peer's address | ||
271 | * @elems: IEs from beacon or mesh peering frame | ||
272 | * | ||
273 | * call under RCU | ||
274 | */ | ||
275 | static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | ||
276 | u8 *addr, | ||
277 | struct ieee802_11_elems *elems) | ||
280 | { | 278 | { |
281 | struct ieee80211_local *local = sdata->local; | 279 | struct ieee80211_local *local = sdata->local; |
280 | enum ieee80211_band band = local->oper_channel->band; | ||
281 | struct ieee80211_supported_band *sband; | ||
282 | u32 rates, basic_rates = 0; | ||
282 | struct sta_info *sta; | 283 | struct sta_info *sta; |
283 | 284 | ||
284 | rcu_read_lock(); | 285 | sband = local->hw.wiphy->bands[band]; |
286 | rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates); | ||
285 | 287 | ||
286 | sta = sta_info_get(sdata, hw_addr); | 288 | sta = sta_info_get(sdata, addr); |
287 | if (!sta) { | 289 | if (!sta) { |
288 | rcu_read_unlock(); | 290 | sta = mesh_plink_alloc(sdata, addr); |
289 | /* Userspace handles peer allocation when security is enabled | ||
290 | * */ | ||
291 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) | ||
292 | cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, | ||
293 | elems->ie_start, elems->total_len, | ||
294 | GFP_KERNEL); | ||
295 | else | ||
296 | sta = mesh_plink_alloc(sdata, hw_addr, rates, elems); | ||
297 | if (!sta) | 291 | if (!sta) |
298 | return; | 292 | return NULL; |
299 | if (sta_info_insert_rcu(sta)) { | ||
300 | rcu_read_unlock(); | ||
301 | return; | ||
302 | } | ||
303 | } | 293 | } |
304 | 294 | ||
295 | spin_lock_bh(&sta->lock); | ||
305 | sta->last_rx = jiffies; | 296 | sta->last_rx = jiffies; |
306 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 297 | sta->sta.supp_rates[band] = rates; |
298 | if (elems->ht_cap_elem && | ||
299 | sdata->local->_oper_channel_type != NL80211_CHAN_NO_HT) | ||
300 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | ||
301 | elems->ht_cap_elem, | ||
302 | &sta->sta.ht_cap); | ||
303 | else | ||
304 | memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); | ||
305 | |||
306 | rate_control_rate_init(sta); | ||
307 | spin_unlock_bh(&sta->lock); | ||
308 | |||
309 | return sta; | ||
310 | } | ||
311 | |||
312 | void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, | ||
313 | u8 *hw_addr, | ||
314 | struct ieee802_11_elems *elems) | ||
315 | { | ||
316 | struct sta_info *sta; | ||
317 | |||
318 | /* Userspace handles peer allocation when security is enabled */ | ||
319 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) { | ||
320 | cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, | ||
321 | elems->ie_start, | ||
322 | elems->total_len, | ||
323 | GFP_KERNEL); | ||
324 | return; | ||
325 | } | ||
326 | |||
327 | rcu_read_lock(); | ||
328 | sta = mesh_peer_init(sdata, hw_addr, elems); | ||
329 | if (!sta) | ||
330 | goto out; | ||
331 | |||
307 | if (mesh_peer_accepts_plinks(elems) && | 332 | if (mesh_peer_accepts_plinks(elems) && |
308 | sta->plink_state == NL80211_PLINK_LISTEN && | 333 | sta->plink_state == NL80211_PLINK_LISTEN && |
309 | sdata->u.mesh.accepting_plinks && | 334 | sdata->u.mesh.accepting_plinks && |
310 | sdata->u.mesh.mshcfg.auto_open_plinks && | 335 | sdata->u.mesh.mshcfg.auto_open_plinks && |
311 | rssi_threshold_check(sta, sdata)) | 336 | rssi_threshold_check(sta, sdata)) |
312 | mesh_plink_open(sta); | 337 | mesh_plink_open(sta); |
313 | 338 | ||
339 | out: | ||
314 | rcu_read_unlock(); | 340 | rcu_read_unlock(); |
315 | } | 341 | } |
316 | 342 | ||
@@ -456,7 +482,6 @@ void mesh_plink_block(struct sta_info *sta) | |||
456 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, | 482 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, |
457 | size_t len, struct ieee80211_rx_status *rx_status) | 483 | size_t len, struct ieee80211_rx_status *rx_status) |
458 | { | 484 | { |
459 | struct ieee80211_local *local = sdata->local; | ||
460 | struct ieee802_11_elems elems; | 485 | struct ieee802_11_elems elems; |
461 | struct sta_info *sta; | 486 | struct sta_info *sta; |
462 | enum plink_event event; | 487 | enum plink_event event; |
@@ -465,7 +490,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
465 | bool deactivated, matches_local = true; | 490 | bool deactivated, matches_local = true; |
466 | u8 ie_len; | 491 | u8 ie_len; |
467 | u8 *baseaddr; | 492 | u8 *baseaddr; |
468 | u32 rates, basic_rates = 0; | ||
469 | __le16 plid, llid, reason; | 493 | __le16 plid, llid, reason; |
470 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 494 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
471 | static const char *mplstates[] = { | 495 | static const char *mplstates[] = { |
@@ -560,11 +584,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
560 | 584 | ||
561 | /* Now we will figure out the appropriate event... */ | 585 | /* Now we will figure out the appropriate event... */ |
562 | event = PLINK_UNDEFINED; | 586 | event = PLINK_UNDEFINED; |
563 | rates = ieee80211_sta_get_rates(local, &elems, | ||
564 | rx_status->band, &basic_rates); | ||
565 | |||
566 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && | 587 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && |
567 | (!mesh_matches_local(&elems, sdata, basic_rates))) { | 588 | !mesh_matches_local(sdata, &elems)) { |
568 | matches_local = false; | 589 | matches_local = false; |
569 | switch (ftype) { | 590 | switch (ftype) { |
570 | case WLAN_SP_MESH_PEERING_OPEN: | 591 | case WLAN_SP_MESH_PEERING_OPEN: |
@@ -587,26 +608,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
587 | return; | 608 | return; |
588 | } else if (!sta) { | 609 | } else if (!sta) { |
589 | /* ftype == WLAN_SP_MESH_PEERING_OPEN */ | 610 | /* ftype == WLAN_SP_MESH_PEERING_OPEN */ |
590 | |||
591 | rcu_read_unlock(); | ||
592 | |||
593 | if (!mesh_plink_free_count(sdata)) { | 611 | if (!mesh_plink_free_count(sdata)) { |
594 | mpl_dbg("Mesh plink error: no more free plinks\n"); | 612 | mpl_dbg("Mesh plink error: no more free plinks\n"); |
595 | return; | ||
596 | } | ||
597 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems); | ||
598 | if (!sta) { | ||
599 | mpl_dbg("Mesh plink error: plink table full\n"); | ||
600 | return; | ||
601 | } | ||
602 | if (sta_info_insert_rcu(sta)) { | ||
603 | rcu_read_unlock(); | 613 | rcu_read_unlock(); |
604 | return; | 614 | return; |
605 | } | 615 | } |
606 | event = OPN_ACPT; | 616 | event = OPN_ACPT; |
607 | spin_lock_bh(&sta->lock); | ||
608 | } else if (matches_local) { | 617 | } else if (matches_local) { |
609 | spin_lock_bh(&sta->lock); | ||
610 | switch (ftype) { | 618 | switch (ftype) { |
611 | case WLAN_SP_MESH_PEERING_OPEN: | 619 | case WLAN_SP_MESH_PEERING_OPEN: |
612 | if (!mesh_plink_free_count(sdata) || | 620 | if (!mesh_plink_free_count(sdata) || |
@@ -643,12 +651,19 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
643 | break; | 651 | break; |
644 | default: | 652 | default: |
645 | mpl_dbg("Mesh plink: unknown frame subtype\n"); | 653 | mpl_dbg("Mesh plink: unknown frame subtype\n"); |
646 | spin_unlock_bh(&sta->lock); | ||
647 | rcu_read_unlock(); | 654 | rcu_read_unlock(); |
648 | return; | 655 | return; |
649 | } | 656 | } |
650 | } else { | 657 | } |
651 | spin_lock_bh(&sta->lock); | 658 | |
659 | if (event == OPN_ACPT) { | ||
660 | /* allocate sta entry if necessary and update info */ | ||
661 | sta = mesh_peer_init(sdata, mgmt->sa, &elems); | ||
662 | if (!sta) { | ||
663 | mpl_dbg("Mesh plink: failed to init peer!\n"); | ||
664 | rcu_read_unlock(); | ||
665 | return; | ||
666 | } | ||
652 | } | 667 | } |
653 | 668 | ||
654 | mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", | 669 | mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", |
@@ -656,6 +671,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
656 | le16_to_cpu(sta->llid), le16_to_cpu(sta->plid), | 671 | le16_to_cpu(sta->llid), le16_to_cpu(sta->plid), |
657 | event); | 672 | event); |
658 | reason = 0; | 673 | reason = 0; |
674 | spin_lock_bh(&sta->lock); | ||
659 | switch (sta->plink_state) { | 675 | switch (sta->plink_state) { |
660 | /* spin_unlock as soon as state is updated at each case */ | 676 | /* spin_unlock as soon as state is updated at each case */ |
661 | case NL80211_PLINK_LISTEN: | 677 | case NL80211_PLINK_LISTEN: |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index ff60d6bcc63..38d30e8ce6d 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -195,7 +195,7 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
195 | spin_unlock_bh(&ifmsh->sync_offset_lock); | 195 | spin_unlock_bh(&ifmsh->sync_offset_lock); |
196 | 196 | ||
197 | } else { | 197 | } else { |
198 | sta->t_offset_setpoint = sta->t_offset; | 198 | sta->t_offset_setpoint = sta->t_offset - TOFFSET_SET_MARGIN; |
199 | set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); | 199 | set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); |
200 | msync_dbg("STA %pM : offset was invalid, " | 200 | msync_dbg("STA %pM : offset was invalid, " |
201 | " sta->t_offset=%lld", | 201 | " sta->t_offset=%lld", |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7cbb4aad057..d5ac02fe37f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -426,6 +426,7 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
426 | 426 | ||
427 | if (test_bit(SCAN_HW_SCANNING, &local->scanning) || | 427 | if (test_bit(SCAN_HW_SCANNING, &local->scanning) || |
428 | test_bit(SCAN_SW_SCANNING, &local->scanning) || | 428 | test_bit(SCAN_SW_SCANNING, &local->scanning) || |
429 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || | ||
429 | local->sched_scanning) | 430 | local->sched_scanning) |
430 | return ieee80211_scan_rx(rx->sdata, skb); | 431 | return ieee80211_scan_rx(rx->sdata, skb); |
431 | 432 | ||
@@ -2917,6 +2918,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2917 | local->dot11ReceivedFragmentCount++; | 2918 | local->dot11ReceivedFragmentCount++; |
2918 | 2919 | ||
2919 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 2920 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
2921 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || | ||
2920 | test_bit(SCAN_SW_SCANNING, &local->scanning))) | 2922 | test_bit(SCAN_SW_SCANNING, &local->scanning))) |
2921 | status->rx_flags |= IEEE80211_RX_IN_SCAN; | 2923 | status->rx_flags |= IEEE80211_RX_IN_SCAN; |
2922 | 2924 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 45f5aa229ef..8282284f835 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -401,6 +401,30 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local) | |||
401 | round_jiffies_relative(0)); | 401 | round_jiffies_relative(0)); |
402 | } | 402 | } |
403 | 403 | ||
404 | static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | ||
405 | unsigned long *next_delay) | ||
406 | { | ||
407 | int i; | ||
408 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
409 | enum ieee80211_band band = local->hw.conf.channel->band; | ||
410 | |||
411 | for (i = 0; i < local->scan_req->n_ssids; i++) | ||
412 | ieee80211_send_probe_req( | ||
413 | sdata, NULL, | ||
414 | local->scan_req->ssids[i].ssid, | ||
415 | local->scan_req->ssids[i].ssid_len, | ||
416 | local->scan_req->ie, local->scan_req->ie_len, | ||
417 | local->scan_req->rates[band], false, | ||
418 | local->scan_req->no_cck); | ||
419 | |||
420 | /* | ||
421 | * After sending probe requests, wait for probe responses | ||
422 | * on the channel. | ||
423 | */ | ||
424 | *next_delay = IEEE80211_CHANNEL_TIME; | ||
425 | local->next_scan_state = SCAN_DECISION; | ||
426 | } | ||
427 | |||
404 | static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | 428 | static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, |
405 | struct cfg80211_scan_request *req) | 429 | struct cfg80211_scan_request *req) |
406 | { | 430 | { |
@@ -451,10 +475,47 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
451 | local->scan_req = req; | 475 | local->scan_req = req; |
452 | local->scan_sdata = sdata; | 476 | local->scan_sdata = sdata; |
453 | 477 | ||
454 | if (local->ops->hw_scan) | 478 | if (local->ops->hw_scan) { |
455 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 479 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
456 | else | 480 | } else if ((req->n_channels == 1) && |
481 | (req->channels[0]->center_freq == | ||
482 | local->hw.conf.channel->center_freq)) { | ||
483 | |||
484 | /* If we are scanning only on the current channel, then | ||
485 | * we do not need to stop normal activities | ||
486 | */ | ||
487 | unsigned long next_delay; | ||
488 | |||
489 | __set_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning); | ||
490 | |||
491 | ieee80211_recalc_idle(local); | ||
492 | |||
493 | /* Notify driver scan is starting, keep order of operations | ||
494 | * same as normal software scan, in case that matters. */ | ||
495 | drv_sw_scan_start(local); | ||
496 | |||
497 | ieee80211_configure_filter(local); /* accept probe-responses */ | ||
498 | |||
499 | /* We need to ensure power level is at max for scanning. */ | ||
500 | ieee80211_hw_config(local, 0); | ||
501 | |||
502 | if ((req->channels[0]->flags & | ||
503 | IEEE80211_CHAN_PASSIVE_SCAN) || | ||
504 | !local->scan_req->n_ssids) { | ||
505 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
506 | } else { | ||
507 | ieee80211_scan_state_send_probe(local, &next_delay); | ||
508 | next_delay = IEEE80211_CHANNEL_TIME; | ||
509 | } | ||
510 | |||
511 | /* Now, just wait a bit and we are all done! */ | ||
512 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, | ||
513 | next_delay); | ||
514 | return 0; | ||
515 | } else { | ||
516 | /* Do normal software scan */ | ||
457 | __set_bit(SCAN_SW_SCANNING, &local->scanning); | 517 | __set_bit(SCAN_SW_SCANNING, &local->scanning); |
518 | } | ||
458 | 519 | ||
459 | ieee80211_recalc_idle(local); | 520 | ieee80211_recalc_idle(local); |
460 | 521 | ||
@@ -611,30 +672,6 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
611 | local->next_scan_state = SCAN_SEND_PROBE; | 672 | local->next_scan_state = SCAN_SEND_PROBE; |
612 | } | 673 | } |
613 | 674 | ||
614 | static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | ||
615 | unsigned long *next_delay) | ||
616 | { | ||
617 | int i; | ||
618 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
619 | enum ieee80211_band band = local->hw.conf.channel->band; | ||
620 | |||
621 | for (i = 0; i < local->scan_req->n_ssids; i++) | ||
622 | ieee80211_send_probe_req( | ||
623 | sdata, NULL, | ||
624 | local->scan_req->ssids[i].ssid, | ||
625 | local->scan_req->ssids[i].ssid_len, | ||
626 | local->scan_req->ie, local->scan_req->ie_len, | ||
627 | local->scan_req->rates[band], false, | ||
628 | local->scan_req->no_cck); | ||
629 | |||
630 | /* | ||
631 | * After sending probe requests, wait for probe responses | ||
632 | * on the channel. | ||
633 | */ | ||
634 | *next_delay = IEEE80211_CHANNEL_TIME; | ||
635 | local->next_scan_state = SCAN_DECISION; | ||
636 | } | ||
637 | |||
638 | static void ieee80211_scan_state_suspend(struct ieee80211_local *local, | 675 | static void ieee80211_scan_state_suspend(struct ieee80211_local *local, |
639 | unsigned long *next_delay) | 676 | unsigned long *next_delay) |
640 | { | 677 | { |
@@ -685,6 +722,12 @@ void ieee80211_scan_work(struct work_struct *work) | |||
685 | 722 | ||
686 | sdata = local->scan_sdata; | 723 | sdata = local->scan_sdata; |
687 | 724 | ||
725 | /* When scanning on-channel, the first-callback means completed. */ | ||
726 | if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { | ||
727 | aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); | ||
728 | goto out_complete; | ||
729 | } | ||
730 | |||
688 | if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { | 731 | if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { |
689 | aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); | 732 | aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); |
690 | goto out_complete; | 733 | goto out_complete; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 7fd7ac48f89..97a9d6639fb 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1417,15 +1417,19 @@ int sta_info_move_state(struct sta_info *sta, | |||
1417 | if (sta->sta_state == IEEE80211_STA_AUTH) { | 1417 | if (sta->sta_state == IEEE80211_STA_AUTH) { |
1418 | set_bit(WLAN_STA_ASSOC, &sta->_flags); | 1418 | set_bit(WLAN_STA_ASSOC, &sta->_flags); |
1419 | } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { | 1419 | } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { |
1420 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | 1420 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || |
1421 | atomic_dec(&sta->sdata->u.ap.num_sta_authorized); | 1421 | (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && |
1422 | !sta->sdata->u.vlan.sta)) | ||
1423 | atomic_dec(&sta->sdata->bss->num_mcast_sta); | ||
1422 | clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | 1424 | clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); |
1423 | } | 1425 | } |
1424 | break; | 1426 | break; |
1425 | case IEEE80211_STA_AUTHORIZED: | 1427 | case IEEE80211_STA_AUTHORIZED: |
1426 | if (sta->sta_state == IEEE80211_STA_ASSOC) { | 1428 | if (sta->sta_state == IEEE80211_STA_ASSOC) { |
1427 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | 1429 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || |
1428 | atomic_inc(&sta->sdata->u.ap.num_sta_authorized); | 1430 | (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && |
1431 | !sta->sdata->u.vlan.sta)) | ||
1432 | atomic_inc(&sta->sdata->bss->num_mcast_sta); | ||
1429 | set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | 1433 | set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); |
1430 | } | 1434 | } |
1431 | break; | 1435 | break; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0abbef952c1..44001c7e0e5 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -306,7 +306,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
306 | } | 306 | } |
307 | } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP && | 307 | } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP && |
308 | ieee80211_is_data(hdr->frame_control) && | 308 | ieee80211_is_data(hdr->frame_control) && |
309 | !atomic_read(&tx->sdata->u.ap.num_sta_authorized))) { | 309 | !atomic_read(&tx->sdata->u.ap.num_mcast_sta))) { |
310 | /* | 310 | /* |
311 | * No associated STAs - no need to send multicast | 311 | * No associated STAs - no need to send multicast |
312 | * frames. | 312 | * frames. |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 89c1e5b9ba9..d9a747d387f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1684,7 +1684,9 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1684 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; | 1684 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; |
1685 | break; | 1685 | break; |
1686 | } | 1686 | } |
1687 | if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | 1687 | if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && |
1688 | channel_type != NL80211_CHAN_NO_HT && | ||
1689 | channel_type != NL80211_CHAN_HT20) | ||
1688 | ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; | 1690 | ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; |
1689 | 1691 | ||
1690 | /* | 1692 | /* |
@@ -1799,5 +1801,10 @@ int ieee80211_ave_rssi(struct ieee80211_vif *vif) | |||
1799 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1801 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
1800 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1802 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1801 | 1803 | ||
1804 | if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION)) { | ||
1805 | /* non-managed type inferfaces */ | ||
1806 | return 0; | ||
1807 | } | ||
1802 | return ifmgd->ave_beacon_signal; | 1808 | return ifmgd->ave_beacon_signal; |
1803 | } | 1809 | } |
1810 | EXPORT_SYMBOL_GPL(ieee80211_ave_rssi); | ||