diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/aes_cmac.c | 6 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 2 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 103 | ||||
-rw-r--r-- | net/mac80211/chan.c | 67 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 36 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 11 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 50 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 53 | ||||
-rw-r--r-- | net/mac80211/iface.c | 316 | ||||
-rw-r--r-- | net/mac80211/key.c | 2 | ||||
-rw-r--r-- | net/mac80211/main.c | 31 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 49 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 5 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 2 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 44 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 85 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 443 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 9 | ||||
-rw-r--r-- | net/mac80211/rate.h | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 60 | ||||
-rw-r--r-- | net/mac80211/scan.c | 53 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 123 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/status.c | 42 | ||||
-rw-r--r-- | net/mac80211/trace.h | 11 | ||||
-rw-r--r-- | net/mac80211/tx.c | 73 | ||||
-rw-r--r-- | net/mac80211/util.c | 108 |
27 files changed, 1106 insertions, 682 deletions
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 8dfd70d8fcfb..a04752e91023 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -38,14 +38,10 @@ static void gf_mulx(u8 *pad) | |||
38 | static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, | 38 | static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, |
39 | const u8 *addr[], const size_t *len, u8 *mac) | 39 | const u8 *addr[], const size_t *len, u8 *mac) |
40 | { | 40 | { |
41 | u8 scratch[2 * AES_BLOCK_SIZE]; | 41 | u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; |
42 | u8 *cbc, *pad; | ||
43 | const u8 *pos, *end; | 42 | const u8 *pos, *end; |
44 | size_t i, e, left, total_len; | 43 | size_t i, e, left, total_len; |
45 | 44 | ||
46 | cbc = scratch; | ||
47 | pad = scratch + AES_BLOCK_SIZE; | ||
48 | |||
49 | memset(cbc, 0, AES_BLOCK_SIZE); | 45 | memset(cbc, 0, AES_BLOCK_SIZE); |
50 | 46 | ||
51 | total_len = 0; | 47 | total_len = 0; |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index d0deb3edae21..3195a6307f50 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -869,7 +869,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
869 | 869 | ||
870 | } else { | 870 | } else { |
871 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, | 871 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, |
872 | true); | 872 | false); |
873 | } | 873 | } |
874 | 874 | ||
875 | out: | 875 | out: |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a58c0b649ba1..05f3a313db88 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -20,7 +20,8 @@ | |||
20 | #include "rate.h" | 20 | #include "rate.h" |
21 | #include "mesh.h" | 21 | #include "mesh.h" |
22 | 22 | ||
23 | static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, char *name, | 23 | static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, |
24 | const char *name, | ||
24 | enum nl80211_iftype type, | 25 | enum nl80211_iftype type, |
25 | u32 *flags, | 26 | u32 *flags, |
26 | struct vif_params *params) | 27 | struct vif_params *params) |
@@ -102,6 +103,18 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
102 | return 0; | 103 | return 0; |
103 | } | 104 | } |
104 | 105 | ||
106 | static int ieee80211_start_p2p_device(struct wiphy *wiphy, | ||
107 | struct wireless_dev *wdev) | ||
108 | { | ||
109 | return ieee80211_do_open(wdev, true); | ||
110 | } | ||
111 | |||
112 | static void ieee80211_stop_p2p_device(struct wiphy *wiphy, | ||
113 | struct wireless_dev *wdev) | ||
114 | { | ||
115 | ieee80211_sdata_stop(IEEE80211_WDEV_TO_SUB_IF(wdev)); | ||
116 | } | ||
117 | |||
105 | static int ieee80211_set_noack_map(struct wiphy *wiphy, | 118 | static int ieee80211_set_noack_map(struct wiphy *wiphy, |
106 | struct net_device *dev, | 119 | struct net_device *dev, |
107 | u16 noack_map) | 120 | u16 noack_map) |
@@ -158,6 +171,38 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
158 | } | 171 | } |
159 | } | 172 | } |
160 | 173 | ||
174 | switch (sdata->vif.type) { | ||
175 | case NL80211_IFTYPE_STATION: | ||
176 | if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) | ||
177 | key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; | ||
178 | break; | ||
179 | case NL80211_IFTYPE_AP: | ||
180 | case NL80211_IFTYPE_AP_VLAN: | ||
181 | /* Keys without a station are used for TX only */ | ||
182 | if (key->sta && test_sta_flag(key->sta, WLAN_STA_MFP)) | ||
183 | key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; | ||
184 | break; | ||
185 | case NL80211_IFTYPE_ADHOC: | ||
186 | /* no MFP (yet) */ | ||
187 | break; | ||
188 | case NL80211_IFTYPE_MESH_POINT: | ||
189 | #ifdef CONFIG_MAC80211_MESH | ||
190 | if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) | ||
191 | key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; | ||
192 | break; | ||
193 | #endif | ||
194 | case NL80211_IFTYPE_WDS: | ||
195 | case NL80211_IFTYPE_MONITOR: | ||
196 | case NL80211_IFTYPE_P2P_DEVICE: | ||
197 | case NL80211_IFTYPE_UNSPECIFIED: | ||
198 | case NUM_NL80211_IFTYPES: | ||
199 | case NL80211_IFTYPE_P2P_CLIENT: | ||
200 | case NL80211_IFTYPE_P2P_GO: | ||
201 | /* shouldn't happen */ | ||
202 | WARN_ON_ONCE(1); | ||
203 | break; | ||
204 | } | ||
205 | |||
161 | err = ieee80211_key_link(key, sdata, sta); | 206 | err = ieee80211_key_link(key, sdata, sta); |
162 | if (err) | 207 | if (err) |
163 | ieee80211_key_free(sdata->local, key); | 208 | ieee80211_key_free(sdata->local, key); |
@@ -330,7 +375,7 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in | |||
330 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { | 375 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { |
331 | struct ieee80211_supported_band *sband; | 376 | struct ieee80211_supported_band *sband; |
332 | sband = sta->local->hw.wiphy->bands[ | 377 | sband = sta->local->hw.wiphy->bands[ |
333 | sta->local->hw.conf.channel->band]; | 378 | sta->local->oper_channel->band]; |
334 | rate->legacy = sband->bitrates[idx].bitrate; | 379 | rate->legacy = sband->bitrates[idx].bitrate; |
335 | } else | 380 | } else |
336 | rate->mcs = idx; | 381 | rate->mcs = idx; |
@@ -725,25 +770,23 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
725 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | 770 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, |
726 | const u8 *resp, size_t resp_len) | 771 | const u8 *resp, size_t resp_len) |
727 | { | 772 | { |
728 | struct sk_buff *new, *old; | 773 | struct probe_resp *new, *old; |
729 | 774 | ||
730 | if (!resp || !resp_len) | 775 | if (!resp || !resp_len) |
731 | return 1; | 776 | return 1; |
732 | 777 | ||
733 | old = rtnl_dereference(sdata->u.ap.probe_resp); | 778 | old = rtnl_dereference(sdata->u.ap.probe_resp); |
734 | 779 | ||
735 | new = dev_alloc_skb(resp_len); | 780 | new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL); |
736 | if (!new) | 781 | if (!new) |
737 | return -ENOMEM; | 782 | return -ENOMEM; |
738 | 783 | ||
739 | memcpy(skb_put(new, resp_len), resp, resp_len); | 784 | new->len = resp_len; |
785 | memcpy(new->data, resp, resp_len); | ||
740 | 786 | ||
741 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); | 787 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); |
742 | if (old) { | 788 | if (old) |
743 | /* TODO: use call_rcu() */ | 789 | kfree_rcu(old, rcu_head); |
744 | synchronize_rcu(); | ||
745 | dev_kfree_skb(old); | ||
746 | } | ||
747 | 790 | ||
748 | return 0; | 791 | return 0; |
749 | } | 792 | } |
@@ -950,7 +993,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
950 | /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) | 993 | /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) |
951 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ | 994 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ |
952 | 995 | ||
953 | memset(msg->da, 0xff, ETH_ALEN); | 996 | eth_broadcast_addr(msg->da); |
954 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); | 997 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); |
955 | msg->len = htons(6); | 998 | msg->len = htons(6); |
956 | msg->dsap = 0; | 999 | msg->dsap = 0; |
@@ -1285,9 +1328,10 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1285 | mutex_unlock(&local->sta_mtx); | 1328 | mutex_unlock(&local->sta_mtx); |
1286 | 1329 | ||
1287 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1330 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1288 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 1331 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
1289 | ieee80211_recalc_ps(local, -1); | 1332 | ieee80211_recalc_ps(local, -1); |
1290 | 1333 | ieee80211_recalc_ps_vif(sdata); | |
1334 | } | ||
1291 | return 0; | 1335 | return 0; |
1292 | } | 1336 | } |
1293 | 1337 | ||
@@ -1660,7 +1704,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1660 | } | 1704 | } |
1661 | 1705 | ||
1662 | if (!sdata->vif.bss_conf.use_short_slot && | 1706 | if (!sdata->vif.bss_conf.use_short_slot && |
1663 | sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) { | 1707 | sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) { |
1664 | sdata->vif.bss_conf.use_short_slot = true; | 1708 | sdata->vif.bss_conf.use_short_slot = true; |
1665 | changed |= BSS_CHANGED_ERP_SLOT; | 1709 | changed |= BSS_CHANGED_ERP_SLOT; |
1666 | } | 1710 | } |
@@ -1774,6 +1818,7 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1774 | case NL80211_IFTYPE_ADHOC: | 1818 | case NL80211_IFTYPE_ADHOC: |
1775 | case NL80211_IFTYPE_MESH_POINT: | 1819 | case NL80211_IFTYPE_MESH_POINT: |
1776 | case NL80211_IFTYPE_P2P_CLIENT: | 1820 | case NL80211_IFTYPE_P2P_CLIENT: |
1821 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1777 | break; | 1822 | break; |
1778 | case NL80211_IFTYPE_P2P_GO: | 1823 | case NL80211_IFTYPE_P2P_GO: |
1779 | if (sdata->local->ops->hw_scan) | 1824 | if (sdata->local->ops->hw_scan) |
@@ -1926,7 +1971,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, | |||
1926 | enum nl80211_tx_power_setting type, int mbm) | 1971 | enum nl80211_tx_power_setting type, int mbm) |
1927 | { | 1972 | { |
1928 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1973 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1929 | struct ieee80211_channel *chan = local->hw.conf.channel; | 1974 | struct ieee80211_channel *chan = local->oper_channel; |
1930 | u32 changes = 0; | 1975 | u32 changes = 0; |
1931 | 1976 | ||
1932 | switch (type) { | 1977 | switch (type) { |
@@ -2026,9 +2071,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
2026 | */ | 2071 | */ |
2027 | if (!sdata->u.mgd.associated || | 2072 | if (!sdata->u.mgd.associated || |
2028 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { | 2073 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { |
2029 | mutex_lock(&sdata->local->iflist_mtx); | ||
2030 | ieee80211_recalc_smps(sdata->local); | 2074 | ieee80211_recalc_smps(sdata->local); |
2031 | mutex_unlock(&sdata->local->iflist_mtx); | ||
2032 | return 0; | 2075 | return 0; |
2033 | } | 2076 | } |
2034 | 2077 | ||
@@ -2078,6 +2121,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2078 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 2121 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
2079 | 2122 | ||
2080 | ieee80211_recalc_ps(local, -1); | 2123 | ieee80211_recalc_ps(local, -1); |
2124 | ieee80211_recalc_ps_vif(sdata); | ||
2081 | 2125 | ||
2082 | return 0; | 2126 | return 0; |
2083 | } | 2127 | } |
@@ -2460,6 +2504,9 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2460 | if (!sdata->u.mgd.associated) | 2504 | if (!sdata->u.mgd.associated) |
2461 | need_offchan = true; | 2505 | need_offchan = true; |
2462 | break; | 2506 | break; |
2507 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2508 | need_offchan = true; | ||
2509 | break; | ||
2463 | default: | 2510 | default: |
2464 | return -EOPNOTSUPP; | 2511 | return -EOPNOTSUPP; |
2465 | } | 2512 | } |
@@ -2652,6 +2699,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2652 | u16 status_code, struct sk_buff *skb) | 2699 | u16 status_code, struct sk_buff *skb) |
2653 | { | 2700 | { |
2654 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2701 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2702 | struct ieee80211_local *local = sdata->local; | ||
2655 | struct ieee80211_tdls_data *tf; | 2703 | struct ieee80211_tdls_data *tf; |
2656 | 2704 | ||
2657 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | 2705 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); |
@@ -2671,8 +2719,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2671 | tf->u.setup_req.capability = | 2719 | tf->u.setup_req.capability = |
2672 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2720 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2673 | 2721 | ||
2674 | ieee80211_add_srates_ie(sdata, skb, false); | 2722 | ieee80211_add_srates_ie(sdata, skb, false, |
2675 | ieee80211_add_ext_srates_ie(sdata, skb, false); | 2723 | local->oper_channel->band); |
2724 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2725 | local->oper_channel->band); | ||
2676 | ieee80211_tdls_add_ext_capab(skb); | 2726 | ieee80211_tdls_add_ext_capab(skb); |
2677 | break; | 2727 | break; |
2678 | case WLAN_TDLS_SETUP_RESPONSE: | 2728 | case WLAN_TDLS_SETUP_RESPONSE: |
@@ -2685,8 +2735,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2685 | tf->u.setup_resp.capability = | 2735 | tf->u.setup_resp.capability = |
2686 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2736 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2687 | 2737 | ||
2688 | ieee80211_add_srates_ie(sdata, skb, false); | 2738 | ieee80211_add_srates_ie(sdata, skb, false, |
2689 | ieee80211_add_ext_srates_ie(sdata, skb, false); | 2739 | local->oper_channel->band); |
2740 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2741 | local->oper_channel->band); | ||
2690 | ieee80211_tdls_add_ext_capab(skb); | 2742 | ieee80211_tdls_add_ext_capab(skb); |
2691 | break; | 2743 | break; |
2692 | case WLAN_TDLS_SETUP_CONFIRM: | 2744 | case WLAN_TDLS_SETUP_CONFIRM: |
@@ -2724,6 +2776,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2724 | u16 status_code, struct sk_buff *skb) | 2776 | u16 status_code, struct sk_buff *skb) |
2725 | { | 2777 | { |
2726 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2778 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2779 | struct ieee80211_local *local = sdata->local; | ||
2727 | struct ieee80211_mgmt *mgmt; | 2780 | struct ieee80211_mgmt *mgmt; |
2728 | 2781 | ||
2729 | mgmt = (void *)skb_put(skb, 24); | 2782 | mgmt = (void *)skb_put(skb, 24); |
@@ -2746,8 +2799,10 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2746 | mgmt->u.action.u.tdls_discover_resp.capability = | 2799 | mgmt->u.action.u.tdls_discover_resp.capability = |
2747 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2800 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2748 | 2801 | ||
2749 | ieee80211_add_srates_ie(sdata, skb, false); | 2802 | ieee80211_add_srates_ie(sdata, skb, false, |
2750 | ieee80211_add_ext_srates_ie(sdata, skb, false); | 2803 | local->oper_channel->band); |
2804 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2805 | local->oper_channel->band); | ||
2751 | ieee80211_tdls_add_ext_capab(skb); | 2806 | ieee80211_tdls_add_ext_capab(skb); |
2752 | break; | 2807 | break; |
2753 | default: | 2808 | default: |
@@ -3004,6 +3059,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
3004 | .add_virtual_intf = ieee80211_add_iface, | 3059 | .add_virtual_intf = ieee80211_add_iface, |
3005 | .del_virtual_intf = ieee80211_del_iface, | 3060 | .del_virtual_intf = ieee80211_del_iface, |
3006 | .change_virtual_intf = ieee80211_change_iface, | 3061 | .change_virtual_intf = ieee80211_change_iface, |
3062 | .start_p2p_device = ieee80211_start_p2p_device, | ||
3063 | .stop_p2p_device = ieee80211_stop_p2p_device, | ||
3007 | .add_key = ieee80211_add_key, | 3064 | .add_key = ieee80211_add_key, |
3008 | .del_key = ieee80211_del_key, | 3065 | .del_key = ieee80211_del_key, |
3009 | .get_key = ieee80211_get_key, | 3066 | .get_key = ieee80211_get_key, |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f0f87e5a1d35..0bfc914ddd15 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -68,16 +68,14 @@ ieee80211_get_channel_mode(struct ieee80211_local *local, | |||
68 | return mode; | 68 | return mode; |
69 | } | 69 | } |
70 | 70 | ||
71 | bool ieee80211_set_channel_type(struct ieee80211_local *local, | 71 | static enum nl80211_channel_type |
72 | struct ieee80211_sub_if_data *sdata, | 72 | ieee80211_get_superchan(struct ieee80211_local *local, |
73 | enum nl80211_channel_type chantype) | 73 | struct ieee80211_sub_if_data *sdata) |
74 | { | 74 | { |
75 | struct ieee80211_sub_if_data *tmp; | ||
76 | enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT; | 75 | enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT; |
77 | bool result; | 76 | struct ieee80211_sub_if_data *tmp; |
78 | 77 | ||
79 | mutex_lock(&local->iflist_mtx); | 78 | mutex_lock(&local->iflist_mtx); |
80 | |||
81 | list_for_each_entry(tmp, &local->interfaces, list) { | 79 | list_for_each_entry(tmp, &local->interfaces, list) { |
82 | if (tmp == sdata) | 80 | if (tmp == sdata) |
83 | continue; | 81 | continue; |
@@ -103,39 +101,70 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
103 | break; | 101 | break; |
104 | } | 102 | } |
105 | } | 103 | } |
104 | mutex_unlock(&local->iflist_mtx); | ||
106 | 105 | ||
107 | switch (superchan) { | 106 | return superchan; |
107 | } | ||
108 | |||
109 | static bool | ||
110 | ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, | ||
111 | enum nl80211_channel_type chantype2, | ||
112 | enum nl80211_channel_type *compat) | ||
113 | { | ||
114 | /* | ||
115 | * start out with chantype1 being the result, | ||
116 | * overwriting later if needed | ||
117 | */ | ||
118 | if (compat) | ||
119 | *compat = chantype1; | ||
120 | |||
121 | switch (chantype1) { | ||
108 | case NL80211_CHAN_NO_HT: | 122 | case NL80211_CHAN_NO_HT: |
123 | if (compat) | ||
124 | *compat = chantype2; | ||
125 | break; | ||
109 | case NL80211_CHAN_HT20: | 126 | case NL80211_CHAN_HT20: |
110 | /* | 127 | /* |
111 | * allow any change that doesn't go to no-HT | 128 | * allow any change that doesn't go to no-HT |
112 | * (if it already is no-HT no change is needed) | 129 | * (if it already is no-HT no change is needed) |
113 | */ | 130 | */ |
114 | if (chantype == NL80211_CHAN_NO_HT) | 131 | if (chantype2 == NL80211_CHAN_NO_HT) |
115 | break; | 132 | break; |
116 | superchan = chantype; | 133 | if (compat) |
134 | *compat = chantype2; | ||
117 | break; | 135 | break; |
118 | case NL80211_CHAN_HT40PLUS: | 136 | case NL80211_CHAN_HT40PLUS: |
119 | case NL80211_CHAN_HT40MINUS: | 137 | case NL80211_CHAN_HT40MINUS: |
120 | /* allow smaller bandwidth and same */ | 138 | /* allow smaller bandwidth and same */ |
121 | if (chantype == NL80211_CHAN_NO_HT) | 139 | if (chantype2 == NL80211_CHAN_NO_HT) |
122 | break; | 140 | break; |
123 | if (chantype == NL80211_CHAN_HT20) | 141 | if (chantype2 == NL80211_CHAN_HT20) |
124 | break; | 142 | break; |
125 | if (superchan == chantype) | 143 | if (chantype2 == chantype1) |
126 | break; | 144 | break; |
127 | result = false; | 145 | return false; |
128 | goto out; | ||
129 | } | 146 | } |
130 | 147 | ||
131 | local->_oper_channel_type = superchan; | 148 | return true; |
149 | } | ||
150 | |||
151 | bool ieee80211_set_channel_type(struct ieee80211_local *local, | ||
152 | struct ieee80211_sub_if_data *sdata, | ||
153 | enum nl80211_channel_type chantype) | ||
154 | { | ||
155 | enum nl80211_channel_type superchan; | ||
156 | enum nl80211_channel_type compatchan; | ||
157 | |||
158 | superchan = ieee80211_get_superchan(local, sdata); | ||
159 | if (!ieee80211_channel_types_are_compatible(superchan, chantype, | ||
160 | &compatchan)) | ||
161 | return false; | ||
162 | |||
163 | local->_oper_channel_type = compatchan; | ||
132 | 164 | ||
133 | if (sdata) | 165 | if (sdata) |
134 | sdata->vif.bss_conf.channel_type = chantype; | 166 | sdata->vif.bss_conf.channel_type = chantype; |
135 | 167 | ||
136 | result = true; | 168 | return true; |
137 | out: | ||
138 | mutex_unlock(&local->iflist_mtx); | ||
139 | 169 | ||
140 | return result; | ||
141 | } | 170 | } |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index b8dfb440c8ef..466f4b45dd94 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -63,8 +63,6 @@ DEBUGFS_READONLY_FILE(user_power, "%d", | |||
63 | local->user_power_level); | 63 | local->user_power_level); |
64 | DEBUGFS_READONLY_FILE(power, "%d", | 64 | DEBUGFS_READONLY_FILE(power, "%d", |
65 | local->hw.conf.power_level); | 65 | local->hw.conf.power_level); |
66 | DEBUGFS_READONLY_FILE(frequency, "%d", | ||
67 | local->hw.conf.channel->center_freq); | ||
68 | DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", | 66 | DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", |
69 | local->total_ps_buffered); | 67 | local->total_ps_buffered); |
70 | DEBUGFS_READONLY_FILE(wep_iv, "%#08x", | 68 | DEBUGFS_READONLY_FILE(wep_iv, "%#08x", |
@@ -72,6 +70,7 @@ DEBUGFS_READONLY_FILE(wep_iv, "%#08x", | |||
72 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", | 70 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", |
73 | local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); | 71 | local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); |
74 | 72 | ||
73 | #ifdef CONFIG_PM | ||
75 | static ssize_t reset_write(struct file *file, const char __user *user_buf, | 74 | static ssize_t reset_write(struct file *file, const char __user *user_buf, |
76 | size_t count, loff_t *ppos) | 75 | size_t count, loff_t *ppos) |
77 | { | 76 | { |
@@ -90,33 +89,7 @@ static const struct file_operations reset_ops = { | |||
90 | .open = simple_open, | 89 | .open = simple_open, |
91 | .llseek = noop_llseek, | 90 | .llseek = noop_llseek, |
92 | }; | 91 | }; |
93 | 92 | #endif | |
94 | static ssize_t channel_type_read(struct file *file, char __user *user_buf, | ||
95 | size_t count, loff_t *ppos) | ||
96 | { | ||
97 | struct ieee80211_local *local = file->private_data; | ||
98 | const char *buf; | ||
99 | |||
100 | switch (local->hw.conf.channel_type) { | ||
101 | case NL80211_CHAN_NO_HT: | ||
102 | buf = "no ht\n"; | ||
103 | break; | ||
104 | case NL80211_CHAN_HT20: | ||
105 | buf = "ht20\n"; | ||
106 | break; | ||
107 | case NL80211_CHAN_HT40MINUS: | ||
108 | buf = "ht40-\n"; | ||
109 | break; | ||
110 | case NL80211_CHAN_HT40PLUS: | ||
111 | buf = "ht40+\n"; | ||
112 | break; | ||
113 | default: | ||
114 | buf = "???"; | ||
115 | break; | ||
116 | } | ||
117 | |||
118 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | ||
119 | } | ||
120 | 93 | ||
121 | static ssize_t hwflags_read(struct file *file, char __user *user_buf, | 94 | static ssize_t hwflags_read(struct file *file, char __user *user_buf, |
122 | size_t count, loff_t *ppos) | 95 | size_t count, loff_t *ppos) |
@@ -205,7 +178,6 @@ static ssize_t queues_read(struct file *file, char __user *user_buf, | |||
205 | } | 178 | } |
206 | 179 | ||
207 | DEBUGFS_READONLY_FILE_OPS(hwflags); | 180 | DEBUGFS_READONLY_FILE_OPS(hwflags); |
208 | DEBUGFS_READONLY_FILE_OPS(channel_type); | ||
209 | DEBUGFS_READONLY_FILE_OPS(queues); | 181 | DEBUGFS_READONLY_FILE_OPS(queues); |
210 | 182 | ||
211 | /* statistics stuff */ | 183 | /* statistics stuff */ |
@@ -272,12 +244,12 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
272 | 244 | ||
273 | local->debugfs.keys = debugfs_create_dir("keys", phyd); | 245 | local->debugfs.keys = debugfs_create_dir("keys", phyd); |
274 | 246 | ||
275 | DEBUGFS_ADD(frequency); | ||
276 | DEBUGFS_ADD(total_ps_buffered); | 247 | DEBUGFS_ADD(total_ps_buffered); |
277 | DEBUGFS_ADD(wep_iv); | 248 | DEBUGFS_ADD(wep_iv); |
278 | DEBUGFS_ADD(queues); | 249 | DEBUGFS_ADD(queues); |
250 | #ifdef CONFIG_PM | ||
279 | DEBUGFS_ADD_MODE(reset, 0200); | 251 | DEBUGFS_ADD_MODE(reset, 0200); |
280 | DEBUGFS_ADD(channel_type); | 252 | #endif |
281 | DEBUGFS_ADD(hwflags); | 253 | DEBUGFS_ADD(hwflags); |
282 | DEBUGFS_ADD(user_power); | 254 | DEBUGFS_ADD(user_power); |
283 | DEBUGFS_ADD(power); | 255 | DEBUGFS_ADD(power); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index df9203199102..da9003b20004 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -9,7 +9,7 @@ static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) | |||
9 | { | 9 | { |
10 | WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), | 10 | WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), |
11 | "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", | 11 | "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", |
12 | sdata->dev->name, sdata->flags); | 12 | sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); |
13 | } | 13 | } |
14 | 14 | ||
15 | static inline struct ieee80211_sub_if_data * | 15 | static inline struct ieee80211_sub_if_data * |
@@ -22,9 +22,11 @@ get_bss_sdata(struct ieee80211_sub_if_data *sdata) | |||
22 | return sdata; | 22 | return sdata; |
23 | } | 23 | } |
24 | 24 | ||
25 | static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb) | 25 | static inline void drv_tx(struct ieee80211_local *local, |
26 | struct ieee80211_tx_control *control, | ||
27 | struct sk_buff *skb) | ||
26 | { | 28 | { |
27 | local->ops->tx(&local->hw, skb); | 29 | local->ops->tx(&local->hw, control, skb); |
28 | } | 30 | } |
29 | 31 | ||
30 | static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, | 32 | static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, |
@@ -526,6 +528,9 @@ static inline void drv_sta_rc_update(struct ieee80211_local *local, | |||
526 | sdata = get_bss_sdata(sdata); | 528 | sdata = get_bss_sdata(sdata); |
527 | check_sdata_in_driver(sdata); | 529 | check_sdata_in_driver(sdata); |
528 | 530 | ||
531 | WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && | ||
532 | sdata->vif.type != NL80211_IFTYPE_ADHOC); | ||
533 | |||
529 | trace_drv_sta_rc_update(local, sdata, sta, changed); | 534 | trace_drv_sta_rc_update(local, sdata, sta, changed); |
530 | if (local->ops->sta_rc_update) | 535 | if (local->ops->sta_rc_update) |
531 | local->ops->sta_rc_update(&local->hw, &sdata->vif, | 536 | local->ops->sta_rc_update(&local->hw, &sdata->vif, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5746d62faba1..5f3620f0bc0a 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -109,7 +109,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
109 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 109 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
110 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 110 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
111 | IEEE80211_STYPE_PROBE_RESP); | 111 | IEEE80211_STYPE_PROBE_RESP); |
112 | memset(mgmt->da, 0xff, ETH_ALEN); | 112 | eth_broadcast_addr(mgmt->da); |
113 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 113 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
114 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); | 114 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); |
115 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); | 115 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); |
@@ -205,7 +205,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
205 | mod_timer(&ifibss->timer, | 205 | mod_timer(&ifibss->timer, |
206 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); | 206 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); |
207 | 207 | ||
208 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, | 208 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, |
209 | mgmt, skb->len, 0, GFP_KERNEL); | 209 | mgmt, skb->len, 0, GFP_KERNEL); |
210 | cfg80211_put_bss(bss); | 210 | cfg80211_put_bss(bss); |
211 | netif_carrier_on(sdata->dev); | 211 | netif_carrier_on(sdata->dev); |
@@ -278,7 +278,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, | |||
278 | if (auth && !sdata->u.ibss.auth_frame_registrations) { | 278 | if (auth && !sdata->u.ibss.auth_frame_registrations) { |
279 | ibss_dbg(sdata, | 279 | ibss_dbg(sdata, |
280 | "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", | 280 | "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", |
281 | sdata->vif.addr, sdata->u.ibss.bssid, addr); | 281 | sdata->vif.addr, addr, sdata->u.ibss.bssid); |
282 | ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0, | 282 | ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0, |
283 | addr, sdata->u.ibss.bssid, NULL, 0, 0); | 283 | addr, sdata->u.ibss.bssid, NULL, 0, 0); |
284 | } | 284 | } |
@@ -294,7 +294,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
294 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 294 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
295 | struct ieee80211_local *local = sdata->local; | 295 | struct ieee80211_local *local = sdata->local; |
296 | struct sta_info *sta; | 296 | struct sta_info *sta; |
297 | int band = local->hw.conf.channel->band; | 297 | int band = local->oper_channel->band; |
298 | 298 | ||
299 | /* | 299 | /* |
300 | * XXX: Consider removing the least recently used entry and | 300 | * XXX: Consider removing the least recently used entry and |
@@ -332,11 +332,27 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
332 | return ieee80211_ibss_finish_sta(sta, auth); | 332 | return ieee80211_ibss_finish_sta(sta, auth); |
333 | } | 333 | } |
334 | 334 | ||
335 | static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, | ||
336 | struct ieee80211_mgmt *mgmt, | ||
337 | size_t len) | ||
338 | { | ||
339 | u16 reason = le16_to_cpu(mgmt->u.deauth.reason_code); | ||
340 | |||
341 | if (len < IEEE80211_DEAUTH_FRAME_LEN) | ||
342 | return; | ||
343 | |||
344 | ibss_dbg(sdata, "RX DeAuth SA=%pM DA=%pM BSSID=%pM (reason: %d)\n", | ||
345 | mgmt->sa, mgmt->da, mgmt->bssid, reason); | ||
346 | sta_info_destroy_addr(sdata, mgmt->sa); | ||
347 | } | ||
348 | |||
335 | static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | 349 | static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, |
336 | struct ieee80211_mgmt *mgmt, | 350 | struct ieee80211_mgmt *mgmt, |
337 | size_t len) | 351 | size_t len) |
338 | { | 352 | { |
339 | u16 auth_alg, auth_transaction; | 353 | u16 auth_alg, auth_transaction; |
354 | struct sta_info *sta; | ||
355 | u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | ||
340 | 356 | ||
341 | lockdep_assert_held(&sdata->u.ibss.mtx); | 357 | lockdep_assert_held(&sdata->u.ibss.mtx); |
342 | 358 | ||
@@ -352,10 +368,22 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
352 | "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", | 368 | "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", |
353 | mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); | 369 | mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); |
354 | sta_info_destroy_addr(sdata, mgmt->sa); | 370 | sta_info_destroy_addr(sdata, mgmt->sa); |
355 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); | 371 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); |
356 | rcu_read_unlock(); | 372 | rcu_read_unlock(); |
357 | 373 | ||
358 | /* | 374 | /* |
375 | * if we have any problem in allocating the new station, we reply with a | ||
376 | * DEAUTH frame to tell the other end that we had a problem | ||
377 | */ | ||
378 | if (!sta) { | ||
379 | ieee80211_send_deauth_disassoc(sdata, sdata->u.ibss.bssid, | ||
380 | IEEE80211_STYPE_DEAUTH, | ||
381 | WLAN_REASON_UNSPECIFIED, true, | ||
382 | deauth_frame_buf); | ||
383 | return; | ||
384 | } | ||
385 | |||
386 | /* | ||
359 | * IEEE 802.11 standard does not require authentication in IBSS | 387 | * IEEE 802.11 standard does not require authentication in IBSS |
360 | * networks and most implementations do not seem to use it. | 388 | * networks and most implementations do not seem to use it. |
361 | * However, try to reply to authentication attempts if someone | 389 | * However, try to reply to authentication attempts if someone |
@@ -459,8 +487,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
459 | } | 487 | } |
460 | } | 488 | } |
461 | 489 | ||
462 | if (sta && rates_updated) | 490 | if (sta && rates_updated) { |
491 | drv_sta_rc_update(local, sdata, &sta->sta, | ||
492 | IEEE80211_RC_SUPP_RATES_CHANGED); | ||
463 | rate_control_rate_init(sta); | 493 | rate_control_rate_init(sta); |
494 | } | ||
464 | 495 | ||
465 | rcu_read_unlock(); | 496 | rcu_read_unlock(); |
466 | } | 497 | } |
@@ -561,7 +592,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
561 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 592 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
562 | struct ieee80211_local *local = sdata->local; | 593 | struct ieee80211_local *local = sdata->local; |
563 | struct sta_info *sta; | 594 | struct sta_info *sta; |
564 | int band = local->hw.conf.channel->band; | 595 | int band = local->oper_channel->band; |
565 | 596 | ||
566 | /* | 597 | /* |
567 | * XXX: Consider removing the least recently used entry and | 598 | * XXX: Consider removing the least recently used entry and |
@@ -759,7 +790,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
759 | return; | 790 | return; |
760 | } | 791 | } |
761 | sdata_info(sdata, "IBSS not allowed on %d MHz\n", | 792 | sdata_info(sdata, "IBSS not allowed on %d MHz\n", |
762 | local->hw.conf.channel->center_freq); | 793 | local->oper_channel->center_freq); |
763 | 794 | ||
764 | /* No IBSS found - decrease scan interval and continue | 795 | /* No IBSS found - decrease scan interval and continue |
765 | * scanning. */ | 796 | * scanning. */ |
@@ -899,6 +930,9 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
899 | case IEEE80211_STYPE_AUTH: | 930 | case IEEE80211_STYPE_AUTH: |
900 | ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len); | 931 | ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len); |
901 | break; | 932 | break; |
933 | case IEEE80211_STYPE_DEAUTH: | ||
934 | ieee80211_rx_mgmt_deauth_ibss(sdata, mgmt, skb->len); | ||
935 | break; | ||
902 | } | 936 | } |
903 | 937 | ||
904 | mgmt_out: | 938 | mgmt_out: |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index bb61f7718c4c..8c804550465b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -68,6 +68,8 @@ struct ieee80211_local; | |||
68 | #define IEEE80211_DEFAULT_MAX_SP_LEN \ | 68 | #define IEEE80211_DEFAULT_MAX_SP_LEN \ |
69 | IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL | 69 | IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL |
70 | 70 | ||
71 | #define IEEE80211_DEAUTH_FRAME_LEN (24 /* hdr */ + 2 /* reason */) | ||
72 | |||
71 | struct ieee80211_fragment_entry { | 73 | struct ieee80211_fragment_entry { |
72 | unsigned long first_frag_time; | 74 | unsigned long first_frag_time; |
73 | unsigned int seq; | 75 | unsigned int seq; |
@@ -193,8 +195,6 @@ struct ieee80211_tx_data { | |||
193 | struct sta_info *sta; | 195 | struct sta_info *sta; |
194 | struct ieee80211_key *key; | 196 | struct ieee80211_key *key; |
195 | 197 | ||
196 | struct ieee80211_channel *channel; | ||
197 | |||
198 | unsigned int flags; | 198 | unsigned int flags; |
199 | }; | 199 | }; |
200 | 200 | ||
@@ -274,9 +274,15 @@ struct beacon_data { | |||
274 | struct rcu_head rcu_head; | 274 | struct rcu_head rcu_head; |
275 | }; | 275 | }; |
276 | 276 | ||
277 | struct probe_resp { | ||
278 | struct rcu_head rcu_head; | ||
279 | int len; | ||
280 | u8 data[0]; | ||
281 | }; | ||
282 | |||
277 | struct ieee80211_if_ap { | 283 | struct ieee80211_if_ap { |
278 | struct beacon_data __rcu *beacon; | 284 | struct beacon_data __rcu *beacon; |
279 | struct sk_buff __rcu *probe_resp; | 285 | struct probe_resp __rcu *probe_resp; |
280 | 286 | ||
281 | struct list_head vlans; | 287 | struct list_head vlans; |
282 | 288 | ||
@@ -359,6 +365,7 @@ enum ieee80211_sta_flags { | |||
359 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | 365 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), |
360 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), | 366 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), |
361 | IEEE80211_STA_DISABLE_40MHZ = BIT(10), | 367 | IEEE80211_STA_DISABLE_40MHZ = BIT(10), |
368 | IEEE80211_STA_DISABLE_VHT = BIT(11), | ||
362 | }; | 369 | }; |
363 | 370 | ||
364 | struct ieee80211_mgd_auth_data { | 371 | struct ieee80211_mgd_auth_data { |
@@ -406,6 +413,7 @@ struct ieee80211_if_managed { | |||
406 | struct work_struct monitor_work; | 413 | struct work_struct monitor_work; |
407 | struct work_struct chswitch_work; | 414 | struct work_struct chswitch_work; |
408 | struct work_struct beacon_connection_loss_work; | 415 | struct work_struct beacon_connection_loss_work; |
416 | struct work_struct csa_connection_drop_work; | ||
409 | 417 | ||
410 | unsigned long beacon_timeout; | 418 | unsigned long beacon_timeout; |
411 | unsigned long probe_timeout; | 419 | unsigned long probe_timeout; |
@@ -965,7 +973,6 @@ struct ieee80211_local { | |||
965 | int scan_channel_idx; | 973 | int scan_channel_idx; |
966 | int scan_ies_len; | 974 | int scan_ies_len; |
967 | 975 | ||
968 | struct ieee80211_sched_scan_ies sched_scan_ies; | ||
969 | struct work_struct sched_scan_stopped_work; | 976 | struct work_struct sched_scan_stopped_work; |
970 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; | 977 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; |
971 | 978 | ||
@@ -1052,7 +1059,7 @@ struct ieee80211_local { | |||
1052 | bool disable_dynamic_ps; | 1059 | bool disable_dynamic_ps; |
1053 | 1060 | ||
1054 | int user_power_level; /* in dBm */ | 1061 | int user_power_level; /* in dBm */ |
1055 | int power_constr_level; /* in dBm */ | 1062 | int ap_power_level; /* in dBm */ |
1056 | 1063 | ||
1057 | enum ieee80211_smps_mode smps_mode; | 1064 | enum ieee80211_smps_mode smps_mode; |
1058 | 1065 | ||
@@ -1075,6 +1082,8 @@ struct ieee80211_local { | |||
1075 | struct idr ack_status_frames; | 1082 | struct idr ack_status_frames; |
1076 | spinlock_t ack_status_lock; | 1083 | spinlock_t ack_status_lock; |
1077 | 1084 | ||
1085 | struct ieee80211_sub_if_data __rcu *p2p_sdata; | ||
1086 | |||
1078 | /* dummy netdev for use w/ NAPI */ | 1087 | /* dummy netdev for use w/ NAPI */ |
1079 | struct net_device napi_dev; | 1088 | struct net_device napi_dev; |
1080 | 1089 | ||
@@ -1131,7 +1140,7 @@ struct ieee802_11_elems { | |||
1131 | u8 *prep; | 1140 | u8 *prep; |
1132 | u8 *perr; | 1141 | u8 *perr; |
1133 | struct ieee80211_rann_ie *rann; | 1142 | struct ieee80211_rann_ie *rann; |
1134 | u8 *ch_switch_elem; | 1143 | struct ieee80211_channel_sw_ie *ch_switch_ie; |
1135 | u8 *country_elem; | 1144 | u8 *country_elem; |
1136 | u8 *pwr_constr_elem; | 1145 | u8 *pwr_constr_elem; |
1137 | u8 *quiet_elem; /* first quite element */ | 1146 | u8 *quiet_elem; /* first quite element */ |
@@ -1157,9 +1166,7 @@ struct ieee802_11_elems { | |||
1157 | u8 preq_len; | 1166 | u8 preq_len; |
1158 | u8 prep_len; | 1167 | u8 prep_len; |
1159 | u8 perr_len; | 1168 | u8 perr_len; |
1160 | u8 ch_switch_elem_len; | ||
1161 | u8 country_elem_len; | 1169 | u8 country_elem_len; |
1162 | u8 pwr_constr_elem_len; | ||
1163 | u8 quiet_elem_len; | 1170 | u8 quiet_elem_len; |
1164 | u8 num_of_quiet_elem; /* can be more the one */ | 1171 | u8 num_of_quiet_elem; /* can be more the one */ |
1165 | u8 timeout_int_len; | 1172 | u8 timeout_int_len; |
@@ -1202,6 +1209,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1202 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 1209 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
1203 | struct ieee80211_sub_if_data *sdata); | 1210 | struct ieee80211_sub_if_data *sdata); |
1204 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); | 1211 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); |
1212 | void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata); | ||
1205 | int ieee80211_max_network_latency(struct notifier_block *nb, | 1213 | int ieee80211_max_network_latency(struct notifier_block *nb, |
1206 | unsigned long data, void *dummy); | 1214 | unsigned long data, void *dummy); |
1207 | int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata); | 1215 | int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata); |
@@ -1291,6 +1299,8 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local); | |||
1291 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1299 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
1292 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | 1300 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, |
1293 | const int offset); | 1301 | const int offset); |
1302 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); | ||
1303 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); | ||
1294 | 1304 | ||
1295 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | 1305 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) |
1296 | { | 1306 | { |
@@ -1358,7 +1368,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | |||
1358 | int ieee80211_reconfig(struct ieee80211_local *local); | 1368 | int ieee80211_reconfig(struct ieee80211_local *local); |
1359 | void ieee80211_stop_device(struct ieee80211_local *local); | 1369 | void ieee80211_stop_device(struct ieee80211_local *local); |
1360 | 1370 | ||
1361 | #ifdef CONFIG_PM | ||
1362 | int __ieee80211_suspend(struct ieee80211_hw *hw, | 1371 | int __ieee80211_suspend(struct ieee80211_hw *hw, |
1363 | struct cfg80211_wowlan *wowlan); | 1372 | struct cfg80211_wowlan *wowlan); |
1364 | 1373 | ||
@@ -1372,18 +1381,6 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) | |||
1372 | 1381 | ||
1373 | return ieee80211_reconfig(hw_to_local(hw)); | 1382 | return ieee80211_reconfig(hw_to_local(hw)); |
1374 | } | 1383 | } |
1375 | #else | ||
1376 | static inline int __ieee80211_suspend(struct ieee80211_hw *hw, | ||
1377 | struct cfg80211_wowlan *wowlan) | ||
1378 | { | ||
1379 | return 0; | ||
1380 | } | ||
1381 | |||
1382 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) | ||
1383 | { | ||
1384 | return 0; | ||
1385 | } | ||
1386 | #endif | ||
1387 | 1384 | ||
1388 | /* utility functions/constants */ | 1385 | /* utility functions/constants */ |
1389 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 1386 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
@@ -1425,7 +1422,6 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
1425 | struct ieee80211_hdr *hdr); | 1422 | struct ieee80211_hdr *hdr); |
1426 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | 1423 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, |
1427 | struct ieee80211_hdr *hdr, bool ack); | 1424 | struct ieee80211_hdr *hdr, bool ack); |
1428 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); | ||
1429 | 1425 | ||
1430 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1426 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1431 | enum queue_stop_reason reason); | 1427 | enum queue_stop_reason reason); |
@@ -1451,19 +1447,24 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
1451 | u16 transaction, u16 auth_alg, | 1447 | u16 transaction, u16 auth_alg, |
1452 | u8 *extra, size_t extra_len, const u8 *bssid, | 1448 | u8 *extra, size_t extra_len, const u8 *bssid, |
1453 | const u8 *da, const u8 *key, u8 key_len, u8 key_idx); | 1449 | const u8 *da, const u8 *key, u8 key_len, u8 key_idx); |
1450 | void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | ||
1451 | const u8 *bssid, u16 stype, u16 reason, | ||
1452 | bool send_frame, u8 *frame_buf); | ||
1454 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1453 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1455 | const u8 *ie, size_t ie_len, | 1454 | const u8 *ie, size_t ie_len, |
1456 | enum ieee80211_band band, u32 rate_mask, | 1455 | enum ieee80211_band band, u32 rate_mask, |
1457 | u8 channel); | 1456 | u8 channel); |
1458 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1457 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1459 | u8 *dst, u32 ratemask, | 1458 | u8 *dst, u32 ratemask, |
1459 | struct ieee80211_channel *chan, | ||
1460 | const u8 *ssid, size_t ssid_len, | 1460 | const u8 *ssid, size_t ssid_len, |
1461 | const u8 *ie, size_t ie_len, | 1461 | const u8 *ie, size_t ie_len, |
1462 | bool directed); | 1462 | bool directed); |
1463 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1463 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1464 | const u8 *ssid, size_t ssid_len, | 1464 | const u8 *ssid, size_t ssid_len, |
1465 | const u8 *ie, size_t ie_len, | 1465 | const u8 *ie, size_t ie_len, |
1466 | u32 ratemask, bool directed, bool no_cck); | 1466 | u32 ratemask, bool directed, bool no_cck, |
1467 | struct ieee80211_channel *channel); | ||
1467 | 1468 | ||
1468 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 1469 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
1469 | const size_t supp_rates_len, | 1470 | const size_t supp_rates_len, |
@@ -1487,9 +1488,11 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1487 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | 1488 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, |
1488 | u32 cap); | 1489 | u32 cap); |
1489 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 1490 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
1490 | struct sk_buff *skb, bool need_basic); | 1491 | struct sk_buff *skb, bool need_basic, |
1492 | enum ieee80211_band band); | ||
1491 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | 1493 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, |
1492 | struct sk_buff *skb, bool need_basic); | 1494 | struct sk_buff *skb, bool need_basic, |
1495 | enum ieee80211_band band); | ||
1493 | 1496 | ||
1494 | /* channel management */ | 1497 | /* channel management */ |
1495 | enum ieee80211_chan_mode { | 1498 | enum ieee80211_chan_mode { |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index bfb57dcc1538..6f8a73c64fb3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -100,6 +100,10 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
100 | sdata->vif.bss_conf.idle = true; | 100 | sdata->vif.bss_conf.idle = true; |
101 | continue; | 101 | continue; |
102 | } | 102 | } |
103 | |||
104 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
105 | continue; | ||
106 | |||
103 | /* count everything else */ | 107 | /* count everything else */ |
104 | sdata->vif.bss_conf.idle = false; | 108 | sdata->vif.bss_conf.idle = false; |
105 | count++; | 109 | count++; |
@@ -121,7 +125,8 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
121 | 125 | ||
122 | list_for_each_entry(sdata, &local->interfaces, list) { | 126 | list_for_each_entry(sdata, &local->interfaces, list) { |
123 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 127 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
124 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 128 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
129 | sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
125 | continue; | 130 | continue; |
126 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | 131 | if (sdata->old_idle == sdata->vif.bss_conf.idle) |
127 | continue; | 132 | continue; |
@@ -204,6 +209,8 @@ static inline int identical_mac_addr_allowed(int type1, int type2) | |||
204 | { | 209 | { |
205 | return type1 == NL80211_IFTYPE_MONITOR || | 210 | return type1 == NL80211_IFTYPE_MONITOR || |
206 | type2 == NL80211_IFTYPE_MONITOR || | 211 | type2 == NL80211_IFTYPE_MONITOR || |
212 | type1 == NL80211_IFTYPE_P2P_DEVICE || | ||
213 | type2 == NL80211_IFTYPE_P2P_DEVICE || | ||
207 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || | 214 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || |
208 | (type1 == NL80211_IFTYPE_WDS && | 215 | (type1 == NL80211_IFTYPE_WDS && |
209 | (type2 == NL80211_IFTYPE_WDS || | 216 | (type2 == NL80211_IFTYPE_WDS || |
@@ -271,13 +278,15 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata) | |||
271 | int n_queues = sdata->local->hw.queues; | 278 | int n_queues = sdata->local->hw.queues; |
272 | int i; | 279 | int i; |
273 | 280 | ||
274 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | 281 | if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) { |
275 | if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == | 282 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
276 | IEEE80211_INVAL_HW_QUEUE)) | 283 | if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == |
277 | return -EINVAL; | 284 | IEEE80211_INVAL_HW_QUEUE)) |
278 | if (WARN_ON_ONCE(sdata->vif.hw_queue[i] >= | 285 | return -EINVAL; |
279 | n_queues)) | 286 | if (WARN_ON_ONCE(sdata->vif.hw_queue[i] >= |
280 | return -EINVAL; | 287 | n_queues)) |
288 | return -EINVAL; | ||
289 | } | ||
281 | } | 290 | } |
282 | 291 | ||
283 | if ((sdata->vif.type != NL80211_IFTYPE_AP) || | 292 | if ((sdata->vif.type != NL80211_IFTYPE_AP) || |
@@ -406,9 +415,10 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
406 | * an error on interface type changes that have been pre-checked, so most | 415 | * an error on interface type changes that have been pre-checked, so most |
407 | * checks should be in ieee80211_check_concurrent_iface. | 416 | * checks should be in ieee80211_check_concurrent_iface. |
408 | */ | 417 | */ |
409 | static int ieee80211_do_open(struct net_device *dev, bool coming_up) | 418 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) |
410 | { | 419 | { |
411 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 420 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
421 | struct net_device *dev = wdev->netdev; | ||
412 | struct ieee80211_local *local = sdata->local; | 422 | struct ieee80211_local *local = sdata->local; |
413 | struct sta_info *sta; | 423 | struct sta_info *sta; |
414 | u32 changed = 0; | 424 | u32 changed = 0; |
@@ -443,6 +453,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
443 | case NL80211_IFTYPE_STATION: | 453 | case NL80211_IFTYPE_STATION: |
444 | case NL80211_IFTYPE_MONITOR: | 454 | case NL80211_IFTYPE_MONITOR: |
445 | case NL80211_IFTYPE_ADHOC: | 455 | case NL80211_IFTYPE_ADHOC: |
456 | case NL80211_IFTYPE_P2P_DEVICE: | ||
446 | /* no special treatment */ | 457 | /* no special treatment */ |
447 | break; | 458 | break; |
448 | case NL80211_IFTYPE_UNSPECIFIED: | 459 | case NL80211_IFTYPE_UNSPECIFIED: |
@@ -471,7 +482,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
471 | * Copy the hopefully now-present MAC address to | 482 | * Copy the hopefully now-present MAC address to |
472 | * this interface, if it has the special null one. | 483 | * this interface, if it has the special null one. |
473 | */ | 484 | */ |
474 | if (is_zero_ether_addr(dev->dev_addr)) { | 485 | if (dev && is_zero_ether_addr(dev->dev_addr)) { |
475 | memcpy(dev->dev_addr, | 486 | memcpy(dev->dev_addr, |
476 | local->hw.wiphy->perm_addr, | 487 | local->hw.wiphy->perm_addr, |
477 | ETH_ALEN); | 488 | ETH_ALEN); |
@@ -536,15 +547,23 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
536 | local->fif_probe_req++; | 547 | local->fif_probe_req++; |
537 | } | 548 | } |
538 | 549 | ||
539 | changed |= ieee80211_reset_erp_info(sdata); | 550 | if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) |
551 | changed |= ieee80211_reset_erp_info(sdata); | ||
540 | ieee80211_bss_info_change_notify(sdata, changed); | 552 | ieee80211_bss_info_change_notify(sdata, changed); |
541 | 553 | ||
542 | if (sdata->vif.type == NL80211_IFTYPE_STATION || | 554 | switch (sdata->vif.type) { |
543 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | 555 | case NL80211_IFTYPE_STATION: |
544 | sdata->vif.type == NL80211_IFTYPE_AP) | 556 | case NL80211_IFTYPE_ADHOC: |
557 | case NL80211_IFTYPE_AP: | ||
558 | case NL80211_IFTYPE_MESH_POINT: | ||
545 | netif_carrier_off(dev); | 559 | netif_carrier_off(dev); |
546 | else | 560 | break; |
561 | case NL80211_IFTYPE_WDS: | ||
562 | case NL80211_IFTYPE_P2P_DEVICE: | ||
563 | break; | ||
564 | default: | ||
547 | netif_carrier_on(dev); | 565 | netif_carrier_on(dev); |
566 | } | ||
548 | 567 | ||
549 | /* | 568 | /* |
550 | * set default queue parameters so drivers don't | 569 | * set default queue parameters so drivers don't |
@@ -576,6 +595,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
576 | } | 595 | } |
577 | 596 | ||
578 | rate_control_rate_init(sta); | 597 | rate_control_rate_init(sta); |
598 | netif_carrier_on(dev); | ||
599 | } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { | ||
600 | rcu_assign_pointer(local->p2p_sdata, sdata); | ||
579 | } | 601 | } |
580 | 602 | ||
581 | /* | 603 | /* |
@@ -601,7 +623,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
601 | 623 | ||
602 | ieee80211_recalc_ps(local, -1); | 624 | ieee80211_recalc_ps(local, -1); |
603 | 625 | ||
604 | netif_tx_start_all_queues(dev); | 626 | if (dev) |
627 | netif_tx_start_all_queues(dev); | ||
605 | 628 | ||
606 | return 0; | 629 | return 0; |
607 | err_del_interface: | 630 | err_del_interface: |
@@ -631,7 +654,7 @@ static int ieee80211_open(struct net_device *dev) | |||
631 | if (err) | 654 | if (err) |
632 | return err; | 655 | return err; |
633 | 656 | ||
634 | return ieee80211_do_open(dev, true); | 657 | return ieee80211_do_open(&sdata->wdev, true); |
635 | } | 658 | } |
636 | 659 | ||
637 | static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | 660 | static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, |
@@ -652,7 +675,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
652 | /* | 675 | /* |
653 | * Stop TX on this interface first. | 676 | * Stop TX on this interface first. |
654 | */ | 677 | */ |
655 | netif_tx_stop_all_queues(sdata->dev); | 678 | if (sdata->dev) |
679 | netif_tx_stop_all_queues(sdata->dev); | ||
656 | 680 | ||
657 | ieee80211_roc_purge(sdata); | 681 | ieee80211_roc_purge(sdata); |
658 | 682 | ||
@@ -691,14 +715,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
691 | local->fif_probe_req--; | 715 | local->fif_probe_req--; |
692 | } | 716 | } |
693 | 717 | ||
694 | netif_addr_lock_bh(sdata->dev); | 718 | if (sdata->dev) { |
695 | spin_lock_bh(&local->filter_lock); | 719 | netif_addr_lock_bh(sdata->dev); |
696 | __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, | 720 | spin_lock_bh(&local->filter_lock); |
697 | sdata->dev->addr_len); | 721 | __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, |
698 | spin_unlock_bh(&local->filter_lock); | 722 | sdata->dev->addr_len); |
699 | netif_addr_unlock_bh(sdata->dev); | 723 | spin_unlock_bh(&local->filter_lock); |
724 | netif_addr_unlock_bh(sdata->dev); | ||
700 | 725 | ||
701 | ieee80211_configure_filter(local); | 726 | ieee80211_configure_filter(local); |
727 | } | ||
702 | 728 | ||
703 | del_timer_sync(&local->dynamic_ps_timer); | 729 | del_timer_sync(&local->dynamic_ps_timer); |
704 | cancel_work_sync(&local->dynamic_ps_enable_work); | 730 | cancel_work_sync(&local->dynamic_ps_enable_work); |
@@ -708,7 +734,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
708 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 734 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
709 | struct beacon_data *old_beacon = | 735 | struct beacon_data *old_beacon = |
710 | rtnl_dereference(sdata->u.ap.beacon); | 736 | rtnl_dereference(sdata->u.ap.beacon); |
711 | struct sk_buff *old_probe_resp = | 737 | struct probe_resp *old_probe_resp = |
712 | rtnl_dereference(sdata->u.ap.probe_resp); | 738 | rtnl_dereference(sdata->u.ap.probe_resp); |
713 | 739 | ||
714 | /* sdata_running will return false, so this will disable */ | 740 | /* sdata_running will return false, so this will disable */ |
@@ -720,7 +746,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
720 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | 746 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); |
721 | synchronize_rcu(); | 747 | synchronize_rcu(); |
722 | kfree(old_beacon); | 748 | kfree(old_beacon); |
723 | kfree_skb(old_probe_resp); | 749 | kfree(old_probe_resp); |
724 | 750 | ||
725 | /* down all dependent devices, that is VLANs */ | 751 | /* down all dependent devices, that is VLANs */ |
726 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 752 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
@@ -759,24 +785,29 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
759 | ieee80211_adjust_monitor_flags(sdata, -1); | 785 | ieee80211_adjust_monitor_flags(sdata, -1); |
760 | ieee80211_configure_filter(local); | 786 | ieee80211_configure_filter(local); |
761 | break; | 787 | break; |
788 | case NL80211_IFTYPE_P2P_DEVICE: | ||
789 | /* relies on synchronize_rcu() below */ | ||
790 | rcu_assign_pointer(local->p2p_sdata, NULL); | ||
791 | /* fall through */ | ||
762 | default: | 792 | default: |
763 | flush_work(&sdata->work); | 793 | flush_work(&sdata->work); |
764 | /* | 794 | /* |
765 | * When we get here, the interface is marked down. | 795 | * When we get here, the interface is marked down. |
766 | * Call synchronize_rcu() to wait for the RX path | 796 | * Call rcu_barrier() to wait both for the RX path |
767 | * should it be using the interface and enqueuing | 797 | * should it be using the interface and enqueuing |
768 | * frames at this very time on another CPU. | 798 | * frames at this very time on another CPU, and |
799 | * for the sta free call_rcu callbacks. | ||
769 | */ | 800 | */ |
770 | synchronize_rcu(); | 801 | rcu_barrier(); |
771 | skb_queue_purge(&sdata->skb_queue); | ||
772 | 802 | ||
773 | /* | 803 | /* |
774 | * Disable beaconing here for mesh only, AP and IBSS | 804 | * free_sta_rcu() enqueues a work for the actual |
775 | * are already taken care of. | 805 | * sta cleanup, so we need to flush it while |
806 | * sdata is still valid. | ||
776 | */ | 807 | */ |
777 | if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | 808 | flush_workqueue(local->workqueue); |
778 | ieee80211_bss_info_change_notify(sdata, | 809 | |
779 | BSS_CHANGED_BEACON_ENABLED); | 810 | skb_queue_purge(&sdata->skb_queue); |
780 | 811 | ||
781 | /* | 812 | /* |
782 | * Free all remaining keys, there shouldn't be any, | 813 | * Free all remaining keys, there shouldn't be any, |
@@ -877,9 +908,8 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
877 | * Called when the netdev is removed or, by the code below, before | 908 | * Called when the netdev is removed or, by the code below, before |
878 | * the interface type changes. | 909 | * the interface type changes. |
879 | */ | 910 | */ |
880 | static void ieee80211_teardown_sdata(struct net_device *dev) | 911 | static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) |
881 | { | 912 | { |
882 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
883 | struct ieee80211_local *local = sdata->local; | 913 | struct ieee80211_local *local = sdata->local; |
884 | int flushed; | 914 | int flushed; |
885 | int i; | 915 | int i; |
@@ -900,6 +930,11 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
900 | WARN_ON(flushed); | 930 | WARN_ON(flushed); |
901 | } | 931 | } |
902 | 932 | ||
933 | static void ieee80211_uninit(struct net_device *dev) | ||
934 | { | ||
935 | ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); | ||
936 | } | ||
937 | |||
903 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, | 938 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, |
904 | struct sk_buff *skb) | 939 | struct sk_buff *skb) |
905 | { | 940 | { |
@@ -909,7 +944,7 @@ static u16 ieee80211_netdev_select_queue(struct net_device *dev, | |||
909 | static const struct net_device_ops ieee80211_dataif_ops = { | 944 | static const struct net_device_ops ieee80211_dataif_ops = { |
910 | .ndo_open = ieee80211_open, | 945 | .ndo_open = ieee80211_open, |
911 | .ndo_stop = ieee80211_stop, | 946 | .ndo_stop = ieee80211_stop, |
912 | .ndo_uninit = ieee80211_teardown_sdata, | 947 | .ndo_uninit = ieee80211_uninit, |
913 | .ndo_start_xmit = ieee80211_subif_start_xmit, | 948 | .ndo_start_xmit = ieee80211_subif_start_xmit, |
914 | .ndo_set_rx_mode = ieee80211_set_multicast_list, | 949 | .ndo_set_rx_mode = ieee80211_set_multicast_list, |
915 | .ndo_change_mtu = ieee80211_change_mtu, | 950 | .ndo_change_mtu = ieee80211_change_mtu, |
@@ -940,7 +975,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, | |||
940 | static const struct net_device_ops ieee80211_monitorif_ops = { | 975 | static const struct net_device_ops ieee80211_monitorif_ops = { |
941 | .ndo_open = ieee80211_open, | 976 | .ndo_open = ieee80211_open, |
942 | .ndo_stop = ieee80211_stop, | 977 | .ndo_stop = ieee80211_stop, |
943 | .ndo_uninit = ieee80211_teardown_sdata, | 978 | .ndo_uninit = ieee80211_uninit, |
944 | .ndo_start_xmit = ieee80211_monitor_start_xmit, | 979 | .ndo_start_xmit = ieee80211_monitor_start_xmit, |
945 | .ndo_set_rx_mode = ieee80211_set_multicast_list, | 980 | .ndo_set_rx_mode = ieee80211_set_multicast_list, |
946 | .ndo_change_mtu = ieee80211_change_mtu, | 981 | .ndo_change_mtu = ieee80211_change_mtu, |
@@ -1099,7 +1134,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1099 | /* and set some type-dependent values */ | 1134 | /* and set some type-dependent values */ |
1100 | sdata->vif.type = type; | 1135 | sdata->vif.type = type; |
1101 | sdata->vif.p2p = false; | 1136 | sdata->vif.p2p = false; |
1102 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; | ||
1103 | sdata->wdev.iftype = type; | 1137 | sdata->wdev.iftype = type; |
1104 | 1138 | ||
1105 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); | 1139 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); |
@@ -1107,8 +1141,11 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1107 | 1141 | ||
1108 | sdata->noack_map = 0; | 1142 | sdata->noack_map = 0; |
1109 | 1143 | ||
1110 | /* only monitor differs */ | 1144 | /* only monitor/p2p-device differ */ |
1111 | sdata->dev->type = ARPHRD_ETHER; | 1145 | if (sdata->dev) { |
1146 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; | ||
1147 | sdata->dev->type = ARPHRD_ETHER; | ||
1148 | } | ||
1112 | 1149 | ||
1113 | skb_queue_head_init(&sdata->skb_queue); | 1150 | skb_queue_head_init(&sdata->skb_queue); |
1114 | INIT_WORK(&sdata->work, ieee80211_iface_work); | 1151 | INIT_WORK(&sdata->work, ieee80211_iface_work); |
@@ -1146,6 +1183,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1146 | break; | 1183 | break; |
1147 | case NL80211_IFTYPE_WDS: | 1184 | case NL80211_IFTYPE_WDS: |
1148 | case NL80211_IFTYPE_AP_VLAN: | 1185 | case NL80211_IFTYPE_AP_VLAN: |
1186 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1149 | break; | 1187 | break; |
1150 | case NL80211_IFTYPE_UNSPECIFIED: | 1188 | case NL80211_IFTYPE_UNSPECIFIED: |
1151 | case NUM_NL80211_IFTYPES: | 1189 | case NUM_NL80211_IFTYPES: |
@@ -1156,18 +1194,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1156 | ieee80211_debugfs_add_netdev(sdata); | 1194 | ieee80211_debugfs_add_netdev(sdata); |
1157 | } | 1195 | } |
1158 | 1196 | ||
1159 | static void ieee80211_clean_sdata(struct ieee80211_sub_if_data *sdata) | ||
1160 | { | ||
1161 | switch (sdata->vif.type) { | ||
1162 | case NL80211_IFTYPE_MESH_POINT: | ||
1163 | mesh_path_flush_by_iface(sdata); | ||
1164 | break; | ||
1165 | |||
1166 | default: | ||
1167 | break; | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1171 | static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | 1197 | static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, |
1172 | enum nl80211_iftype type) | 1198 | enum nl80211_iftype type) |
1173 | { | 1199 | { |
@@ -1225,7 +1251,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
1225 | 1251 | ||
1226 | ieee80211_do_stop(sdata, false); | 1252 | ieee80211_do_stop(sdata, false); |
1227 | 1253 | ||
1228 | ieee80211_teardown_sdata(sdata->dev); | 1254 | ieee80211_teardown_sdata(sdata); |
1229 | 1255 | ||
1230 | ret = drv_change_interface(local, sdata, internal_type, p2p); | 1256 | ret = drv_change_interface(local, sdata, internal_type, p2p); |
1231 | if (ret) | 1257 | if (ret) |
@@ -1240,7 +1266,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
1240 | 1266 | ||
1241 | ieee80211_setup_sdata(sdata, type); | 1267 | ieee80211_setup_sdata(sdata, type); |
1242 | 1268 | ||
1243 | err = ieee80211_do_open(sdata->dev, false); | 1269 | err = ieee80211_do_open(&sdata->wdev, false); |
1244 | WARN(err, "type change: do_open returned %d", err); | 1270 | WARN(err, "type change: do_open returned %d", err); |
1245 | 1271 | ||
1246 | return ret; | 1272 | return ret; |
@@ -1267,14 +1293,14 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1267 | return ret; | 1293 | return ret; |
1268 | } else { | 1294 | } else { |
1269 | /* Purge and reset type-dependent state. */ | 1295 | /* Purge and reset type-dependent state. */ |
1270 | ieee80211_teardown_sdata(sdata->dev); | 1296 | ieee80211_teardown_sdata(sdata); |
1271 | ieee80211_setup_sdata(sdata, type); | 1297 | ieee80211_setup_sdata(sdata, type); |
1272 | } | 1298 | } |
1273 | 1299 | ||
1274 | /* reset some values that shouldn't be kept across type changes */ | 1300 | /* reset some values that shouldn't be kept across type changes */ |
1275 | sdata->vif.bss_conf.basic_rates = | 1301 | sdata->vif.bss_conf.basic_rates = |
1276 | ieee80211_mandatory_rates(sdata->local, | 1302 | ieee80211_mandatory_rates(sdata->local, |
1277 | sdata->local->hw.conf.channel->band); | 1303 | sdata->local->oper_channel->band); |
1278 | sdata->drop_unencrypted = 0; | 1304 | sdata->drop_unencrypted = 0; |
1279 | if (type == NL80211_IFTYPE_STATION) | 1305 | if (type == NL80211_IFTYPE_STATION) |
1280 | sdata->u.mgd.use_4addr = false; | 1306 | sdata->u.mgd.use_4addr = false; |
@@ -1283,8 +1309,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1283 | } | 1309 | } |
1284 | 1310 | ||
1285 | static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | 1311 | static void ieee80211_assign_perm_addr(struct ieee80211_local *local, |
1286 | struct net_device *dev, | 1312 | u8 *perm_addr, enum nl80211_iftype type) |
1287 | enum nl80211_iftype type) | ||
1288 | { | 1313 | { |
1289 | struct ieee80211_sub_if_data *sdata; | 1314 | struct ieee80211_sub_if_data *sdata; |
1290 | u64 mask, start, addr, val, inc; | 1315 | u64 mask, start, addr, val, inc; |
@@ -1293,13 +1318,12 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1293 | int i; | 1318 | int i; |
1294 | 1319 | ||
1295 | /* default ... something at least */ | 1320 | /* default ... something at least */ |
1296 | memcpy(dev->perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | 1321 | memcpy(perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); |
1297 | 1322 | ||
1298 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && | 1323 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && |
1299 | local->hw.wiphy->n_addresses <= 1) | 1324 | local->hw.wiphy->n_addresses <= 1) |
1300 | return; | 1325 | return; |
1301 | 1326 | ||
1302 | |||
1303 | mutex_lock(&local->iflist_mtx); | 1327 | mutex_lock(&local->iflist_mtx); |
1304 | 1328 | ||
1305 | switch (type) { | 1329 | switch (type) { |
@@ -1312,11 +1336,24 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1312 | list_for_each_entry(sdata, &local->interfaces, list) { | 1336 | list_for_each_entry(sdata, &local->interfaces, list) { |
1313 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 1337 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
1314 | continue; | 1338 | continue; |
1315 | memcpy(dev->perm_addr, sdata->vif.addr, ETH_ALEN); | 1339 | memcpy(perm_addr, sdata->vif.addr, ETH_ALEN); |
1316 | break; | 1340 | break; |
1317 | } | 1341 | } |
1318 | /* keep default if no AP interface present */ | 1342 | /* keep default if no AP interface present */ |
1319 | break; | 1343 | break; |
1344 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1345 | case NL80211_IFTYPE_P2P_GO: | ||
1346 | if (local->hw.flags & IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF) { | ||
1347 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1348 | if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) | ||
1349 | continue; | ||
1350 | if (!ieee80211_sdata_running(sdata)) | ||
1351 | continue; | ||
1352 | memcpy(perm_addr, sdata->vif.addr, ETH_ALEN); | ||
1353 | goto out_unlock; | ||
1354 | } | ||
1355 | } | ||
1356 | /* otherwise fall through */ | ||
1320 | default: | 1357 | default: |
1321 | /* assign a new address if possible -- try n_addresses first */ | 1358 | /* assign a new address if possible -- try n_addresses first */ |
1322 | for (i = 0; i < local->hw.wiphy->n_addresses; i++) { | 1359 | for (i = 0; i < local->hw.wiphy->n_addresses; i++) { |
@@ -1331,7 +1368,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1331 | } | 1368 | } |
1332 | 1369 | ||
1333 | if (!used) { | 1370 | if (!used) { |
1334 | memcpy(dev->perm_addr, | 1371 | memcpy(perm_addr, |
1335 | local->hw.wiphy->addresses[i].addr, | 1372 | local->hw.wiphy->addresses[i].addr, |
1336 | ETH_ALEN); | 1373 | ETH_ALEN); |
1337 | break; | 1374 | break; |
@@ -1382,7 +1419,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1382 | } | 1419 | } |
1383 | 1420 | ||
1384 | if (!used) { | 1421 | if (!used) { |
1385 | memcpy(dev->perm_addr, tmp_addr, ETH_ALEN); | 1422 | memcpy(perm_addr, tmp_addr, ETH_ALEN); |
1386 | break; | 1423 | break; |
1387 | } | 1424 | } |
1388 | addr = (start & ~mask) | (val & mask); | 1425 | addr = (start & ~mask) | (val & mask); |
@@ -1391,6 +1428,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1391 | break; | 1428 | break; |
1392 | } | 1429 | } |
1393 | 1430 | ||
1431 | out_unlock: | ||
1394 | mutex_unlock(&local->iflist_mtx); | 1432 | mutex_unlock(&local->iflist_mtx); |
1395 | } | 1433 | } |
1396 | 1434 | ||
@@ -1398,49 +1436,68 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1398 | struct wireless_dev **new_wdev, enum nl80211_iftype type, | 1436 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1399 | struct vif_params *params) | 1437 | struct vif_params *params) |
1400 | { | 1438 | { |
1401 | struct net_device *ndev; | 1439 | struct net_device *ndev = NULL; |
1402 | struct ieee80211_sub_if_data *sdata = NULL; | 1440 | struct ieee80211_sub_if_data *sdata = NULL; |
1403 | int ret, i; | 1441 | int ret, i; |
1404 | int txqs = 1; | 1442 | int txqs = 1; |
1405 | 1443 | ||
1406 | ASSERT_RTNL(); | 1444 | ASSERT_RTNL(); |
1407 | 1445 | ||
1408 | if (local->hw.queues >= IEEE80211_NUM_ACS) | 1446 | if (type == NL80211_IFTYPE_P2P_DEVICE) { |
1409 | txqs = IEEE80211_NUM_ACS; | 1447 | struct wireless_dev *wdev; |
1410 | 1448 | ||
1411 | ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, | 1449 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, |
1412 | name, ieee80211_if_setup, txqs, 1); | 1450 | GFP_KERNEL); |
1413 | if (!ndev) | 1451 | if (!sdata) |
1414 | return -ENOMEM; | 1452 | return -ENOMEM; |
1415 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); | 1453 | wdev = &sdata->wdev; |
1416 | 1454 | ||
1417 | ndev->needed_headroom = local->tx_headroom + | 1455 | sdata->dev = NULL; |
1418 | 4*6 /* four MAC addresses */ | 1456 | strlcpy(sdata->name, name, IFNAMSIZ); |
1419 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ | 1457 | ieee80211_assign_perm_addr(local, wdev->address, type); |
1420 | + 6 /* mesh */ | 1458 | memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); |
1421 | + 8 /* rfc1042/bridge tunnel */ | 1459 | } else { |
1422 | - ETH_HLEN /* ethernet hard_header_len */ | 1460 | if (local->hw.queues >= IEEE80211_NUM_ACS) |
1423 | + IEEE80211_ENCRYPT_HEADROOM; | 1461 | txqs = IEEE80211_NUM_ACS; |
1424 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | 1462 | |
1425 | 1463 | ndev = alloc_netdev_mqs(sizeof(*sdata) + | |
1426 | ret = dev_alloc_name(ndev, ndev->name); | 1464 | local->hw.vif_data_size, |
1427 | if (ret < 0) | 1465 | name, ieee80211_if_setup, txqs, 1); |
1428 | goto fail; | 1466 | if (!ndev) |
1429 | 1467 | return -ENOMEM; | |
1430 | ieee80211_assign_perm_addr(local, ndev, type); | 1468 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); |
1431 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); | 1469 | |
1432 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | 1470 | ndev->needed_headroom = local->tx_headroom + |
1433 | 1471 | 4*6 /* four MAC addresses */ | |
1434 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 1472 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ |
1435 | sdata = netdev_priv(ndev); | 1473 | + 6 /* mesh */ |
1436 | ndev->ieee80211_ptr = &sdata->wdev; | 1474 | + 8 /* rfc1042/bridge tunnel */ |
1437 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | 1475 | - ETH_HLEN /* ethernet hard_header_len */ |
1438 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | 1476 | + IEEE80211_ENCRYPT_HEADROOM; |
1477 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | ||
1478 | |||
1479 | ret = dev_alloc_name(ndev, ndev->name); | ||
1480 | if (ret < 0) { | ||
1481 | free_netdev(ndev); | ||
1482 | return ret; | ||
1483 | } | ||
1484 | |||
1485 | ieee80211_assign_perm_addr(local, ndev->perm_addr, type); | ||
1486 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); | ||
1487 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | ||
1488 | |||
1489 | /* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */ | ||
1490 | sdata = netdev_priv(ndev); | ||
1491 | ndev->ieee80211_ptr = &sdata->wdev; | ||
1492 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | ||
1493 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | ||
1494 | |||
1495 | sdata->dev = ndev; | ||
1496 | } | ||
1439 | 1497 | ||
1440 | /* initialise type-independent data */ | 1498 | /* initialise type-independent data */ |
1441 | sdata->wdev.wiphy = local->hw.wiphy; | 1499 | sdata->wdev.wiphy = local->hw.wiphy; |
1442 | sdata->local = local; | 1500 | sdata->local = local; |
1443 | sdata->dev = ndev; | ||
1444 | #ifdef CONFIG_INET | 1501 | #ifdef CONFIG_INET |
1445 | sdata->arp_filter_state = true; | 1502 | sdata->arp_filter_state = true; |
1446 | #endif | 1503 | #endif |
@@ -1469,17 +1526,21 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1469 | /* setup type-dependent data */ | 1526 | /* setup type-dependent data */ |
1470 | ieee80211_setup_sdata(sdata, type); | 1527 | ieee80211_setup_sdata(sdata, type); |
1471 | 1528 | ||
1472 | if (params) { | 1529 | if (ndev) { |
1473 | ndev->ieee80211_ptr->use_4addr = params->use_4addr; | 1530 | if (params) { |
1474 | if (type == NL80211_IFTYPE_STATION) | 1531 | ndev->ieee80211_ptr->use_4addr = params->use_4addr; |
1475 | sdata->u.mgd.use_4addr = params->use_4addr; | 1532 | if (type == NL80211_IFTYPE_STATION) |
1476 | } | 1533 | sdata->u.mgd.use_4addr = params->use_4addr; |
1534 | } | ||
1477 | 1535 | ||
1478 | ndev->features |= local->hw.netdev_features; | 1536 | ndev->features |= local->hw.netdev_features; |
1479 | 1537 | ||
1480 | ret = register_netdevice(ndev); | 1538 | ret = register_netdevice(ndev); |
1481 | if (ret) | 1539 | if (ret) { |
1482 | goto fail; | 1540 | free_netdev(ndev); |
1541 | return ret; | ||
1542 | } | ||
1543 | } | ||
1483 | 1544 | ||
1484 | mutex_lock(&local->iflist_mtx); | 1545 | mutex_lock(&local->iflist_mtx); |
1485 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 1546 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
@@ -1489,10 +1550,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1489 | *new_wdev = &sdata->wdev; | 1550 | *new_wdev = &sdata->wdev; |
1490 | 1551 | ||
1491 | return 0; | 1552 | return 0; |
1492 | |||
1493 | fail: | ||
1494 | free_netdev(ndev); | ||
1495 | return ret; | ||
1496 | } | 1553 | } |
1497 | 1554 | ||
1498 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | 1555 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) |
@@ -1503,11 +1560,22 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | |||
1503 | list_del_rcu(&sdata->list); | 1560 | list_del_rcu(&sdata->list); |
1504 | mutex_unlock(&sdata->local->iflist_mtx); | 1561 | mutex_unlock(&sdata->local->iflist_mtx); |
1505 | 1562 | ||
1506 | /* clean up type-dependent data */ | ||
1507 | ieee80211_clean_sdata(sdata); | ||
1508 | |||
1509 | synchronize_rcu(); | 1563 | synchronize_rcu(); |
1510 | unregister_netdevice(sdata->dev); | 1564 | |
1565 | if (sdata->dev) { | ||
1566 | unregister_netdevice(sdata->dev); | ||
1567 | } else { | ||
1568 | cfg80211_unregister_wdev(&sdata->wdev); | ||
1569 | kfree(sdata); | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata) | ||
1574 | { | ||
1575 | if (WARN_ON_ONCE(!test_bit(SDATA_STATE_RUNNING, &sdata->state))) | ||
1576 | return; | ||
1577 | ieee80211_do_stop(sdata, true); | ||
1578 | ieee80211_teardown_sdata(sdata); | ||
1511 | } | 1579 | } |
1512 | 1580 | ||
1513 | /* | 1581 | /* |
@@ -1518,6 +1586,7 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1518 | { | 1586 | { |
1519 | struct ieee80211_sub_if_data *sdata, *tmp; | 1587 | struct ieee80211_sub_if_data *sdata, *tmp; |
1520 | LIST_HEAD(unreg_list); | 1588 | LIST_HEAD(unreg_list); |
1589 | LIST_HEAD(wdev_list); | ||
1521 | 1590 | ||
1522 | ASSERT_RTNL(); | 1591 | ASSERT_RTNL(); |
1523 | 1592 | ||
@@ -1525,13 +1594,20 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1525 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | 1594 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { |
1526 | list_del(&sdata->list); | 1595 | list_del(&sdata->list); |
1527 | 1596 | ||
1528 | ieee80211_clean_sdata(sdata); | 1597 | if (sdata->dev) |
1529 | 1598 | unregister_netdevice_queue(sdata->dev, &unreg_list); | |
1530 | unregister_netdevice_queue(sdata->dev, &unreg_list); | 1599 | else |
1600 | list_add(&sdata->list, &wdev_list); | ||
1531 | } | 1601 | } |
1532 | mutex_unlock(&local->iflist_mtx); | 1602 | mutex_unlock(&local->iflist_mtx); |
1533 | unregister_netdevice_many(&unreg_list); | 1603 | unregister_netdevice_many(&unreg_list); |
1534 | list_del(&unreg_list); | 1604 | list_del(&unreg_list); |
1605 | |||
1606 | list_for_each_entry_safe(sdata, tmp, &wdev_list, list) { | ||
1607 | list_del(&sdata->list); | ||
1608 | cfg80211_unregister_wdev(&sdata->wdev); | ||
1609 | kfree(sdata); | ||
1610 | } | ||
1535 | } | 1611 | } |
1536 | 1612 | ||
1537 | static int netdev_notify(struct notifier_block *nb, | 1613 | static int netdev_notify(struct notifier_block *nb, |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 7ae678ba5d67..d27e61aaa71b 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -402,7 +402,7 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
402 | * Synchronize so the TX path can no longer be using | 402 | * Synchronize so the TX path can no longer be using |
403 | * this key before we free/remove it. | 403 | * this key before we free/remove it. |
404 | */ | 404 | */ |
405 | synchronize_rcu(); | 405 | synchronize_net(); |
406 | 406 | ||
407 | if (key->local) | 407 | if (key->local) |
408 | ieee80211_key_disable_hw_accel(key); | 408 | ieee80211_key_disable_hw_accel(key); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c26e231c733a..c80c4490351c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -150,13 +150,11 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
150 | 150 | ||
151 | 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) || | 152 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || |
153 | test_bit(SCAN_HW_SCANNING, &local->scanning)) | 153 | test_bit(SCAN_HW_SCANNING, &local->scanning) || |
154 | !local->ap_power_level) | ||
154 | power = chan->max_power; | 155 | power = chan->max_power; |
155 | else | 156 | else |
156 | power = local->power_constr_level ? | 157 | power = min(chan->max_power, local->ap_power_level); |
157 | min(chan->max_power, | ||
158 | (chan->max_reg_power - local->power_constr_level)) : | ||
159 | chan->max_power; | ||
160 | 158 | ||
161 | if (local->user_power_level >= 0) | 159 | if (local->user_power_level >= 0) |
162 | power = min(power, local->user_power_level); | 160 | power = min(power, local->user_power_level); |
@@ -207,6 +205,10 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
207 | sdata->vif.bss_conf.bssid = NULL; | 205 | sdata->vif.bss_conf.bssid = NULL; |
208 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 206 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
209 | sdata->vif.bss_conf.bssid = zero; | 207 | sdata->vif.bss_conf.bssid = zero; |
208 | } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { | ||
209 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | ||
210 | WARN_ONCE(changed & ~(BSS_CHANGED_IDLE), | ||
211 | "P2P Device BSS changed %#x", changed); | ||
210 | } else { | 212 | } else { |
211 | WARN_ON(1); | 213 | WARN_ON(1); |
212 | return; | 214 | return; |
@@ -362,9 +364,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work) | |||
362 | struct ieee80211_local *local = | 364 | struct ieee80211_local *local = |
363 | container_of(work, struct ieee80211_local, recalc_smps); | 365 | container_of(work, struct ieee80211_local, recalc_smps); |
364 | 366 | ||
365 | mutex_lock(&local->iflist_mtx); | ||
366 | ieee80211_recalc_smps(local); | 367 | ieee80211_recalc_smps(local); |
367 | mutex_unlock(&local->iflist_mtx); | ||
368 | } | 368 | } |
369 | 369 | ||
370 | #ifdef CONFIG_INET | 370 | #ifdef CONFIG_INET |
@@ -514,6 +514,11 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
514 | BIT(IEEE80211_STYPE_AUTH >> 4) | | 514 | BIT(IEEE80211_STYPE_AUTH >> 4) | |
515 | BIT(IEEE80211_STYPE_DEAUTH >> 4), | 515 | BIT(IEEE80211_STYPE_DEAUTH >> 4), |
516 | }, | 516 | }, |
517 | [NL80211_IFTYPE_P2P_DEVICE] = { | ||
518 | .tx = 0xffff, | ||
519 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
520 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
521 | }, | ||
517 | }; | 522 | }; |
518 | 523 | ||
519 | static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { | 524 | static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { |
@@ -536,6 +541,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
536 | int priv_size, i; | 541 | int priv_size, i; |
537 | struct wiphy *wiphy; | 542 | struct wiphy *wiphy; |
538 | 543 | ||
544 | if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config || | ||
545 | !ops->add_interface || !ops->remove_interface || | ||
546 | !ops->configure_filter)) | ||
547 | return NULL; | ||
548 | |||
539 | if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove))) | 549 | if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove))) |
540 | return NULL; | 550 | return NULL; |
541 | 551 | ||
@@ -588,13 +598,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
588 | 598 | ||
589 | local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); | 599 | local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); |
590 | 600 | ||
591 | BUG_ON(!ops->tx); | ||
592 | BUG_ON(!ops->start); | ||
593 | BUG_ON(!ops->stop); | ||
594 | BUG_ON(!ops->config); | ||
595 | BUG_ON(!ops->add_interface); | ||
596 | BUG_ON(!ops->remove_interface); | ||
597 | BUG_ON(!ops->configure_filter); | ||
598 | local->ops = ops; | 601 | local->ops = ops; |
599 | 602 | ||
600 | /* set up some defaults */ | 603 | /* set up some defaults */ |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 85572353a7e3..ff0296c7bab8 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -109,11 +109,11 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
109 | 109 | ||
110 | /* Disallow HT40+/- mismatch */ | 110 | /* Disallow HT40+/- mismatch */ |
111 | if (ie->ht_operation && | 111 | if (ie->ht_operation && |
112 | (local->_oper_channel_type == NL80211_CHAN_HT40MINUS || | 112 | (sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS || |
113 | local->_oper_channel_type == NL80211_CHAN_HT40PLUS) && | 113 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) && |
114 | (sta_channel_type == NL80211_CHAN_HT40MINUS || | 114 | (sta_channel_type == NL80211_CHAN_HT40MINUS || |
115 | sta_channel_type == NL80211_CHAN_HT40PLUS) && | 115 | sta_channel_type == NL80211_CHAN_HT40PLUS) && |
116 | local->_oper_channel_type != sta_channel_type) | 116 | sdata->vif.bss_conf.channel_type != sta_channel_type) |
117 | goto mismatch; | 117 | goto mismatch; |
118 | 118 | ||
119 | return true; | 119 | return true; |
@@ -136,10 +136,13 @@ bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) | |||
136 | * mesh_accept_plinks_update - update accepting_plink in local mesh beacons | 136 | * mesh_accept_plinks_update - update accepting_plink in local mesh beacons |
137 | * | 137 | * |
138 | * @sdata: mesh interface in which mesh beacons are going to be updated | 138 | * @sdata: mesh interface in which mesh beacons are going to be updated |
139 | * | ||
140 | * Returns: beacon changed flag if the beacon content changed. | ||
139 | */ | 141 | */ |
140 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | 142 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) |
141 | { | 143 | { |
142 | bool free_plinks; | 144 | bool free_plinks; |
145 | u32 changed = 0; | ||
143 | 146 | ||
144 | /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, | 147 | /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, |
145 | * the mesh interface might be able to establish plinks with peers that | 148 | * the mesh interface might be able to establish plinks with peers that |
@@ -149,8 +152,12 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
149 | */ | 152 | */ |
150 | free_plinks = mesh_plink_availables(sdata); | 153 | free_plinks = mesh_plink_availables(sdata); |
151 | 154 | ||
152 | if (free_plinks != sdata->u.mesh.accepting_plinks) | 155 | if (free_plinks != sdata->u.mesh.accepting_plinks) { |
153 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); | 156 | sdata->u.mesh.accepting_plinks = free_plinks; |
157 | changed = BSS_CHANGED_BEACON; | ||
158 | } | ||
159 | |||
160 | return changed; | ||
154 | } | 161 | } |
155 | 162 | ||
156 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 163 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
@@ -262,7 +269,6 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
262 | neighbors = (neighbors > 15) ? 15 : neighbors; | 269 | neighbors = (neighbors > 15) ? 15 : neighbors; |
263 | *pos++ = neighbors << 1; | 270 | *pos++ = neighbors << 1; |
264 | /* Mesh capability */ | 271 | /* Mesh capability */ |
265 | ifmsh->accepting_plinks = mesh_plink_availables(sdata); | ||
266 | *pos = MESHCONF_CAPAB_FORWARDING; | 272 | *pos = MESHCONF_CAPAB_FORWARDING; |
267 | *pos |= ifmsh->accepting_plinks ? | 273 | *pos |= ifmsh->accepting_plinks ? |
268 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 274 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
@@ -349,17 +355,18 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
349 | { | 355 | { |
350 | struct ieee80211_local *local = sdata->local; | 356 | struct ieee80211_local *local = sdata->local; |
351 | struct ieee80211_supported_band *sband; | 357 | struct ieee80211_supported_band *sband; |
358 | struct ieee80211_channel *chan = local->oper_channel; | ||
352 | u8 *pos; | 359 | u8 *pos; |
353 | 360 | ||
354 | if (skb_tailroom(skb) < 3) | 361 | if (skb_tailroom(skb) < 3) |
355 | return -ENOMEM; | 362 | return -ENOMEM; |
356 | 363 | ||
357 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 364 | sband = local->hw.wiphy->bands[chan->band]; |
358 | if (sband->band == IEEE80211_BAND_2GHZ) { | 365 | if (sband->band == IEEE80211_BAND_2GHZ) { |
359 | pos = skb_put(skb, 2 + 1); | 366 | pos = skb_put(skb, 2 + 1); |
360 | *pos++ = WLAN_EID_DS_PARAMS; | 367 | *pos++ = WLAN_EID_DS_PARAMS; |
361 | *pos++ = 1; | 368 | *pos++ = 1; |
362 | *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq); | 369 | *pos++ = ieee80211_frequency_to_channel(chan->center_freq); |
363 | } | 370 | } |
364 | 371 | ||
365 | return 0; | 372 | return 0; |
@@ -374,7 +381,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, | |||
374 | 381 | ||
375 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 382 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
376 | if (!sband->ht_cap.ht_supported || | 383 | if (!sband->ht_cap.ht_supported || |
377 | local->_oper_channel_type == NL80211_CHAN_NO_HT) | 384 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) |
378 | return 0; | 385 | return 0; |
379 | 386 | ||
380 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) | 387 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) |
@@ -391,7 +398,8 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
391 | { | 398 | { |
392 | struct ieee80211_local *local = sdata->local; | 399 | struct ieee80211_local *local = sdata->local; |
393 | struct ieee80211_channel *channel = local->oper_channel; | 400 | struct ieee80211_channel *channel = local->oper_channel; |
394 | enum nl80211_channel_type channel_type = local->_oper_channel_type; | 401 | enum nl80211_channel_type channel_type = |
402 | sdata->vif.bss_conf.channel_type; | ||
395 | struct ieee80211_supported_band *sband = | 403 | struct ieee80211_supported_band *sband = |
396 | local->hw.wiphy->bands[channel->band]; | 404 | local->hw.wiphy->bands[channel->band]; |
397 | struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; | 405 | struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; |
@@ -521,14 +529,13 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | |||
521 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | 529 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, |
522 | struct ieee80211_if_mesh *ifmsh) | 530 | struct ieee80211_if_mesh *ifmsh) |
523 | { | 531 | { |
524 | bool free_plinks; | 532 | u32 changed; |
525 | 533 | ||
526 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 534 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
527 | mesh_path_expire(sdata); | 535 | mesh_path_expire(sdata); |
528 | 536 | ||
529 | free_plinks = mesh_plink_availables(sdata); | 537 | changed = mesh_accept_plinks_update(sdata); |
530 | if (free_plinks != sdata->u.mesh.accepting_plinks) | 538 | ieee80211_bss_info_change_notify(sdata, changed); |
531 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | ||
532 | 539 | ||
533 | mod_timer(&ifmsh->housekeeping_timer, | 540 | mod_timer(&ifmsh->housekeeping_timer, |
534 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | 541 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); |
@@ -603,12 +610,14 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
603 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; | 610 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; |
604 | sdata->vif.bss_conf.basic_rates = | 611 | sdata->vif.bss_conf.basic_rates = |
605 | ieee80211_mandatory_rates(sdata->local, | 612 | ieee80211_mandatory_rates(sdata->local, |
606 | sdata->local->hw.conf.channel->band); | 613 | sdata->local->oper_channel->band); |
607 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | | 614 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
608 | BSS_CHANGED_BEACON_ENABLED | | 615 | BSS_CHANGED_BEACON_ENABLED | |
609 | BSS_CHANGED_HT | | 616 | BSS_CHANGED_HT | |
610 | BSS_CHANGED_BASIC_RATES | | 617 | BSS_CHANGED_BASIC_RATES | |
611 | BSS_CHANGED_BEACON_INT); | 618 | BSS_CHANGED_BEACON_INT); |
619 | |||
620 | netif_carrier_on(sdata->dev); | ||
612 | } | 621 | } |
613 | 622 | ||
614 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 623 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
@@ -616,9 +625,15 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
616 | struct ieee80211_local *local = sdata->local; | 625 | struct ieee80211_local *local = sdata->local; |
617 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 626 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
618 | 627 | ||
628 | netif_carrier_off(sdata->dev); | ||
629 | |||
630 | /* stop the beacon */ | ||
619 | ifmsh->mesh_id_len = 0; | 631 | ifmsh->mesh_id_len = 0; |
620 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 632 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
621 | sta_info_flush(local, NULL); | 633 | |
634 | /* flush STAs and mpaths on this iface */ | ||
635 | sta_info_flush(sdata->local, sdata); | ||
636 | mesh_path_flush_by_iface(sdata); | ||
622 | 637 | ||
623 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | 638 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); |
624 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); | 639 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index faaa39bcfd10..25d0f17dec71 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -215,6 +215,9 @@ struct mesh_rmc { | |||
215 | /* Maximum number of paths per interface */ | 215 | /* Maximum number of paths per interface */ |
216 | #define MESH_MAX_MPATHS 1024 | 216 | #define MESH_MAX_MPATHS 1024 |
217 | 217 | ||
218 | /* Number of frames buffered per destination for unresolved destinations */ | ||
219 | #define MESH_FRAME_QUEUE_LEN 10 | ||
220 | |||
218 | /* Public interfaces */ | 221 | /* Public interfaces */ |
219 | /* Various */ | 222 | /* Various */ |
220 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 223 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
@@ -282,7 +285,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, | |||
282 | u8 *hw_addr, | 285 | u8 *hw_addr, |
283 | struct ieee802_11_elems *ie); | 286 | struct ieee802_11_elems *ie); |
284 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); | 287 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
285 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 288 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
286 | void mesh_plink_broken(struct sta_info *sta); | 289 | void mesh_plink_broken(struct sta_info *sta); |
287 | void mesh_plink_deactivate(struct sta_info *sta); | 290 | void mesh_plink_deactivate(struct sta_info *sta); |
288 | int mesh_plink_open(struct sta_info *sta); | 291 | int mesh_plink_open(struct sta_info *sta); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 494bc39f61a4..47aeee2d8db1 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #define MAX_METRIC 0xffffffff | 17 | #define MAX_METRIC 0xffffffff |
18 | #define ARITH_SHIFT 8 | 18 | #define ARITH_SHIFT 8 |
19 | 19 | ||
20 | /* Number of frames buffered per destination for unresolved destinations */ | ||
21 | #define MESH_FRAME_QUEUE_LEN 10 | ||
22 | #define MAX_PREQ_QUEUE_LEN 64 | 20 | #define MAX_PREQ_QUEUE_LEN 64 |
23 | 21 | ||
24 | /* Destination only */ | 22 | /* Destination only */ |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 075bc535c601..aa749818860e 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -203,23 +203,17 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | |||
203 | { | 203 | { |
204 | struct sk_buff *skb; | 204 | struct sk_buff *skb; |
205 | struct ieee80211_hdr *hdr; | 205 | struct ieee80211_hdr *hdr; |
206 | struct sk_buff_head tmpq; | ||
207 | unsigned long flags; | 206 | unsigned long flags; |
208 | 207 | ||
209 | rcu_assign_pointer(mpath->next_hop, sta); | 208 | rcu_assign_pointer(mpath->next_hop, sta); |
210 | 209 | ||
211 | __skb_queue_head_init(&tmpq); | ||
212 | |||
213 | spin_lock_irqsave(&mpath->frame_queue.lock, flags); | 210 | spin_lock_irqsave(&mpath->frame_queue.lock, flags); |
214 | 211 | skb_queue_walk(&mpath->frame_queue, skb) { | |
215 | while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { | ||
216 | hdr = (struct ieee80211_hdr *) skb->data; | 212 | hdr = (struct ieee80211_hdr *) skb->data; |
217 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); | 213 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); |
218 | memcpy(hdr->addr2, mpath->sdata->vif.addr, ETH_ALEN); | 214 | memcpy(hdr->addr2, mpath->sdata->vif.addr, ETH_ALEN); |
219 | __skb_queue_tail(&tmpq, skb); | ||
220 | } | 215 | } |
221 | 216 | ||
222 | skb_queue_splice(&tmpq, &mpath->frame_queue); | ||
223 | spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); | 217 | spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); |
224 | } | 218 | } |
225 | 219 | ||
@@ -285,40 +279,42 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, | |||
285 | struct mesh_path *from_mpath, | 279 | struct mesh_path *from_mpath, |
286 | bool copy) | 280 | bool copy) |
287 | { | 281 | { |
288 | struct sk_buff *skb, *cp_skb = NULL; | 282 | struct sk_buff *skb, *fskb, *tmp; |
289 | struct sk_buff_head gateq, failq; | 283 | struct sk_buff_head failq; |
290 | unsigned long flags; | 284 | unsigned long flags; |
291 | int num_skbs; | ||
292 | 285 | ||
293 | BUG_ON(gate_mpath == from_mpath); | 286 | BUG_ON(gate_mpath == from_mpath); |
294 | BUG_ON(!gate_mpath->next_hop); | 287 | BUG_ON(!gate_mpath->next_hop); |
295 | 288 | ||
296 | __skb_queue_head_init(&gateq); | ||
297 | __skb_queue_head_init(&failq); | 289 | __skb_queue_head_init(&failq); |
298 | 290 | ||
299 | spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); | 291 | spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); |
300 | skb_queue_splice_init(&from_mpath->frame_queue, &failq); | 292 | skb_queue_splice_init(&from_mpath->frame_queue, &failq); |
301 | spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); | 293 | spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); |
302 | 294 | ||
303 | num_skbs = skb_queue_len(&failq); | 295 | skb_queue_walk_safe(&failq, fskb, tmp) { |
304 | 296 | if (skb_queue_len(&gate_mpath->frame_queue) >= | |
305 | while (num_skbs--) { | 297 | MESH_FRAME_QUEUE_LEN) { |
306 | skb = __skb_dequeue(&failq); | 298 | mpath_dbg(gate_mpath->sdata, "mpath queue full!\n"); |
307 | if (copy) { | 299 | break; |
308 | cp_skb = skb_copy(skb, GFP_ATOMIC); | ||
309 | if (cp_skb) | ||
310 | __skb_queue_tail(&failq, cp_skb); | ||
311 | } | 300 | } |
312 | 301 | ||
302 | skb = skb_copy(fskb, GFP_ATOMIC); | ||
303 | if (WARN_ON(!skb)) | ||
304 | break; | ||
305 | |||
313 | prepare_for_gate(skb, gate_mpath->dst, gate_mpath); | 306 | prepare_for_gate(skb, gate_mpath->dst, gate_mpath); |
314 | __skb_queue_tail(&gateq, skb); | 307 | skb_queue_tail(&gate_mpath->frame_queue, skb); |
308 | |||
309 | if (copy) | ||
310 | continue; | ||
311 | |||
312 | __skb_unlink(fskb, &failq); | ||
313 | kfree_skb(fskb); | ||
315 | } | 314 | } |
316 | 315 | ||
317 | spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags); | ||
318 | skb_queue_splice(&gateq, &gate_mpath->frame_queue); | ||
319 | mpath_dbg(gate_mpath->sdata, "Mpath queue for gate %pM has %d frames\n", | 316 | mpath_dbg(gate_mpath->sdata, "Mpath queue for gate %pM has %d frames\n", |
320 | gate_mpath->dst, skb_queue_len(&gate_mpath->frame_queue)); | 317 | gate_mpath->dst, skb_queue_len(&gate_mpath->frame_queue)); |
321 | spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags); | ||
322 | 318 | ||
323 | if (!copy) | 319 | if (!copy) |
324 | return; | 320 | return; |
@@ -531,7 +527,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
531 | 527 | ||
532 | read_lock_bh(&pathtbl_resize_lock); | 528 | read_lock_bh(&pathtbl_resize_lock); |
533 | memcpy(new_mpath->dst, dst, ETH_ALEN); | 529 | memcpy(new_mpath->dst, dst, ETH_ALEN); |
534 | memset(new_mpath->rann_snd_addr, 0xff, ETH_ALEN); | 530 | eth_broadcast_addr(new_mpath->rann_snd_addr); |
535 | new_mpath->is_root = false; | 531 | new_mpath->is_root = false; |
536 | new_mpath->sdata = sdata; | 532 | new_mpath->sdata = sdata; |
537 | new_mpath->flags = 0; | 533 | new_mpath->flags = 0; |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index af671b984df3..3ab34d816897 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -48,17 +48,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
48 | u8 *da, __le16 llid, __le16 plid, __le16 reason); | 48 | u8 *da, __le16 llid, __le16 plid, __le16 reason); |
49 | 49 | ||
50 | static inline | 50 | static inline |
51 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | 51 | u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) |
52 | { | 52 | { |
53 | atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); | 53 | atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); |
54 | mesh_accept_plinks_update(sdata); | 54 | return mesh_accept_plinks_update(sdata); |
55 | } | 55 | } |
56 | 56 | ||
57 | static inline | 57 | static inline |
58 | void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | 58 | u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) |
59 | { | 59 | { |
60 | atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); | 60 | atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); |
61 | mesh_accept_plinks_update(sdata); | 61 | return mesh_accept_plinks_update(sdata); |
62 | } | 62 | } |
63 | 63 | ||
64 | /** | 64 | /** |
@@ -117,7 +117,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
117 | u16 ht_opmode; | 117 | u16 ht_opmode; |
118 | bool non_ht_sta = false, ht20_sta = false; | 118 | bool non_ht_sta = false, ht20_sta = false; |
119 | 119 | ||
120 | if (local->_oper_channel_type == NL80211_CHAN_NO_HT) | 120 | if (sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) |
121 | return 0; | 121 | return 0; |
122 | 122 | ||
123 | rcu_read_lock(); | 123 | rcu_read_lock(); |
@@ -147,7 +147,8 @@ out: | |||
147 | 147 | ||
148 | if (non_ht_sta) | 148 | if (non_ht_sta) |
149 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; | 149 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; |
150 | else if (ht20_sta && local->_oper_channel_type > NL80211_CHAN_HT20) | 150 | else if (ht20_sta && |
151 | sdata->vif.bss_conf.channel_type > NL80211_CHAN_HT20) | ||
151 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; | 152 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; |
152 | else | 153 | else |
153 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 154 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
@@ -170,22 +171,21 @@ out: | |||
170 | * @sta: mesh peer link to deactivate | 171 | * @sta: mesh peer link to deactivate |
171 | * | 172 | * |
172 | * All mesh paths with this peer as next hop will be flushed | 173 | * All mesh paths with this peer as next hop will be flushed |
174 | * Returns beacon changed flag if the beacon content changed. | ||
173 | * | 175 | * |
174 | * Locking: the caller must hold sta->lock | 176 | * Locking: the caller must hold sta->lock |
175 | */ | 177 | */ |
176 | static bool __mesh_plink_deactivate(struct sta_info *sta) | 178 | static u32 __mesh_plink_deactivate(struct sta_info *sta) |
177 | { | 179 | { |
178 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 180 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
179 | bool deactivated = false; | 181 | u32 changed = 0; |
180 | 182 | ||
181 | if (sta->plink_state == NL80211_PLINK_ESTAB) { | 183 | if (sta->plink_state == NL80211_PLINK_ESTAB) |
182 | mesh_plink_dec_estab_count(sdata); | 184 | changed = mesh_plink_dec_estab_count(sdata); |
183 | deactivated = true; | ||
184 | } | ||
185 | sta->plink_state = NL80211_PLINK_BLOCKED; | 185 | sta->plink_state = NL80211_PLINK_BLOCKED; |
186 | mesh_path_flush_by_nexthop(sta); | 186 | mesh_path_flush_by_nexthop(sta); |
187 | 187 | ||
188 | return deactivated; | 188 | return changed; |
189 | } | 189 | } |
190 | 190 | ||
191 | /** | 191 | /** |
@@ -198,18 +198,17 @@ static bool __mesh_plink_deactivate(struct sta_info *sta) | |||
198 | void mesh_plink_deactivate(struct sta_info *sta) | 198 | void mesh_plink_deactivate(struct sta_info *sta) |
199 | { | 199 | { |
200 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 200 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
201 | bool deactivated; | 201 | u32 changed; |
202 | 202 | ||
203 | spin_lock_bh(&sta->lock); | 203 | spin_lock_bh(&sta->lock); |
204 | deactivated = __mesh_plink_deactivate(sta); | 204 | changed = __mesh_plink_deactivate(sta); |
205 | sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); | 205 | sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); |
206 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 206 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
207 | sta->sta.addr, sta->llid, sta->plid, | 207 | sta->sta.addr, sta->llid, sta->plid, |
208 | sta->reason); | 208 | sta->reason); |
209 | spin_unlock_bh(&sta->lock); | 209 | spin_unlock_bh(&sta->lock); |
210 | 210 | ||
211 | if (deactivated) | 211 | ieee80211_bss_info_change_notify(sdata, changed); |
212 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | ||
213 | } | 212 | } |
214 | 213 | ||
215 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 214 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
@@ -217,12 +216,14 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
217 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { | 216 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { |
218 | struct ieee80211_local *local = sdata->local; | 217 | struct ieee80211_local *local = sdata->local; |
219 | struct sk_buff *skb; | 218 | struct sk_buff *skb; |
219 | struct ieee80211_tx_info *info; | ||
220 | struct ieee80211_mgmt *mgmt; | 220 | struct ieee80211_mgmt *mgmt; |
221 | bool include_plid = false; | 221 | bool include_plid = false; |
222 | u16 peering_proto = 0; | 222 | u16 peering_proto = 0; |
223 | u8 *pos, ie_len = 4; | 223 | u8 *pos, ie_len = 4; |
224 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + | 224 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + |
225 | sizeof(mgmt->u.action.u.self_prot); | 225 | sizeof(mgmt->u.action.u.self_prot); |
226 | int err = -ENOMEM; | ||
226 | 227 | ||
227 | skb = dev_alloc_skb(local->tx_headroom + | 228 | skb = dev_alloc_skb(local->tx_headroom + |
228 | hdr_len + | 229 | hdr_len + |
@@ -238,6 +239,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
238 | sdata->u.mesh.ie_len); | 239 | sdata->u.mesh.ie_len); |
239 | if (!skb) | 240 | if (!skb) |
240 | return -1; | 241 | return -1; |
242 | info = IEEE80211_SKB_CB(skb); | ||
241 | skb_reserve(skb, local->tx_headroom); | 243 | skb_reserve(skb, local->tx_headroom); |
242 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); | 244 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
243 | memset(mgmt, 0, hdr_len); | 245 | memset(mgmt, 0, hdr_len); |
@@ -258,15 +260,18 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
258 | pos = skb_put(skb, 2); | 260 | pos = skb_put(skb, 2); |
259 | memcpy(pos + 2, &plid, 2); | 261 | memcpy(pos + 2, &plid, 2); |
260 | } | 262 | } |
261 | if (ieee80211_add_srates_ie(sdata, skb, true) || | 263 | if (ieee80211_add_srates_ie(sdata, skb, true, |
262 | ieee80211_add_ext_srates_ie(sdata, skb, true) || | 264 | local->oper_channel->band) || |
265 | ieee80211_add_ext_srates_ie(sdata, skb, true, | ||
266 | local->oper_channel->band) || | ||
263 | mesh_add_rsn_ie(skb, sdata) || | 267 | mesh_add_rsn_ie(skb, sdata) || |
264 | mesh_add_meshid_ie(skb, sdata) || | 268 | mesh_add_meshid_ie(skb, sdata) || |
265 | mesh_add_meshconf_ie(skb, sdata)) | 269 | mesh_add_meshconf_ie(skb, sdata)) |
266 | return -1; | 270 | goto free; |
267 | } else { /* WLAN_SP_MESH_PEERING_CLOSE */ | 271 | } else { /* WLAN_SP_MESH_PEERING_CLOSE */ |
272 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
268 | if (mesh_add_meshid_ie(skb, sdata)) | 273 | if (mesh_add_meshid_ie(skb, sdata)) |
269 | return -1; | 274 | goto free; |
270 | } | 275 | } |
271 | 276 | ||
272 | /* Add Mesh Peering Management element */ | 277 | /* Add Mesh Peering Management element */ |
@@ -285,11 +290,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
285 | ie_len += 2; /* reason code */ | 290 | ie_len += 2; /* reason code */ |
286 | break; | 291 | break; |
287 | default: | 292 | default: |
288 | return -EINVAL; | 293 | err = -EINVAL; |
294 | goto free; | ||
289 | } | 295 | } |
290 | 296 | ||
291 | if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) | 297 | if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) |
292 | return -ENOMEM; | 298 | goto free; |
293 | 299 | ||
294 | pos = skb_put(skb, 2 + ie_len); | 300 | pos = skb_put(skb, 2 + ie_len); |
295 | *pos++ = WLAN_EID_PEER_MGMT; | 301 | *pos++ = WLAN_EID_PEER_MGMT; |
@@ -310,14 +316,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
310 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { | 316 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { |
311 | if (mesh_add_ht_cap_ie(skb, sdata) || | 317 | if (mesh_add_ht_cap_ie(skb, sdata) || |
312 | mesh_add_ht_oper_ie(skb, sdata)) | 318 | mesh_add_ht_oper_ie(skb, sdata)) |
313 | return -1; | 319 | goto free; |
314 | } | 320 | } |
315 | 321 | ||
316 | if (mesh_add_vendor_ies(skb, sdata)) | 322 | if (mesh_add_vendor_ies(skb, sdata)) |
317 | return -1; | 323 | goto free; |
318 | 324 | ||
319 | ieee80211_tx_skb(sdata, skb); | 325 | ieee80211_tx_skb(sdata, skb); |
320 | return 0; | 326 | return 0; |
327 | free: | ||
328 | kfree_skb(skb); | ||
329 | return err; | ||
321 | } | 330 | } |
322 | 331 | ||
323 | /** | 332 | /** |
@@ -362,9 +371,14 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | |||
362 | 371 | ||
363 | spin_lock_bh(&sta->lock); | 372 | spin_lock_bh(&sta->lock); |
364 | sta->last_rx = jiffies; | 373 | sta->last_rx = jiffies; |
374 | if (sta->plink_state == NL80211_PLINK_ESTAB) { | ||
375 | spin_unlock_bh(&sta->lock); | ||
376 | return sta; | ||
377 | } | ||
378 | |||
365 | sta->sta.supp_rates[band] = rates; | 379 | sta->sta.supp_rates[band] = rates; |
366 | if (elems->ht_cap_elem && | 380 | if (elems->ht_cap_elem && |
367 | sdata->local->_oper_channel_type != NL80211_CHAN_NO_HT) | 381 | sdata->vif.bss_conf.channel_type != NL80211_CHAN_NO_HT) |
368 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 382 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
369 | elems->ht_cap_elem, | 383 | elems->ht_cap_elem, |
370 | &sta->sta.ht_cap); | 384 | &sta->sta.ht_cap); |
@@ -523,7 +537,8 @@ int mesh_plink_open(struct sta_info *sta) | |||
523 | spin_lock_bh(&sta->lock); | 537 | spin_lock_bh(&sta->lock); |
524 | get_random_bytes(&llid, 2); | 538 | get_random_bytes(&llid, 2); |
525 | sta->llid = llid; | 539 | sta->llid = llid; |
526 | if (sta->plink_state != NL80211_PLINK_LISTEN) { | 540 | if (sta->plink_state != NL80211_PLINK_LISTEN && |
541 | sta->plink_state != NL80211_PLINK_BLOCKED) { | ||
527 | spin_unlock_bh(&sta->lock); | 542 | spin_unlock_bh(&sta->lock); |
528 | return -EBUSY; | 543 | return -EBUSY; |
529 | } | 544 | } |
@@ -541,15 +556,14 @@ int mesh_plink_open(struct sta_info *sta) | |||
541 | void mesh_plink_block(struct sta_info *sta) | 556 | void mesh_plink_block(struct sta_info *sta) |
542 | { | 557 | { |
543 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 558 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
544 | bool deactivated; | 559 | u32 changed; |
545 | 560 | ||
546 | spin_lock_bh(&sta->lock); | 561 | spin_lock_bh(&sta->lock); |
547 | deactivated = __mesh_plink_deactivate(sta); | 562 | changed = __mesh_plink_deactivate(sta); |
548 | sta->plink_state = NL80211_PLINK_BLOCKED; | 563 | sta->plink_state = NL80211_PLINK_BLOCKED; |
549 | spin_unlock_bh(&sta->lock); | 564 | spin_unlock_bh(&sta->lock); |
550 | 565 | ||
551 | if (deactivated) | 566 | ieee80211_bss_info_change_notify(sdata, changed); |
552 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | ||
553 | } | 567 | } |
554 | 568 | ||
555 | 569 | ||
@@ -852,9 +866,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
852 | del_timer(&sta->plink_timer); | 866 | del_timer(&sta->plink_timer); |
853 | sta->plink_state = NL80211_PLINK_ESTAB; | 867 | sta->plink_state = NL80211_PLINK_ESTAB; |
854 | spin_unlock_bh(&sta->lock); | 868 | spin_unlock_bh(&sta->lock); |
855 | mesh_plink_inc_estab_count(sdata); | 869 | changed |= mesh_plink_inc_estab_count(sdata); |
856 | changed |= mesh_set_ht_prot_mode(sdata); | 870 | changed |= mesh_set_ht_prot_mode(sdata); |
857 | changed |= BSS_CHANGED_BEACON; | ||
858 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", | 871 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", |
859 | sta->sta.addr); | 872 | sta->sta.addr); |
860 | break; | 873 | break; |
@@ -888,9 +901,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
888 | del_timer(&sta->plink_timer); | 901 | del_timer(&sta->plink_timer); |
889 | sta->plink_state = NL80211_PLINK_ESTAB; | 902 | sta->plink_state = NL80211_PLINK_ESTAB; |
890 | spin_unlock_bh(&sta->lock); | 903 | spin_unlock_bh(&sta->lock); |
891 | mesh_plink_inc_estab_count(sdata); | 904 | changed |= mesh_plink_inc_estab_count(sdata); |
892 | changed |= mesh_set_ht_prot_mode(sdata); | 905 | changed |= mesh_set_ht_prot_mode(sdata); |
893 | changed |= BSS_CHANGED_BEACON; | ||
894 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", | 906 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", |
895 | sta->sta.addr); | 907 | sta->sta.addr); |
896 | mesh_plink_frame_tx(sdata, | 908 | mesh_plink_frame_tx(sdata, |
@@ -908,13 +920,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
908 | case CLS_ACPT: | 920 | case CLS_ACPT: |
909 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); | 921 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); |
910 | sta->reason = reason; | 922 | sta->reason = reason; |
911 | __mesh_plink_deactivate(sta); | 923 | changed |= __mesh_plink_deactivate(sta); |
912 | sta->plink_state = NL80211_PLINK_HOLDING; | 924 | sta->plink_state = NL80211_PLINK_HOLDING; |
913 | llid = sta->llid; | 925 | llid = sta->llid; |
914 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 926 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
915 | spin_unlock_bh(&sta->lock); | 927 | spin_unlock_bh(&sta->lock); |
916 | changed |= mesh_set_ht_prot_mode(sdata); | 928 | changed |= mesh_set_ht_prot_mode(sdata); |
917 | changed |= BSS_CHANGED_BEACON; | ||
918 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 929 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
919 | sta->sta.addr, llid, plid, reason); | 930 | sta->sta.addr, llid, plid, reason); |
920 | break; | 931 | break; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f76b83341cf9..e714ed8bb198 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -88,8 +88,6 @@ MODULE_PARM_DESC(probe_wait_ms, | |||
88 | #define TMR_RUNNING_TIMER 0 | 88 | #define TMR_RUNNING_TIMER 0 |
89 | #define TMR_RUNNING_CHANSW 1 | 89 | #define TMR_RUNNING_CHANSW 1 |
90 | 90 | ||
91 | #define DEAUTH_DISASSOC_LEN (24 /* hdr */ + 2 /* reason */) | ||
92 | |||
93 | /* | 91 | /* |
94 | * All cfg80211 functions have to be called outside a locked | 92 | * All cfg80211 functions have to be called outside a locked |
95 | * section so that they can acquire a lock themselves... This | 93 | * section so that they can acquire a lock themselves... This |
@@ -146,6 +144,9 @@ void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) | |||
146 | if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER) | 144 | if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER) |
147 | return; | 145 | return; |
148 | 146 | ||
147 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
148 | return; | ||
149 | |||
149 | mod_timer(&sdata->u.mgd.bcn_mon_timer, | 150 | mod_timer(&sdata->u.mgd.bcn_mon_timer, |
150 | round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout)); | 151 | round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout)); |
151 | } | 152 | } |
@@ -182,15 +183,15 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, | |||
182 | u16 ht_opmode; | 183 | u16 ht_opmode; |
183 | bool disable_40 = false; | 184 | bool disable_40 = false; |
184 | 185 | ||
185 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 186 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
186 | 187 | ||
187 | switch (sdata->vif.bss_conf.channel_type) { | 188 | switch (sdata->vif.bss_conf.channel_type) { |
188 | case NL80211_CHAN_HT40PLUS: | 189 | case NL80211_CHAN_HT40PLUS: |
189 | if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40PLUS) | 190 | if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40PLUS) |
190 | disable_40 = true; | 191 | disable_40 = true; |
191 | break; | 192 | break; |
192 | case NL80211_CHAN_HT40MINUS: | 193 | case NL80211_CHAN_HT40MINUS: |
193 | if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40MINUS) | 194 | if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40MINUS) |
194 | disable_40 = true; | 195 | disable_40 = true; |
195 | break; | 196 | break; |
196 | default: | 197 | default: |
@@ -326,6 +327,26 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | |||
326 | ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); | 327 | ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); |
327 | } | 328 | } |
328 | 329 | ||
330 | static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | ||
331 | struct sk_buff *skb, | ||
332 | struct ieee80211_supported_band *sband) | ||
333 | { | ||
334 | u8 *pos; | ||
335 | u32 cap; | ||
336 | struct ieee80211_sta_vht_cap vht_cap; | ||
337 | |||
338 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); | ||
339 | |||
340 | memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); | ||
341 | |||
342 | /* determine capability flags */ | ||
343 | cap = vht_cap.cap; | ||
344 | |||
345 | /* reserve and fill IE */ | ||
346 | pos = skb_put(skb, sizeof(struct ieee80211_vht_capabilities) + 2); | ||
347 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); | ||
348 | } | ||
349 | |||
329 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | 350 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) |
330 | { | 351 | { |
331 | struct ieee80211_local *local = sdata->local; | 352 | struct ieee80211_local *local = sdata->local; |
@@ -371,6 +392,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
371 | 4 + /* power capability */ | 392 | 4 + /* power capability */ |
372 | 2 + 2 * sband->n_channels + /* supported channels */ | 393 | 2 + 2 * sband->n_channels + /* supported channels */ |
373 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ | 394 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ |
395 | 2 + sizeof(struct ieee80211_vht_capabilities) + /* VHT */ | ||
374 | assoc_data->ie_len + /* extra IEs */ | 396 | assoc_data->ie_len + /* extra IEs */ |
375 | 9, /* WMM */ | 397 | 9, /* WMM */ |
376 | GFP_KERNEL); | 398 | GFP_KERNEL); |
@@ -503,6 +525,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
503 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, | 525 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
504 | sband, local->oper_channel, ifmgd->ap_smps); | 526 | sband, local->oper_channel, ifmgd->ap_smps); |
505 | 527 | ||
528 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | ||
529 | ieee80211_add_vht_ie(sdata, skb, sband); | ||
530 | |||
506 | /* if present, add any custom non-vendor IEs that go after HT */ | 531 | /* if present, add any custom non-vendor IEs that go after HT */ |
507 | if (assoc_data->ie_len && assoc_data->ie) { | 532 | if (assoc_data->ie_len && assoc_data->ie) { |
508 | noffset = ieee80211_ie_split_vendor(assoc_data->ie, | 533 | noffset = ieee80211_ie_split_vendor(assoc_data->ie, |
@@ -547,48 +572,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
547 | ieee80211_tx_skb(sdata, skb); | 572 | ieee80211_tx_skb(sdata, skb); |
548 | } | 573 | } |
549 | 574 | ||
550 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | ||
551 | const u8 *bssid, u16 stype, | ||
552 | u16 reason, bool send_frame, | ||
553 | u8 *frame_buf) | ||
554 | { | ||
555 | struct ieee80211_local *local = sdata->local; | ||
556 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
557 | struct sk_buff *skb; | ||
558 | struct ieee80211_mgmt *mgmt = (void *)frame_buf; | ||
559 | |||
560 | /* build frame */ | ||
561 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); | ||
562 | mgmt->duration = 0; /* initialize only */ | ||
563 | mgmt->seq_ctrl = 0; /* initialize only */ | ||
564 | memcpy(mgmt->da, bssid, ETH_ALEN); | ||
565 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
566 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | ||
567 | /* u.deauth.reason_code == u.disassoc.reason_code */ | ||
568 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); | ||
569 | |||
570 | if (send_frame) { | ||
571 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
572 | DEAUTH_DISASSOC_LEN); | ||
573 | if (!skb) | ||
574 | return; | ||
575 | |||
576 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
577 | |||
578 | /* copy in frame */ | ||
579 | memcpy(skb_put(skb, DEAUTH_DISASSOC_LEN), | ||
580 | mgmt, DEAUTH_DISASSOC_LEN); | ||
581 | |||
582 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) | ||
583 | IEEE80211_SKB_CB(skb)->flags |= | ||
584 | IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
585 | |||
586 | drv_mgd_prepare_tx(local, sdata); | ||
587 | |||
588 | ieee80211_tx_skb(sdata, skb); | ||
589 | } | ||
590 | } | ||
591 | |||
592 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 575 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
593 | struct ieee80211_sub_if_data *sdata) | 576 | struct ieee80211_sub_if_data *sdata) |
594 | { | 577 | { |
@@ -687,6 +670,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
687 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 670 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
688 | ifmgd->associated->channel = sdata->local->oper_channel; | 671 | ifmgd->associated->channel = sdata->local->oper_channel; |
689 | 672 | ||
673 | /* XXX: wait for a beacon first? */ | ||
690 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 674 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
691 | IEEE80211_QUEUE_STOP_REASON_CSA); | 675 | IEEE80211_QUEUE_STOP_REASON_CSA); |
692 | out: | 676 | out: |
@@ -704,16 +688,13 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) | |||
704 | 688 | ||
705 | trace_api_chswitch_done(sdata, success); | 689 | trace_api_chswitch_done(sdata, success); |
706 | if (!success) { | 690 | if (!success) { |
707 | /* | 691 | sdata_info(sdata, |
708 | * If the channel switch was not successful, stay | 692 | "driver channel switch failed, disconnecting\n"); |
709 | * around on the old channel. We currently lack | 693 | ieee80211_queue_work(&sdata->local->hw, |
710 | * good handling of this situation, possibly we | 694 | &ifmgd->csa_connection_drop_work); |
711 | * should just drop the association. | 695 | } else { |
712 | */ | 696 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); |
713 | sdata->local->csa_channel = sdata->local->oper_channel; | ||
714 | } | 697 | } |
715 | |||
716 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); | ||
717 | } | 698 | } |
718 | EXPORT_SYMBOL(ieee80211_chswitch_done); | 699 | EXPORT_SYMBOL(ieee80211_chswitch_done); |
719 | 700 | ||
@@ -758,61 +739,111 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
758 | return; | 739 | return; |
759 | 740 | ||
760 | new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); | 741 | new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); |
761 | if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) | 742 | if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) { |
743 | sdata_info(sdata, | ||
744 | "AP %pM switches to unsupported channel (%d MHz), disconnecting\n", | ||
745 | ifmgd->associated->bssid, new_freq); | ||
746 | ieee80211_queue_work(&sdata->local->hw, | ||
747 | &ifmgd->csa_connection_drop_work); | ||
762 | return; | 748 | return; |
749 | } | ||
763 | 750 | ||
764 | sdata->local->csa_channel = new_ch; | 751 | sdata->local->csa_channel = new_ch; |
765 | 752 | ||
753 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
754 | |||
755 | if (sw_elem->mode) | ||
756 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
757 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
758 | |||
766 | if (sdata->local->ops->channel_switch) { | 759 | if (sdata->local->ops->channel_switch) { |
767 | /* use driver's channel switch callback */ | 760 | /* use driver's channel switch callback */ |
768 | struct ieee80211_channel_switch ch_switch; | 761 | struct ieee80211_channel_switch ch_switch = { |
769 | memset(&ch_switch, 0, sizeof(ch_switch)); | 762 | .timestamp = timestamp, |
770 | ch_switch.timestamp = timestamp; | 763 | .block_tx = sw_elem->mode, |
771 | if (sw_elem->mode) { | 764 | .channel = new_ch, |
772 | ch_switch.block_tx = true; | 765 | .count = sw_elem->count, |
773 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 766 | }; |
774 | IEEE80211_QUEUE_STOP_REASON_CSA); | 767 | |
775 | } | ||
776 | ch_switch.channel = new_ch; | ||
777 | ch_switch.count = sw_elem->count; | ||
778 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
779 | drv_channel_switch(sdata->local, &ch_switch); | 768 | drv_channel_switch(sdata->local, &ch_switch); |
780 | return; | 769 | return; |
781 | } | 770 | } |
782 | 771 | ||
783 | /* channel switch handled in software */ | 772 | /* channel switch handled in software */ |
784 | if (sw_elem->count <= 1) { | 773 | if (sw_elem->count <= 1) |
785 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); | 774 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); |
786 | } else { | 775 | else |
787 | if (sw_elem->mode) | ||
788 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
789 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
790 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
791 | mod_timer(&ifmgd->chswitch_timer, | 776 | mod_timer(&ifmgd->chswitch_timer, |
792 | jiffies + | 777 | TU_TO_EXP_TIME(sw_elem->count * |
793 | msecs_to_jiffies(sw_elem->count * | 778 | cbss->beacon_interval)); |
794 | cbss->beacon_interval)); | ||
795 | } | ||
796 | } | 779 | } |
797 | 780 | ||
798 | static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | 781 | static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, |
799 | u16 capab_info, u8 *pwr_constr_elem, | 782 | struct ieee80211_channel *channel, |
800 | u8 pwr_constr_elem_len) | 783 | const u8 *country_ie, u8 country_ie_len, |
784 | const u8 *pwr_constr_elem) | ||
801 | { | 785 | { |
802 | struct ieee80211_conf *conf = &sdata->local->hw.conf; | 786 | struct ieee80211_country_ie_triplet *triplet; |
787 | int chan = ieee80211_frequency_to_channel(channel->center_freq); | ||
788 | int i, chan_pwr, chan_increment, new_ap_level; | ||
789 | bool have_chan_pwr = false; | ||
803 | 790 | ||
804 | if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT)) | 791 | /* Invalid IE */ |
792 | if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) | ||
805 | return; | 793 | return; |
806 | 794 | ||
807 | /* Power constraint IE length should be 1 octet */ | 795 | triplet = (void *)(country_ie + 3); |
808 | if (pwr_constr_elem_len != 1) | 796 | country_ie_len -= 3; |
809 | return; | 797 | |
798 | switch (channel->band) { | ||
799 | default: | ||
800 | WARN_ON_ONCE(1); | ||
801 | /* fall through */ | ||
802 | case IEEE80211_BAND_2GHZ: | ||
803 | case IEEE80211_BAND_60GHZ: | ||
804 | chan_increment = 1; | ||
805 | break; | ||
806 | case IEEE80211_BAND_5GHZ: | ||
807 | chan_increment = 4; | ||
808 | break; | ||
809 | } | ||
810 | |||
811 | /* find channel */ | ||
812 | while (country_ie_len >= 3) { | ||
813 | u8 first_channel = triplet->chans.first_channel; | ||
810 | 814 | ||
811 | if ((*pwr_constr_elem <= conf->channel->max_reg_power) && | 815 | if (first_channel >= IEEE80211_COUNTRY_EXTENSION_ID) |
812 | (*pwr_constr_elem != sdata->local->power_constr_level)) { | 816 | goto next; |
813 | sdata->local->power_constr_level = *pwr_constr_elem; | 817 | |
814 | ieee80211_hw_config(sdata->local, 0); | 818 | for (i = 0; i < triplet->chans.num_channels; i++) { |
819 | if (first_channel + i * chan_increment == chan) { | ||
820 | have_chan_pwr = true; | ||
821 | chan_pwr = triplet->chans.max_power; | ||
822 | break; | ||
823 | } | ||
824 | } | ||
825 | if (have_chan_pwr) | ||
826 | break; | ||
827 | |||
828 | next: | ||
829 | triplet++; | ||
830 | country_ie_len -= 3; | ||
815 | } | 831 | } |
832 | |||
833 | if (!have_chan_pwr) | ||
834 | return; | ||
835 | |||
836 | new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); | ||
837 | |||
838 | if (sdata->local->ap_power_level == new_ap_level) | ||
839 | return; | ||
840 | |||
841 | sdata_info(sdata, | ||
842 | "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", | ||
843 | new_ap_level, chan_pwr, *pwr_constr_elem, | ||
844 | sdata->u.mgd.bssid); | ||
845 | sdata->local->ap_power_level = new_ap_level; | ||
846 | ieee80211_hw_config(sdata->local, 0); | ||
816 | } | 847 | } |
817 | 848 | ||
818 | void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) | 849 | void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) |
@@ -1007,6 +1038,16 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
1007 | ieee80211_change_ps(local); | 1038 | ieee80211_change_ps(local); |
1008 | } | 1039 | } |
1009 | 1040 | ||
1041 | void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata) | ||
1042 | { | ||
1043 | bool ps_allowed = ieee80211_powersave_allowed(sdata); | ||
1044 | |||
1045 | if (sdata->vif.bss_conf.ps != ps_allowed) { | ||
1046 | sdata->vif.bss_conf.ps = ps_allowed; | ||
1047 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_PS); | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1010 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work) | 1051 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work) |
1011 | { | 1052 | { |
1012 | struct ieee80211_local *local = | 1053 | struct ieee80211_local *local = |
@@ -1239,7 +1280,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | |||
1239 | } | 1280 | } |
1240 | 1281 | ||
1241 | use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); | 1282 | use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); |
1242 | if (sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) | 1283 | if (sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) |
1243 | use_short_slot = true; | 1284 | use_short_slot = true; |
1244 | 1285 | ||
1245 | if (use_protection != bss_conf->use_cts_prot) { | 1286 | if (use_protection != bss_conf->use_cts_prot) { |
@@ -1307,9 +1348,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1307 | 1348 | ||
1308 | mutex_lock(&local->iflist_mtx); | 1349 | mutex_lock(&local->iflist_mtx); |
1309 | ieee80211_recalc_ps(local, -1); | 1350 | ieee80211_recalc_ps(local, -1); |
1310 | ieee80211_recalc_smps(local); | ||
1311 | mutex_unlock(&local->iflist_mtx); | 1351 | mutex_unlock(&local->iflist_mtx); |
1312 | 1352 | ||
1353 | ieee80211_recalc_smps(local); | ||
1354 | ieee80211_recalc_ps_vif(sdata); | ||
1355 | |||
1313 | netif_tx_start_all_queues(sdata->dev); | 1356 | netif_tx_start_all_queues(sdata->dev); |
1314 | netif_carrier_on(sdata->dev); | 1357 | netif_carrier_on(sdata->dev); |
1315 | } | 1358 | } |
@@ -1356,7 +1399,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1356 | sta = sta_info_get(sdata, ifmgd->bssid); | 1399 | sta = sta_info_get(sdata, ifmgd->bssid); |
1357 | if (sta) { | 1400 | if (sta) { |
1358 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | 1401 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
1359 | ieee80211_sta_tear_down_BA_sessions(sta, tx); | 1402 | ieee80211_sta_tear_down_BA_sessions(sta, false); |
1360 | } | 1403 | } |
1361 | mutex_unlock(&local->sta_mtx); | 1404 | mutex_unlock(&local->sta_mtx); |
1362 | 1405 | ||
@@ -1371,6 +1414,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1371 | } | 1414 | } |
1372 | local->ps_sdata = NULL; | 1415 | local->ps_sdata = NULL; |
1373 | 1416 | ||
1417 | /* disable per-vif ps */ | ||
1418 | ieee80211_recalc_ps_vif(sdata); | ||
1419 | |||
1374 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ | 1420 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ |
1375 | if (tx) | 1421 | if (tx) |
1376 | drv_flush(local, false); | 1422 | drv_flush(local, false); |
@@ -1401,7 +1447,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1401 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); | 1447 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); |
1402 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); | 1448 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); |
1403 | 1449 | ||
1404 | local->power_constr_level = 0; | 1450 | local->ap_power_level = 0; |
1405 | 1451 | ||
1406 | del_timer_sync(&local->dynamic_ps_timer); | 1452 | del_timer_sync(&local->dynamic_ps_timer); |
1407 | cancel_work_sync(&local->dynamic_ps_enable_work); | 1453 | cancel_work_sync(&local->dynamic_ps_enable_work); |
@@ -1542,7 +1588,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1542 | ssid_len = ssid[1]; | 1588 | ssid_len = ssid[1]; |
1543 | 1589 | ||
1544 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, | 1590 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, |
1545 | 0, (u32) -1, true, false); | 1591 | 0, (u32) -1, true, false, |
1592 | ifmgd->associated->channel); | ||
1546 | } | 1593 | } |
1547 | 1594 | ||
1548 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); | 1595 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); |
@@ -1645,19 +1692,21 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1645 | ssid_len = ssid[1]; | 1692 | ssid_len = ssid[1]; |
1646 | 1693 | ||
1647 | skb = ieee80211_build_probe_req(sdata, cbss->bssid, | 1694 | skb = ieee80211_build_probe_req(sdata, cbss->bssid, |
1648 | (u32) -1, ssid + 2, ssid_len, | 1695 | (u32) -1, |
1696 | sdata->local->oper_channel, | ||
1697 | ssid + 2, ssid_len, | ||
1649 | NULL, 0, true); | 1698 | NULL, 0, true); |
1650 | 1699 | ||
1651 | return skb; | 1700 | return skb; |
1652 | } | 1701 | } |
1653 | EXPORT_SYMBOL(ieee80211_ap_probereq_get); | 1702 | EXPORT_SYMBOL(ieee80211_ap_probereq_get); |
1654 | 1703 | ||
1655 | static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | 1704 | static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata, |
1705 | bool transmit_frame) | ||
1656 | { | 1706 | { |
1657 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1707 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1658 | struct ieee80211_local *local = sdata->local; | 1708 | struct ieee80211_local *local = sdata->local; |
1659 | u8 bssid[ETH_ALEN]; | 1709 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
1660 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; | ||
1661 | 1710 | ||
1662 | mutex_lock(&ifmgd->mtx); | 1711 | mutex_lock(&ifmgd->mtx); |
1663 | if (!ifmgd->associated) { | 1712 | if (!ifmgd->associated) { |
@@ -1665,27 +1714,24 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1665 | return; | 1714 | return; |
1666 | } | 1715 | } |
1667 | 1716 | ||
1668 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | ||
1669 | |||
1670 | sdata_info(sdata, "Connection to AP %pM lost\n", bssid); | ||
1671 | |||
1672 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 1717 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
1673 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1718 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
1674 | false, frame_buf); | 1719 | transmit_frame, frame_buf); |
1720 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | ||
1675 | mutex_unlock(&ifmgd->mtx); | 1721 | mutex_unlock(&ifmgd->mtx); |
1676 | 1722 | ||
1677 | /* | 1723 | /* |
1678 | * must be outside lock due to cfg80211, | 1724 | * must be outside lock due to cfg80211, |
1679 | * but that's not a problem. | 1725 | * but that's not a problem. |
1680 | */ | 1726 | */ |
1681 | cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); | 1727 | cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); |
1682 | 1728 | ||
1683 | mutex_lock(&local->mtx); | 1729 | mutex_lock(&local->mtx); |
1684 | ieee80211_recalc_idle(local); | 1730 | ieee80211_recalc_idle(local); |
1685 | mutex_unlock(&local->mtx); | 1731 | mutex_unlock(&local->mtx); |
1686 | } | 1732 | } |
1687 | 1733 | ||
1688 | void ieee80211_beacon_connection_loss_work(struct work_struct *work) | 1734 | static void ieee80211_beacon_connection_loss_work(struct work_struct *work) |
1689 | { | 1735 | { |
1690 | struct ieee80211_sub_if_data *sdata = | 1736 | struct ieee80211_sub_if_data *sdata = |
1691 | container_of(work, struct ieee80211_sub_if_data, | 1737 | container_of(work, struct ieee80211_sub_if_data, |
@@ -1701,10 +1747,24 @@ void ieee80211_beacon_connection_loss_work(struct work_struct *work) | |||
1701 | rcu_read_unlock(); | 1747 | rcu_read_unlock(); |
1702 | } | 1748 | } |
1703 | 1749 | ||
1704 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | 1750 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) { |
1705 | __ieee80211_connection_loss(sdata); | 1751 | sdata_info(sdata, "Connection to AP %pM lost\n", |
1706 | else | 1752 | ifmgd->bssid); |
1753 | __ieee80211_disconnect(sdata, false); | ||
1754 | } else { | ||
1707 | ieee80211_mgd_probe_ap(sdata, true); | 1755 | ieee80211_mgd_probe_ap(sdata, true); |
1756 | } | ||
1757 | } | ||
1758 | |||
1759 | static void ieee80211_csa_connection_drop_work(struct work_struct *work) | ||
1760 | { | ||
1761 | struct ieee80211_sub_if_data *sdata = | ||
1762 | container_of(work, struct ieee80211_sub_if_data, | ||
1763 | u.mgd.csa_connection_drop_work); | ||
1764 | |||
1765 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | ||
1766 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
1767 | __ieee80211_disconnect(sdata, true); | ||
1708 | } | 1768 | } |
1709 | 1769 | ||
1710 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) | 1770 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) |
@@ -2232,14 +2292,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2232 | mutex_unlock(&local->iflist_mtx); | 2292 | mutex_unlock(&local->iflist_mtx); |
2233 | } | 2293 | } |
2234 | 2294 | ||
2235 | if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && | 2295 | if (elems->ch_switch_ie && |
2236 | (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, | 2296 | memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, ETH_ALEN) == 0) |
2237 | ETH_ALEN) == 0)) { | 2297 | ieee80211_sta_process_chanswitch(sdata, elems->ch_switch_ie, |
2238 | struct ieee80211_channel_sw_ie *sw_elem = | ||
2239 | (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; | ||
2240 | ieee80211_sta_process_chanswitch(sdata, sw_elem, | ||
2241 | bss, rx_status->mactime); | 2298 | bss, rx_status->mactime); |
2242 | } | ||
2243 | } | 2299 | } |
2244 | 2300 | ||
2245 | 2301 | ||
@@ -2326,7 +2382,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2326 | if (baselen > len) | 2382 | if (baselen > len) |
2327 | return; | 2383 | return; |
2328 | 2384 | ||
2329 | if (rx_status->freq != local->hw.conf.channel->center_freq) | 2385 | if (rx_status->freq != local->oper_channel->center_freq) |
2330 | return; | 2386 | return; |
2331 | 2387 | ||
2332 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && | 2388 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && |
@@ -2490,21 +2546,19 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2490 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { | 2546 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { |
2491 | struct ieee80211_supported_band *sband; | 2547 | struct ieee80211_supported_band *sband; |
2492 | 2548 | ||
2493 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 2549 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
2494 | 2550 | ||
2495 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, | 2551 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, |
2496 | bssid, true); | 2552 | bssid, true); |
2497 | } | 2553 | } |
2498 | 2554 | ||
2499 | /* Note: country IE parsing is done for us by cfg80211 */ | 2555 | if (elems.country_elem && elems.pwr_constr_elem && |
2500 | if (elems.country_elem) { | 2556 | mgmt->u.probe_resp.capab_info & |
2501 | /* TODO: IBSS also needs this */ | 2557 | cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) |
2502 | if (elems.pwr_constr_elem) | 2558 | ieee80211_handle_pwr_constr(sdata, local->oper_channel, |
2503 | ieee80211_handle_pwr_constr(sdata, | 2559 | elems.country_elem, |
2504 | le16_to_cpu(mgmt->u.probe_resp.capab_info), | 2560 | elems.country_elem_len, |
2505 | elems.pwr_constr_elem, | 2561 | elems.pwr_constr_elem); |
2506 | elems.pwr_constr_elem_len); | ||
2507 | } | ||
2508 | 2562 | ||
2509 | ieee80211_bss_info_change_notify(sdata, changed); | 2563 | ieee80211_bss_info_change_notify(sdata, changed); |
2510 | } | 2564 | } |
@@ -2601,7 +2655,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2601 | { | 2655 | { |
2602 | struct ieee80211_local *local = sdata->local; | 2656 | struct ieee80211_local *local = sdata->local; |
2603 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2657 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2604 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; | 2658 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
2605 | 2659 | ||
2606 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, | 2660 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, |
2607 | false, frame_buf); | 2661 | false, frame_buf); |
@@ -2611,7 +2665,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2611 | * must be outside lock due to cfg80211, | 2665 | * must be outside lock due to cfg80211, |
2612 | * but that's not a problem. | 2666 | * but that's not a problem. |
2613 | */ | 2667 | */ |
2614 | cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); | 2668 | cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); |
2615 | 2669 | ||
2616 | mutex_lock(&local->mtx); | 2670 | mutex_lock(&local->mtx); |
2617 | ieee80211_recalc_idle(local); | 2671 | ieee80211_recalc_idle(local); |
@@ -2673,7 +2727,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2673 | * will not answer to direct packet in unassociated state. | 2727 | * will not answer to direct packet in unassociated state. |
2674 | */ | 2728 | */ |
2675 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], | 2729 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], |
2676 | NULL, 0, (u32) -1, true, false); | 2730 | NULL, 0, (u32) -1, true, false, |
2731 | auth_data->bss->channel); | ||
2677 | } | 2732 | } |
2678 | 2733 | ||
2679 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 2734 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
@@ -2894,6 +2949,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
2894 | 2949 | ||
2895 | cancel_work_sync(&ifmgd->monitor_work); | 2950 | cancel_work_sync(&ifmgd->monitor_work); |
2896 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | 2951 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
2952 | cancel_work_sync(&ifmgd->csa_connection_drop_work); | ||
2897 | if (del_timer_sync(&ifmgd->timer)) | 2953 | if (del_timer_sync(&ifmgd->timer)) |
2898 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 2954 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
2899 | 2955 | ||
@@ -2950,6 +3006,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2950 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 3006 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
2951 | INIT_WORK(&ifmgd->beacon_connection_loss_work, | 3007 | INIT_WORK(&ifmgd->beacon_connection_loss_work, |
2952 | ieee80211_beacon_connection_loss_work); | 3008 | ieee80211_beacon_connection_loss_work); |
3009 | INIT_WORK(&ifmgd->csa_connection_drop_work, | ||
3010 | ieee80211_csa_connection_drop_work); | ||
2953 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); | 3011 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); |
2954 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 3012 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
2955 | (unsigned long) sdata); | 3013 | (unsigned long) sdata); |
@@ -3000,41 +3058,17 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
3000 | return 0; | 3058 | return 0; |
3001 | } | 3059 | } |
3002 | 3060 | ||
3003 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | 3061 | static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, |
3004 | struct cfg80211_bss *cbss, bool assoc) | 3062 | struct cfg80211_bss *cbss) |
3005 | { | 3063 | { |
3006 | struct ieee80211_local *local = sdata->local; | 3064 | struct ieee80211_local *local = sdata->local; |
3007 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3065 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3008 | struct ieee80211_bss *bss = (void *)cbss->priv; | ||
3009 | struct sta_info *sta = NULL; | ||
3010 | bool have_sta = false; | ||
3011 | int err; | ||
3012 | int ht_cfreq; | 3066 | int ht_cfreq; |
3013 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 3067 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
3014 | const u8 *ht_oper_ie; | 3068 | const u8 *ht_oper_ie; |
3015 | const struct ieee80211_ht_operation *ht_oper = NULL; | 3069 | const struct ieee80211_ht_operation *ht_oper = NULL; |
3016 | struct ieee80211_supported_band *sband; | 3070 | struct ieee80211_supported_band *sband; |
3017 | 3071 | ||
3018 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) | ||
3019 | return -EINVAL; | ||
3020 | |||
3021 | if (assoc) { | ||
3022 | rcu_read_lock(); | ||
3023 | have_sta = sta_info_get(sdata, cbss->bssid); | ||
3024 | rcu_read_unlock(); | ||
3025 | } | ||
3026 | |||
3027 | if (!have_sta) { | ||
3028 | sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); | ||
3029 | if (!sta) | ||
3030 | return -ENOMEM; | ||
3031 | } | ||
3032 | |||
3033 | mutex_lock(&local->mtx); | ||
3034 | ieee80211_recalc_idle(sdata->local); | ||
3035 | mutex_unlock(&local->mtx); | ||
3036 | |||
3037 | /* switch to the right channel */ | ||
3038 | sband = local->hw.wiphy->bands[cbss->channel->band]; | 3072 | sband = local->hw.wiphy->bands[cbss->channel->band]; |
3039 | 3073 | ||
3040 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; | 3074 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; |
@@ -3097,10 +3131,51 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3097 | local->oper_channel = cbss->channel; | 3131 | local->oper_channel = cbss->channel; |
3098 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 3132 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
3099 | 3133 | ||
3100 | if (sta) { | 3134 | return 0; |
3135 | } | ||
3136 | |||
3137 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | ||
3138 | struct cfg80211_bss *cbss, bool assoc) | ||
3139 | { | ||
3140 | struct ieee80211_local *local = sdata->local; | ||
3141 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3142 | struct ieee80211_bss *bss = (void *)cbss->priv; | ||
3143 | struct sta_info *new_sta = NULL; | ||
3144 | bool have_sta = false; | ||
3145 | int err; | ||
3146 | |||
3147 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) | ||
3148 | return -EINVAL; | ||
3149 | |||
3150 | if (assoc) { | ||
3151 | rcu_read_lock(); | ||
3152 | have_sta = sta_info_get(sdata, cbss->bssid); | ||
3153 | rcu_read_unlock(); | ||
3154 | } | ||
3155 | |||
3156 | if (!have_sta) { | ||
3157 | new_sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); | ||
3158 | if (!new_sta) | ||
3159 | return -ENOMEM; | ||
3160 | } | ||
3161 | |||
3162 | mutex_lock(&local->mtx); | ||
3163 | ieee80211_recalc_idle(sdata->local); | ||
3164 | mutex_unlock(&local->mtx); | ||
3165 | |||
3166 | if (new_sta) { | ||
3101 | u32 rates = 0, basic_rates = 0; | 3167 | u32 rates = 0, basic_rates = 0; |
3102 | bool have_higher_than_11mbit; | 3168 | bool have_higher_than_11mbit; |
3103 | int min_rate = INT_MAX, min_rate_index = -1; | 3169 | int min_rate = INT_MAX, min_rate_index = -1; |
3170 | struct ieee80211_supported_band *sband; | ||
3171 | |||
3172 | sband = local->hw.wiphy->bands[cbss->channel->band]; | ||
3173 | |||
3174 | err = ieee80211_prep_channel(sdata, cbss); | ||
3175 | if (err) { | ||
3176 | sta_info_free(local, new_sta); | ||
3177 | return err; | ||
3178 | } | ||
3104 | 3179 | ||
3105 | ieee80211_get_rates(sband, bss->supp_rates, | 3180 | ieee80211_get_rates(sband, bss->supp_rates, |
3106 | bss->supp_rates_len, | 3181 | bss->supp_rates_len, |
@@ -3122,7 +3197,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3122 | basic_rates = BIT(min_rate_index); | 3197 | basic_rates = BIT(min_rate_index); |
3123 | } | 3198 | } |
3124 | 3199 | ||
3125 | sta->sta.supp_rates[cbss->channel->band] = rates; | 3200 | new_sta->sta.supp_rates[cbss->channel->band] = rates; |
3126 | sdata->vif.bss_conf.basic_rates = basic_rates; | 3201 | sdata->vif.bss_conf.basic_rates = basic_rates; |
3127 | 3202 | ||
3128 | /* cf. IEEE 802.11 9.2.12 */ | 3203 | /* cf. IEEE 802.11 9.2.12 */ |
@@ -3145,10 +3220,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3145 | BSS_CHANGED_BEACON_INT); | 3220 | BSS_CHANGED_BEACON_INT); |
3146 | 3221 | ||
3147 | if (assoc) | 3222 | if (assoc) |
3148 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 3223 | sta_info_pre_move_state(new_sta, IEEE80211_STA_AUTH); |
3149 | 3224 | ||
3150 | err = sta_info_insert(sta); | 3225 | err = sta_info_insert(new_sta); |
3151 | sta = NULL; | 3226 | new_sta = NULL; |
3152 | if (err) { | 3227 | if (err) { |
3153 | sdata_info(sdata, | 3228 | sdata_info(sdata, |
3154 | "failed to insert STA entry for the AP (error %d)\n", | 3229 | "failed to insert STA entry for the AP (error %d)\n", |
@@ -3302,9 +3377,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3302 | } | 3377 | } |
3303 | 3378 | ||
3304 | /* prepare assoc data */ | 3379 | /* prepare assoc data */ |
3305 | 3380 | ||
3306 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; | 3381 | /* |
3307 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 3382 | * keep only the 40 MHz disable bit set as it might have |
3383 | * been set during authentication already, all other bits | ||
3384 | * should be reset for a new connection | ||
3385 | */ | ||
3386 | ifmgd->flags &= IEEE80211_STA_DISABLE_40MHZ; | ||
3308 | 3387 | ||
3309 | ifmgd->beacon_crc_valid = false; | 3388 | ifmgd->beacon_crc_valid = false; |
3310 | 3389 | ||
@@ -3320,21 +3399,34 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3320 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 3399 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
3321 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { | 3400 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { |
3322 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3401 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3402 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
3323 | netdev_info(sdata->dev, | 3403 | netdev_info(sdata->dev, |
3324 | "disabling HT due to WEP/TKIP use\n"); | 3404 | "disabling HT/VHT due to WEP/TKIP use\n"); |
3325 | } | 3405 | } |
3326 | } | 3406 | } |
3327 | 3407 | ||
3328 | if (req->flags & ASSOC_REQ_DISABLE_HT) | 3408 | if (req->flags & ASSOC_REQ_DISABLE_HT) { |
3329 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3409 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3410 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
3411 | } | ||
3330 | 3412 | ||
3331 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 3413 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
3332 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3414 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
3333 | if (!sband->ht_cap.ht_supported || | 3415 | if (!sband->ht_cap.ht_supported || |
3334 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 3416 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { |
3335 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3417 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3336 | netdev_info(sdata->dev, | 3418 | if (!bss->wmm_used) |
3337 | "disabling HT as WMM/QoS is not supported\n"); | 3419 | netdev_info(sdata->dev, |
3420 | "disabling HT as WMM/QoS is not supported by the AP\n"); | ||
3421 | } | ||
3422 | |||
3423 | /* disable VHT if we don't support it or the AP doesn't use WMM */ | ||
3424 | if (!sband->vht_cap.vht_supported || | ||
3425 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | ||
3426 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
3427 | if (!bss->wmm_used) | ||
3428 | netdev_info(sdata->dev, | ||
3429 | "disabling VHT as WMM/QoS is not supported by the AP\n"); | ||
3338 | } | 3430 | } |
3339 | 3431 | ||
3340 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); | 3432 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); |
@@ -3456,7 +3548,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3456 | struct cfg80211_deauth_request *req) | 3548 | struct cfg80211_deauth_request *req) |
3457 | { | 3549 | { |
3458 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3550 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3459 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; | 3551 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
3460 | 3552 | ||
3461 | mutex_lock(&ifmgd->mtx); | 3553 | mutex_lock(&ifmgd->mtx); |
3462 | 3554 | ||
@@ -3471,17 +3563,21 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3471 | req->bssid, req->reason_code); | 3563 | req->bssid, req->reason_code); |
3472 | 3564 | ||
3473 | if (ifmgd->associated && | 3565 | if (ifmgd->associated && |
3474 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) | 3566 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { |
3475 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 3567 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
3476 | req->reason_code, true, frame_buf); | 3568 | req->reason_code, true, frame_buf); |
3477 | else | 3569 | } else { |
3570 | drv_mgd_prepare_tx(sdata->local, sdata); | ||
3478 | ieee80211_send_deauth_disassoc(sdata, req->bssid, | 3571 | ieee80211_send_deauth_disassoc(sdata, req->bssid, |
3479 | IEEE80211_STYPE_DEAUTH, | 3572 | IEEE80211_STYPE_DEAUTH, |
3480 | req->reason_code, true, | 3573 | req->reason_code, true, |
3481 | frame_buf); | 3574 | frame_buf); |
3575 | } | ||
3576 | |||
3482 | mutex_unlock(&ifmgd->mtx); | 3577 | mutex_unlock(&ifmgd->mtx); |
3483 | 3578 | ||
3484 | __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); | 3579 | __cfg80211_send_deauth(sdata->dev, frame_buf, |
3580 | IEEE80211_DEAUTH_FRAME_LEN); | ||
3485 | 3581 | ||
3486 | mutex_lock(&sdata->local->mtx); | 3582 | mutex_lock(&sdata->local->mtx); |
3487 | ieee80211_recalc_idle(sdata->local); | 3583 | ieee80211_recalc_idle(sdata->local); |
@@ -3495,7 +3591,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
3495 | { | 3591 | { |
3496 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3592 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3497 | u8 bssid[ETH_ALEN]; | 3593 | u8 bssid[ETH_ALEN]; |
3498 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; | 3594 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
3499 | 3595 | ||
3500 | mutex_lock(&ifmgd->mtx); | 3596 | mutex_lock(&ifmgd->mtx); |
3501 | 3597 | ||
@@ -3520,7 +3616,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
3520 | frame_buf); | 3616 | frame_buf); |
3521 | mutex_unlock(&ifmgd->mtx); | 3617 | mutex_unlock(&ifmgd->mtx); |
3522 | 3618 | ||
3523 | __cfg80211_send_disassoc(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); | 3619 | __cfg80211_send_disassoc(sdata->dev, frame_buf, |
3620 | IEEE80211_DEAUTH_FRAME_LEN); | ||
3524 | 3621 | ||
3525 | mutex_lock(&sdata->local->mtx); | 3622 | mutex_lock(&sdata->local->mtx); |
3526 | ieee80211_recalc_idle(sdata->local); | 3623 | ieee80211_recalc_idle(sdata->local); |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 635c3250c668..83608ac16780 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -116,6 +116,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | |||
116 | if (!ieee80211_sdata_running(sdata)) | 116 | if (!ieee80211_sdata_running(sdata)) |
117 | continue; | 117 | continue; |
118 | 118 | ||
119 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
120 | continue; | ||
121 | |||
119 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 122 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
120 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | 123 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); |
121 | 124 | ||
@@ -144,6 +147,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
144 | 147 | ||
145 | mutex_lock(&local->iflist_mtx); | 148 | mutex_lock(&local->iflist_mtx); |
146 | list_for_each_entry(sdata, &local->interfaces, list) { | 149 | list_for_each_entry(sdata, &local->interfaces, list) { |
150 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
151 | continue; | ||
152 | |||
147 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 153 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
148 | clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | 154 | clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); |
149 | 155 | ||
@@ -227,8 +233,7 @@ static void ieee80211_hw_roc_start(struct work_struct *work) | |||
227 | u32 dur = dep->duration; | 233 | u32 dur = dep->duration; |
228 | dep->duration = dur - roc->duration; | 234 | dep->duration = dur - roc->duration; |
229 | roc->duration = dur; | 235 | roc->duration = dur; |
230 | list_del(&dep->list); | 236 | list_move(&dep->list, &roc->list); |
231 | list_add(&dep->list, &roc->list); | ||
232 | } | 237 | } |
233 | } | 238 | } |
234 | out_unlock: | 239 | out_unlock: |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 6e4fd32c6617..10de668eb9f6 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -56,7 +56,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
56 | if (!ref) | 56 | if (!ref) |
57 | return; | 57 | return; |
58 | 58 | ||
59 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 59 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
60 | 60 | ||
61 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | 61 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); |
62 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); | 62 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0cb4edee6af5..61c621e9273f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -60,7 +60,9 @@ static inline int should_drop_frame(struct sk_buff *skb, | |||
60 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 60 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
61 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 61 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
62 | 62 | ||
63 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 63 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | |
64 | RX_FLAG_FAILED_PLCP_CRC | | ||
65 | RX_FLAG_AMPDU_IS_ZEROLEN)) | ||
64 | return 1; | 66 | return 1; |
65 | if (unlikely(skb->len < 16 + present_fcs_len)) | 67 | if (unlikely(skb->len < 16 + present_fcs_len)) |
66 | return 1; | 68 | return 1; |
@@ -91,10 +93,17 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
91 | if (status->flag & RX_FLAG_HT) /* HT info */ | 93 | if (status->flag & RX_FLAG_HT) /* HT info */ |
92 | len += 3; | 94 | len += 3; |
93 | 95 | ||
96 | if (status->flag & RX_FLAG_AMPDU_DETAILS) { | ||
97 | /* padding */ | ||
98 | while (len & 3) | ||
99 | len++; | ||
100 | len += 8; | ||
101 | } | ||
102 | |||
94 | return len; | 103 | return len; |
95 | } | 104 | } |
96 | 105 | ||
97 | /** | 106 | /* |
98 | * ieee80211_add_rx_radiotap_header - add radiotap header | 107 | * ieee80211_add_rx_radiotap_header - add radiotap header |
99 | * | 108 | * |
100 | * add a radiotap header containing all the fields which the hardware provided. | 109 | * add a radiotap header containing all the fields which the hardware provided. |
@@ -215,6 +224,37 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
215 | pos++; | 224 | pos++; |
216 | *pos++ = status->rate_idx; | 225 | *pos++ = status->rate_idx; |
217 | } | 226 | } |
227 | |||
228 | if (status->flag & RX_FLAG_AMPDU_DETAILS) { | ||
229 | u16 flags = 0; | ||
230 | |||
231 | /* ensure 4 byte alignment */ | ||
232 | while ((pos - (u8 *)rthdr) & 3) | ||
233 | pos++; | ||
234 | rthdr->it_present |= | ||
235 | cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); | ||
236 | put_unaligned_le32(status->ampdu_reference, pos); | ||
237 | pos += 4; | ||
238 | if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN) | ||
239 | flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN; | ||
240 | if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN) | ||
241 | flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN; | ||
242 | if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN) | ||
243 | flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN; | ||
244 | if (status->flag & RX_FLAG_AMPDU_IS_LAST) | ||
245 | flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST; | ||
246 | if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR) | ||
247 | flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR; | ||
248 | if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) | ||
249 | flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN; | ||
250 | put_unaligned_le16(flags, pos); | ||
251 | pos += 2; | ||
252 | if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) | ||
253 | *pos++ = status->ampdu_delimiter_crc; | ||
254 | else | ||
255 | *pos++ = 0; | ||
256 | *pos++ = 0; | ||
257 | } | ||
218 | } | 258 | } |
219 | 259 | ||
220 | /* | 260 | /* |
@@ -2268,7 +2308,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2268 | 2308 | ||
2269 | goto queue; | 2309 | goto queue; |
2270 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 2310 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
2271 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | 2311 | if (status->band != IEEE80211_BAND_5GHZ) |
2272 | break; | 2312 | break; |
2273 | 2313 | ||
2274 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2314 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
@@ -2772,8 +2812,7 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2772 | if (!bssid) { | 2812 | if (!bssid) { |
2773 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) | 2813 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) |
2774 | return 0; | 2814 | return 0; |
2775 | } else if (!ieee80211_bssid_match(bssid, | 2815 | } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { |
2776 | sdata->vif.addr)) { | ||
2777 | /* | 2816 | /* |
2778 | * Accept public action frames even when the | 2817 | * Accept public action frames even when the |
2779 | * BSSID doesn't match, this is used for P2P | 2818 | * BSSID doesn't match, this is used for P2P |
@@ -2793,9 +2832,18 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2793 | if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) | 2832 | if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) |
2794 | return 0; | 2833 | return 0; |
2795 | break; | 2834 | break; |
2835 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2836 | if (!ieee80211_is_public_action(hdr, skb->len) && | ||
2837 | !ieee80211_is_probe_req(hdr->frame_control) && | ||
2838 | !ieee80211_is_probe_resp(hdr->frame_control) && | ||
2839 | !ieee80211_is_beacon(hdr->frame_control)) | ||
2840 | return 0; | ||
2841 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) | ||
2842 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | ||
2843 | break; | ||
2796 | default: | 2844 | default: |
2797 | /* should never get here */ | 2845 | /* should never get here */ |
2798 | WARN_ON(1); | 2846 | WARN_ON_ONCE(1); |
2799 | break; | 2847 | break; |
2800 | } | 2848 | } |
2801 | 2849 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 839dd9737989..c4cdbde24fd3 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -407,7 +407,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
407 | enum ieee80211_band band = local->hw.conf.channel->band; | 407 | enum ieee80211_band band = local->hw.conf.channel->band; |
408 | 408 | ||
409 | sdata = rcu_dereference_protected(local->scan_sdata, | 409 | sdata = rcu_dereference_protected(local->scan_sdata, |
410 | lockdep_is_held(&local->mtx));; | 410 | lockdep_is_held(&local->mtx)); |
411 | 411 | ||
412 | for (i = 0; i < local->scan_req->n_ssids; i++) | 412 | for (i = 0; i < local->scan_req->n_ssids; i++) |
413 | ieee80211_send_probe_req( | 413 | ieee80211_send_probe_req( |
@@ -416,7 +416,8 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
416 | local->scan_req->ssids[i].ssid_len, | 416 | local->scan_req->ssids[i].ssid_len, |
417 | local->scan_req->ie, local->scan_req->ie_len, | 417 | local->scan_req->ie, local->scan_req->ie_len, |
418 | local->scan_req->rates[band], false, | 418 | local->scan_req->rates[band], false, |
419 | local->scan_req->no_cck); | 419 | local->scan_req->no_cck, |
420 | local->hw.conf.channel); | ||
420 | 421 | ||
421 | /* | 422 | /* |
422 | * After sending probe requests, wait for probe responses | 423 | * After sending probe requests, wait for probe responses |
@@ -479,11 +480,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
479 | if (local->ops->hw_scan) { | 480 | if (local->ops->hw_scan) { |
480 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 481 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
481 | } else if ((req->n_channels == 1) && | 482 | } else if ((req->n_channels == 1) && |
482 | (req->channels[0]->center_freq == | 483 | (req->channels[0] == local->oper_channel)) { |
483 | local->hw.conf.channel->center_freq)) { | 484 | /* |
484 | 485 | * If we are scanning only on the operating channel | |
485 | /* If we are scanning only on the current channel, then | 486 | * then we do not need to stop normal activities |
486 | * we do not need to stop normal activities | ||
487 | */ | 487 | */ |
488 | unsigned long next_delay; | 488 | unsigned long next_delay; |
489 | 489 | ||
@@ -917,6 +917,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
917 | struct cfg80211_sched_scan_request *req) | 917 | struct cfg80211_sched_scan_request *req) |
918 | { | 918 | { |
919 | struct ieee80211_local *local = sdata->local; | 919 | struct ieee80211_local *local = sdata->local; |
920 | struct ieee80211_sched_scan_ies sched_scan_ies; | ||
920 | int ret, i; | 921 | int ret, i; |
921 | 922 | ||
922 | mutex_lock(&local->mtx); | 923 | mutex_lock(&local->mtx); |
@@ -935,33 +936,28 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
935 | if (!local->hw.wiphy->bands[i]) | 936 | if (!local->hw.wiphy->bands[i]) |
936 | continue; | 937 | continue; |
937 | 938 | ||
938 | local->sched_scan_ies.ie[i] = kzalloc(2 + | 939 | sched_scan_ies.ie[i] = kzalloc(2 + IEEE80211_MAX_SSID_LEN + |
939 | IEEE80211_MAX_SSID_LEN + | 940 | local->scan_ies_len + |
940 | local->scan_ies_len + | 941 | req->ie_len, |
941 | req->ie_len, | 942 | GFP_KERNEL); |
942 | GFP_KERNEL); | 943 | if (!sched_scan_ies.ie[i]) { |
943 | if (!local->sched_scan_ies.ie[i]) { | ||
944 | ret = -ENOMEM; | 944 | ret = -ENOMEM; |
945 | goto out_free; | 945 | goto out_free; |
946 | } | 946 | } |
947 | 947 | ||
948 | local->sched_scan_ies.len[i] = | 948 | sched_scan_ies.len[i] = |
949 | ieee80211_build_preq_ies(local, | 949 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], |
950 | local->sched_scan_ies.ie[i], | ||
951 | req->ie, req->ie_len, i, | 950 | req->ie, req->ie_len, i, |
952 | (u32) -1, 0); | 951 | (u32) -1, 0); |
953 | } | 952 | } |
954 | 953 | ||
955 | ret = drv_sched_scan_start(local, sdata, req, | 954 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
956 | &local->sched_scan_ies); | 955 | if (ret == 0) |
957 | if (ret == 0) { | ||
958 | rcu_assign_pointer(local->sched_scan_sdata, sdata); | 956 | rcu_assign_pointer(local->sched_scan_sdata, sdata); |
959 | goto out; | ||
960 | } | ||
961 | 957 | ||
962 | out_free: | 958 | out_free: |
963 | while (i > 0) | 959 | while (i > 0) |
964 | kfree(local->sched_scan_ies.ie[--i]); | 960 | kfree(sched_scan_ies.ie[--i]); |
965 | out: | 961 | out: |
966 | mutex_unlock(&local->mtx); | 962 | mutex_unlock(&local->mtx); |
967 | return ret; | 963 | return ret; |
@@ -970,7 +966,7 @@ out: | |||
970 | int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | 966 | int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) |
971 | { | 967 | { |
972 | struct ieee80211_local *local = sdata->local; | 968 | struct ieee80211_local *local = sdata->local; |
973 | int ret = 0, i; | 969 | int ret = 0; |
974 | 970 | ||
975 | mutex_lock(&local->mtx); | 971 | mutex_lock(&local->mtx); |
976 | 972 | ||
@@ -979,12 +975,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | |||
979 | goto out; | 975 | goto out; |
980 | } | 976 | } |
981 | 977 | ||
982 | if (rcu_access_pointer(local->sched_scan_sdata)) { | 978 | if (rcu_access_pointer(local->sched_scan_sdata)) |
983 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | ||
984 | kfree(local->sched_scan_ies.ie[i]); | ||
985 | |||
986 | drv_sched_scan_stop(local, sdata); | 979 | drv_sched_scan_stop(local, sdata); |
987 | } | 980 | |
988 | out: | 981 | out: |
989 | mutex_unlock(&local->mtx); | 982 | mutex_unlock(&local->mtx); |
990 | 983 | ||
@@ -1006,7 +999,6 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) | |||
1006 | struct ieee80211_local *local = | 999 | struct ieee80211_local *local = |
1007 | container_of(work, struct ieee80211_local, | 1000 | container_of(work, struct ieee80211_local, |
1008 | sched_scan_stopped_work); | 1001 | sched_scan_stopped_work); |
1009 | int i; | ||
1010 | 1002 | ||
1011 | mutex_lock(&local->mtx); | 1003 | mutex_lock(&local->mtx); |
1012 | 1004 | ||
@@ -1015,9 +1007,6 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) | |||
1015 | return; | 1007 | return; |
1016 | } | 1008 | } |
1017 | 1009 | ||
1018 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | ||
1019 | kfree(local->sched_scan_ies.ie[i]); | ||
1020 | |||
1021 | rcu_assign_pointer(local->sched_scan_sdata, NULL); | 1010 | rcu_assign_pointer(local->sched_scan_sdata, NULL); |
1022 | 1011 | ||
1023 | mutex_unlock(&local->mtx); | 1012 | mutex_unlock(&local->mtx); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 06fa75ceb025..797dd36a220d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -91,6 +91,70 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
91 | return -ENOENT; | 91 | return -ENOENT; |
92 | } | 92 | } |
93 | 93 | ||
94 | static void free_sta_work(struct work_struct *wk) | ||
95 | { | ||
96 | struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk); | ||
97 | int ac, i; | ||
98 | struct tid_ampdu_tx *tid_tx; | ||
99 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
100 | struct ieee80211_local *local = sdata->local; | ||
101 | |||
102 | /* | ||
103 | * At this point, when being called as call_rcu callback, | ||
104 | * neither mac80211 nor the driver can reference this | ||
105 | * sta struct any more except by still existing timers | ||
106 | * associated with this station that we clean up below. | ||
107 | */ | ||
108 | |||
109 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | ||
110 | BUG_ON(!sdata->bss); | ||
111 | |||
112 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
113 | |||
114 | atomic_dec(&sdata->bss->num_sta_ps); | ||
115 | sta_info_recalc_tim(sta); | ||
116 | } | ||
117 | |||
118 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
119 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); | ||
120 | __skb_queue_purge(&sta->ps_tx_buf[ac]); | ||
121 | __skb_queue_purge(&sta->tx_filtered[ac]); | ||
122 | } | ||
123 | |||
124 | #ifdef CONFIG_MAC80211_MESH | ||
125 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
126 | mesh_accept_plinks_update(sdata); | ||
127 | mesh_plink_deactivate(sta); | ||
128 | del_timer_sync(&sta->plink_timer); | ||
129 | } | ||
130 | #endif | ||
131 | |||
132 | cancel_work_sync(&sta->drv_unblock_wk); | ||
133 | |||
134 | /* | ||
135 | * Destroy aggregation state here. It would be nice to wait for the | ||
136 | * driver to finish aggregation stop and then clean up, but for now | ||
137 | * drivers have to handle aggregation stop being requested, followed | ||
138 | * directly by station destruction. | ||
139 | */ | ||
140 | for (i = 0; i < STA_TID_NUM; i++) { | ||
141 | tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); | ||
142 | if (!tid_tx) | ||
143 | continue; | ||
144 | __skb_queue_purge(&tid_tx->pending); | ||
145 | kfree(tid_tx); | ||
146 | } | ||
147 | |||
148 | sta_info_free(local, sta); | ||
149 | } | ||
150 | |||
151 | static void free_sta_rcu(struct rcu_head *h) | ||
152 | { | ||
153 | struct sta_info *sta = container_of(h, struct sta_info, rcu_head); | ||
154 | |||
155 | ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk); | ||
156 | } | ||
157 | |||
94 | /* protected by RCU */ | 158 | /* protected by RCU */ |
95 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | 159 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
96 | const u8 *addr) | 160 | const u8 *addr) |
@@ -241,6 +305,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
241 | 305 | ||
242 | spin_lock_init(&sta->lock); | 306 | spin_lock_init(&sta->lock); |
243 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | 307 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); |
308 | INIT_WORK(&sta->free_sta_wk, free_sta_work); | ||
244 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | 309 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); |
245 | mutex_init(&sta->ampdu_mlme.mtx); | 310 | mutex_init(&sta->ampdu_mlme.mtx); |
246 | 311 | ||
@@ -654,8 +719,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
654 | { | 719 | { |
655 | struct ieee80211_local *local; | 720 | struct ieee80211_local *local; |
656 | struct ieee80211_sub_if_data *sdata; | 721 | struct ieee80211_sub_if_data *sdata; |
657 | int ret, i, ac; | 722 | int ret, i; |
658 | struct tid_ampdu_tx *tid_tx; | ||
659 | 723 | ||
660 | might_sleep(); | 724 | might_sleep(); |
661 | 725 | ||
@@ -674,7 +738,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
674 | * will be sufficient. | 738 | * will be sufficient. |
675 | */ | 739 | */ |
676 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | 740 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
677 | ieee80211_sta_tear_down_BA_sessions(sta, true); | 741 | ieee80211_sta_tear_down_BA_sessions(sta, false); |
678 | 742 | ||
679 | ret = sta_info_hash_del(local, sta); | 743 | ret = sta_info_hash_del(local, sta); |
680 | if (ret) | 744 | if (ret) |
@@ -711,65 +775,14 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
711 | WARN_ON_ONCE(ret != 0); | 775 | WARN_ON_ONCE(ret != 0); |
712 | } | 776 | } |
713 | 777 | ||
714 | /* | ||
715 | * At this point, after we wait for an RCU grace period, | ||
716 | * neither mac80211 nor the driver can reference this | ||
717 | * sta struct any more except by still existing timers | ||
718 | * associated with this station that we clean up below. | ||
719 | */ | ||
720 | synchronize_rcu(); | ||
721 | |||
722 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | ||
723 | BUG_ON(!sdata->bss); | ||
724 | |||
725 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
726 | |||
727 | atomic_dec(&sdata->bss->num_sta_ps); | ||
728 | sta_info_recalc_tim(sta); | ||
729 | } | ||
730 | |||
731 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
732 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); | ||
733 | __skb_queue_purge(&sta->ps_tx_buf[ac]); | ||
734 | __skb_queue_purge(&sta->tx_filtered[ac]); | ||
735 | } | ||
736 | |||
737 | #ifdef CONFIG_MAC80211_MESH | ||
738 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
739 | mesh_accept_plinks_update(sdata); | ||
740 | #endif | ||
741 | |||
742 | sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr); | 778 | sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr); |
743 | 779 | ||
744 | cancel_work_sync(&sta->drv_unblock_wk); | ||
745 | |||
746 | cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL); | 780 | cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL); |
747 | 781 | ||
748 | rate_control_remove_sta_debugfs(sta); | 782 | rate_control_remove_sta_debugfs(sta); |
749 | ieee80211_sta_debugfs_remove(sta); | 783 | ieee80211_sta_debugfs_remove(sta); |
750 | 784 | ||
751 | #ifdef CONFIG_MAC80211_MESH | 785 | call_rcu(&sta->rcu_head, free_sta_rcu); |
752 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { | ||
753 | mesh_plink_deactivate(sta); | ||
754 | del_timer_sync(&sta->plink_timer); | ||
755 | } | ||
756 | #endif | ||
757 | |||
758 | /* | ||
759 | * Destroy aggregation state here. It would be nice to wait for the | ||
760 | * driver to finish aggregation stop and then clean up, but for now | ||
761 | * drivers have to handle aggregation stop being requested, followed | ||
762 | * directly by station destruction. | ||
763 | */ | ||
764 | for (i = 0; i < STA_TID_NUM; i++) { | ||
765 | tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); | ||
766 | if (!tid_tx) | ||
767 | continue; | ||
768 | __skb_queue_purge(&tid_tx->pending); | ||
769 | kfree(tid_tx); | ||
770 | } | ||
771 | |||
772 | sta_info_free(local, sta); | ||
773 | 786 | ||
774 | return 0; | 787 | return 0; |
775 | } | 788 | } |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index a470e1123a55..c88f161f8118 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -287,6 +287,7 @@ struct sta_ampdu_mlme { | |||
287 | struct sta_info { | 287 | struct sta_info { |
288 | /* General information, mostly static */ | 288 | /* General information, mostly static */ |
289 | struct list_head list; | 289 | struct list_head list; |
290 | struct rcu_head rcu_head; | ||
290 | struct sta_info __rcu *hnext; | 291 | struct sta_info __rcu *hnext; |
291 | struct ieee80211_local *local; | 292 | struct ieee80211_local *local; |
292 | struct ieee80211_sub_if_data *sdata; | 293 | struct ieee80211_sub_if_data *sdata; |
@@ -297,6 +298,7 @@ struct sta_info { | |||
297 | spinlock_t lock; | 298 | spinlock_t lock; |
298 | 299 | ||
299 | struct work_struct drv_unblock_wk; | 300 | struct work_struct drv_unblock_wk; |
301 | struct work_struct free_sta_wk; | ||
300 | 302 | ||
301 | u16 listen_interval; | 303 | u16 listen_interval; |
302 | 304 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 8cd72914cdaf..2ce89732d0f2 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -517,21 +517,41 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
517 | 517 | ||
518 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { | 518 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { |
519 | u64 cookie = (unsigned long)skb; | 519 | u64 cookie = (unsigned long)skb; |
520 | bool found = false; | ||
521 | |||
520 | acked = info->flags & IEEE80211_TX_STAT_ACK; | 522 | acked = info->flags & IEEE80211_TX_STAT_ACK; |
521 | 523 | ||
522 | /* | 524 | rcu_read_lock(); |
523 | * TODO: When we have non-netdev frame TX, | 525 | |
524 | * we cannot use skb->dev->ieee80211_ptr | 526 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
525 | */ | 527 | if (!sdata->dev) |
528 | continue; | ||
529 | |||
530 | if (skb->dev != sdata->dev) | ||
531 | continue; | ||
526 | 532 | ||
527 | if (ieee80211_is_nullfunc(hdr->frame_control) || | 533 | found = true; |
528 | ieee80211_is_qos_nullfunc(hdr->frame_control)) | 534 | break; |
529 | cfg80211_probe_status(skb->dev, hdr->addr1, | 535 | } |
536 | |||
537 | if (!skb->dev) { | ||
538 | sdata = rcu_dereference(local->p2p_sdata); | ||
539 | if (sdata) | ||
540 | found = true; | ||
541 | } | ||
542 | |||
543 | if (!found) | ||
544 | skb->dev = NULL; | ||
545 | else if (ieee80211_is_nullfunc(hdr->frame_control) || | ||
546 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { | ||
547 | cfg80211_probe_status(sdata->dev, hdr->addr1, | ||
530 | cookie, acked, GFP_ATOMIC); | 548 | cookie, acked, GFP_ATOMIC); |
531 | else | 549 | } else { |
532 | cfg80211_mgmt_tx_status( | 550 | cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data, |
533 | skb->dev->ieee80211_ptr, cookie, skb->data, | 551 | skb->len, acked, GFP_ATOMIC); |
534 | skb->len, acked, GFP_ATOMIC); | 552 | } |
553 | |||
554 | rcu_read_unlock(); | ||
535 | } | 555 | } |
536 | 556 | ||
537 | if (unlikely(info->ack_frame_id)) { | 557 | if (unlikely(info->ack_frame_id)) { |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index c6d33b55b2df..18d9c8a52e9e 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -24,7 +24,7 @@ | |||
24 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 24 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
25 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ | 25 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ |
26 | __entry->p2p = sdata->vif.p2p; \ | 26 | __entry->p2p = sdata->vif.p2p; \ |
27 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 27 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : sdata->name) |
28 | #define VIF_PR_FMT " vif:%s(%d%s)" | 28 | #define VIF_PR_FMT " vif:%s(%d%s)" |
29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" | 29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
30 | 30 | ||
@@ -274,9 +274,12 @@ TRACE_EVENT(drv_config, | |||
274 | __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout; | 274 | __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout; |
275 | __entry->max_sleep_period = local->hw.conf.max_sleep_period; | 275 | __entry->max_sleep_period = local->hw.conf.max_sleep_period; |
276 | __entry->listen_interval = local->hw.conf.listen_interval; | 276 | __entry->listen_interval = local->hw.conf.listen_interval; |
277 | __entry->long_frame_max_tx_count = local->hw.conf.long_frame_max_tx_count; | 277 | __entry->long_frame_max_tx_count = |
278 | __entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count; | 278 | local->hw.conf.long_frame_max_tx_count; |
279 | __entry->center_freq = local->hw.conf.channel->center_freq; | 279 | __entry->short_frame_max_tx_count = |
280 | local->hw.conf.short_frame_max_tx_count; | ||
281 | __entry->center_freq = local->hw.conf.channel ? | ||
282 | local->hw.conf.channel->center_freq : 0; | ||
280 | __entry->channel_type = local->hw.conf.channel_type; | 283 | __entry->channel_type = local->hw.conf.channel_type; |
281 | __entry->smps = local->hw.conf.smps_mode; | 284 | __entry->smps = local->hw.conf.smps_mode; |
282 | ), | 285 | ), |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c5e8c9c31f76..e0e0d1d0e830 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -55,7 +55,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
55 | if (WARN_ON_ONCE(info->control.rates[0].idx < 0)) | 55 | if (WARN_ON_ONCE(info->control.rates[0].idx < 0)) |
56 | return 0; | 56 | return 0; |
57 | 57 | ||
58 | sband = local->hw.wiphy->bands[tx->channel->band]; | 58 | sband = local->hw.wiphy->bands[info->band]; |
59 | txrate = &sband->bitrates[info->control.rates[0].idx]; | 59 | txrate = &sband->bitrates[info->control.rates[0].idx]; |
60 | 60 | ||
61 | erp = txrate->flags & IEEE80211_RATE_ERP_G; | 61 | erp = txrate->flags & IEEE80211_RATE_ERP_G; |
@@ -580,7 +580,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
580 | tx->key = NULL; | 580 | tx->key = NULL; |
581 | else | 581 | else |
582 | skip_hw = (tx->key->conf.flags & | 582 | skip_hw = (tx->key->conf.flags & |
583 | IEEE80211_KEY_FLAG_SW_MGMT) && | 583 | IEEE80211_KEY_FLAG_SW_MGMT_TX) && |
584 | ieee80211_is_mgmt(hdr->frame_control); | 584 | ieee80211_is_mgmt(hdr->frame_control); |
585 | break; | 585 | break; |
586 | case WLAN_CIPHER_SUITE_AES_CMAC: | 586 | case WLAN_CIPHER_SUITE_AES_CMAC: |
@@ -615,7 +615,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
615 | 615 | ||
616 | memset(&txrc, 0, sizeof(txrc)); | 616 | memset(&txrc, 0, sizeof(txrc)); |
617 | 617 | ||
618 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 618 | sband = tx->local->hw.wiphy->bands[info->band]; |
619 | 619 | ||
620 | len = min_t(u32, tx->skb->len + FCS_LEN, | 620 | len = min_t(u32, tx->skb->len + FCS_LEN, |
621 | tx->local->hw.wiphy->frag_threshold); | 621 | tx->local->hw.wiphy->frag_threshold); |
@@ -626,13 +626,13 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
626 | txrc.bss_conf = &tx->sdata->vif.bss_conf; | 626 | txrc.bss_conf = &tx->sdata->vif.bss_conf; |
627 | txrc.skb = tx->skb; | 627 | txrc.skb = tx->skb; |
628 | txrc.reported_rate.idx = -1; | 628 | txrc.reported_rate.idx = -1; |
629 | txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[tx->channel->band]; | 629 | txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band]; |
630 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) | 630 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) |
631 | txrc.max_rate_idx = -1; | 631 | txrc.max_rate_idx = -1; |
632 | else | 632 | else |
633 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 633 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
634 | memcpy(txrc.rate_idx_mcs_mask, | 634 | memcpy(txrc.rate_idx_mcs_mask, |
635 | tx->sdata->rc_rateidx_mcs_mask[tx->channel->band], | 635 | tx->sdata->rc_rateidx_mcs_mask[info->band], |
636 | sizeof(txrc.rate_idx_mcs_mask)); | 636 | sizeof(txrc.rate_idx_mcs_mask)); |
637 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || | 637 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || |
638 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || | 638 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || |
@@ -667,7 +667,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
667 | "scanning and associated. Target station: " | 667 | "scanning and associated. Target station: " |
668 | "%pM on %d GHz band\n", | 668 | "%pM on %d GHz band\n", |
669 | tx->sdata->name, hdr->addr1, | 669 | tx->sdata->name, hdr->addr1, |
670 | tx->channel->band ? 5 : 2)) | 670 | info->band ? 5 : 2)) |
671 | return TX_DROP; | 671 | return TX_DROP; |
672 | 672 | ||
673 | /* | 673 | /* |
@@ -1131,7 +1131,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1131 | tx->skb = skb; | 1131 | tx->skb = skb; |
1132 | tx->local = local; | 1132 | tx->local = local; |
1133 | tx->sdata = sdata; | 1133 | tx->sdata = sdata; |
1134 | tx->channel = local->hw.conf.channel; | ||
1135 | __skb_queue_head_init(&tx->skbs); | 1134 | __skb_queue_head_init(&tx->skbs); |
1136 | 1135 | ||
1137 | /* | 1136 | /* |
@@ -1204,6 +1203,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1204 | struct sk_buff_head *skbs, | 1203 | struct sk_buff_head *skbs, |
1205 | bool txpending) | 1204 | bool txpending) |
1206 | { | 1205 | { |
1206 | struct ieee80211_tx_control control; | ||
1207 | struct sk_buff *skb, *tmp; | 1207 | struct sk_buff *skb, *tmp; |
1208 | unsigned long flags; | 1208 | unsigned long flags; |
1209 | 1209 | ||
@@ -1240,10 +1240,10 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1240 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 1240 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
1241 | 1241 | ||
1242 | info->control.vif = vif; | 1242 | info->control.vif = vif; |
1243 | info->control.sta = sta; | 1243 | control.sta = sta; |
1244 | 1244 | ||
1245 | __skb_unlink(skb, skbs); | 1245 | __skb_unlink(skb, skbs); |
1246 | drv_tx(local, skb); | 1246 | drv_tx(local, &control, skb); |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | return true; | 1249 | return true; |
@@ -1399,8 +1399,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1399 | goto out; | 1399 | goto out; |
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | tx.channel = local->hw.conf.channel; | 1402 | info->band = local->hw.conf.channel->band; |
1403 | info->band = tx.channel->band; | ||
1404 | 1403 | ||
1405 | /* set up hw_queue value early */ | 1404 | /* set up hw_queue value early */ |
1406 | if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || | 1405 | if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || |
@@ -1720,7 +1719,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1720 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1719 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1721 | struct ieee80211_local *local = sdata->local; | 1720 | struct ieee80211_local *local = sdata->local; |
1722 | struct ieee80211_tx_info *info; | 1721 | struct ieee80211_tx_info *info; |
1723 | int ret = NETDEV_TX_BUSY, head_need; | 1722 | int head_need; |
1724 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1723 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1725 | __le16 fc; | 1724 | __le16 fc; |
1726 | struct ieee80211_hdr hdr; | 1725 | struct ieee80211_hdr hdr; |
@@ -1736,10 +1735,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1736 | u32 info_flags = 0; | 1735 | u32 info_flags = 0; |
1737 | u16 info_id = 0; | 1736 | u16 info_id = 0; |
1738 | 1737 | ||
1739 | if (unlikely(skb->len < ETH_HLEN)) { | 1738 | if (unlikely(skb->len < ETH_HLEN)) |
1740 | ret = NETDEV_TX_OK; | ||
1741 | goto fail; | 1739 | goto fail; |
1742 | } | ||
1743 | 1740 | ||
1744 | /* convert Ethernet header to proper 802.11 header (based on | 1741 | /* convert Ethernet header to proper 802.11 header (based on |
1745 | * operation mode) */ | 1742 | * operation mode) */ |
@@ -1787,7 +1784,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1787 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1784 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1788 | /* Do not send frames with mesh_ttl == 0 */ | 1785 | /* Do not send frames with mesh_ttl == 0 */ |
1789 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1786 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1790 | ret = NETDEV_TX_OK; | ||
1791 | goto fail; | 1787 | goto fail; |
1792 | } | 1788 | } |
1793 | rcu_read_lock(); | 1789 | rcu_read_lock(); |
@@ -1874,10 +1870,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1874 | 1870 | ||
1875 | if (tdls_direct) { | 1871 | if (tdls_direct) { |
1876 | /* link during setup - throw out frames to peer */ | 1872 | /* link during setup - throw out frames to peer */ |
1877 | if (!tdls_auth) { | 1873 | if (!tdls_auth) |
1878 | ret = NETDEV_TX_OK; | ||
1879 | goto fail; | 1874 | goto fail; |
1880 | } | ||
1881 | 1875 | ||
1882 | /* DA SA BSSID */ | 1876 | /* DA SA BSSID */ |
1883 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1877 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
@@ -1911,7 +1905,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1911 | hdrlen = 24; | 1905 | hdrlen = 24; |
1912 | break; | 1906 | break; |
1913 | default: | 1907 | default: |
1914 | ret = NETDEV_TX_OK; | ||
1915 | goto fail; | 1908 | goto fail; |
1916 | } | 1909 | } |
1917 | 1910 | ||
@@ -1956,7 +1949,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1956 | 1949 | ||
1957 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); | 1950 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); |
1958 | 1951 | ||
1959 | ret = NETDEV_TX_OK; | ||
1960 | goto fail; | 1952 | goto fail; |
1961 | } | 1953 | } |
1962 | 1954 | ||
@@ -2011,10 +2003,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2011 | skb = skb_clone(skb, GFP_ATOMIC); | 2003 | skb = skb_clone(skb, GFP_ATOMIC); |
2012 | kfree_skb(tmp_skb); | 2004 | kfree_skb(tmp_skb); |
2013 | 2005 | ||
2014 | if (!skb) { | 2006 | if (!skb) |
2015 | ret = NETDEV_TX_OK; | ||
2016 | goto fail; | 2007 | goto fail; |
2017 | } | ||
2018 | } | 2008 | } |
2019 | 2009 | ||
2020 | hdr.frame_control = fc; | 2010 | hdr.frame_control = fc; |
@@ -2117,10 +2107,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2117 | return NETDEV_TX_OK; | 2107 | return NETDEV_TX_OK; |
2118 | 2108 | ||
2119 | fail: | 2109 | fail: |
2120 | if (ret == NETDEV_TX_OK) | 2110 | dev_kfree_skb(skb); |
2121 | dev_kfree_skb(skb); | 2111 | return NETDEV_TX_OK; |
2122 | |||
2123 | return ret; | ||
2124 | } | 2112 | } |
2125 | 2113 | ||
2126 | 2114 | ||
@@ -2295,12 +2283,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2295 | struct ieee80211_sub_if_data *sdata = NULL; | 2283 | struct ieee80211_sub_if_data *sdata = NULL; |
2296 | struct ieee80211_if_ap *ap = NULL; | 2284 | struct ieee80211_if_ap *ap = NULL; |
2297 | struct beacon_data *beacon; | 2285 | struct beacon_data *beacon; |
2298 | struct ieee80211_supported_band *sband; | 2286 | enum ieee80211_band band = local->oper_channel->band; |
2299 | enum ieee80211_band band = local->hw.conf.channel->band; | ||
2300 | struct ieee80211_tx_rate_control txrc; | 2287 | struct ieee80211_tx_rate_control txrc; |
2301 | 2288 | ||
2302 | sband = local->hw.wiphy->bands[band]; | ||
2303 | |||
2304 | rcu_read_lock(); | 2289 | rcu_read_lock(); |
2305 | 2290 | ||
2306 | sdata = vif_to_sdata(vif); | 2291 | sdata = vif_to_sdata(vif); |
@@ -2410,7 +2395,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2410 | memset(mgmt, 0, hdr_len); | 2395 | memset(mgmt, 0, hdr_len); |
2411 | mgmt->frame_control = | 2396 | mgmt->frame_control = |
2412 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); | 2397 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
2413 | memset(mgmt->da, 0xff, ETH_ALEN); | 2398 | eth_broadcast_addr(mgmt->da); |
2414 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 2399 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
2415 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 2400 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
2416 | mgmt->u.beacon.beacon_int = | 2401 | mgmt->u.beacon.beacon_int = |
@@ -2422,9 +2407,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2422 | *pos++ = WLAN_EID_SSID; | 2407 | *pos++ = WLAN_EID_SSID; |
2423 | *pos++ = 0x0; | 2408 | *pos++ = 0x0; |
2424 | 2409 | ||
2425 | if (ieee80211_add_srates_ie(sdata, skb, true) || | 2410 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
2426 | mesh_add_ds_params_ie(skb, sdata) || | 2411 | mesh_add_ds_params_ie(skb, sdata) || |
2427 | ieee80211_add_ext_srates_ie(sdata, skb, true) || | 2412 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
2428 | mesh_add_rsn_ie(skb, sdata) || | 2413 | mesh_add_rsn_ie(skb, sdata) || |
2429 | mesh_add_ht_cap_ie(skb, sdata) || | 2414 | mesh_add_ht_cap_ie(skb, sdata) || |
2430 | mesh_add_ht_oper_ie(skb, sdata) || | 2415 | mesh_add_ht_oper_ie(skb, sdata) || |
@@ -2447,12 +2432,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2447 | 2432 | ||
2448 | memset(&txrc, 0, sizeof(txrc)); | 2433 | memset(&txrc, 0, sizeof(txrc)); |
2449 | txrc.hw = hw; | 2434 | txrc.hw = hw; |
2450 | txrc.sband = sband; | 2435 | txrc.sband = local->hw.wiphy->bands[band]; |
2451 | txrc.bss_conf = &sdata->vif.bss_conf; | 2436 | txrc.bss_conf = &sdata->vif.bss_conf; |
2452 | txrc.skb = skb; | 2437 | txrc.skb = skb; |
2453 | txrc.reported_rate.idx = -1; | 2438 | txrc.reported_rate.idx = -1; |
2454 | txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; | 2439 | txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; |
2455 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) | 2440 | if (txrc.rate_idx_mask == (1 << txrc.sband->n_bitrates) - 1) |
2456 | txrc.max_rate_idx = -1; | 2441 | txrc.max_rate_idx = -1; |
2457 | else | 2442 | else |
2458 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 2443 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
@@ -2476,7 +2461,8 @@ struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | |||
2476 | struct ieee80211_vif *vif) | 2461 | struct ieee80211_vif *vif) |
2477 | { | 2462 | { |
2478 | struct ieee80211_if_ap *ap = NULL; | 2463 | struct ieee80211_if_ap *ap = NULL; |
2479 | struct sk_buff *presp = NULL, *skb = NULL; | 2464 | struct sk_buff *skb = NULL; |
2465 | struct probe_resp *presp = NULL; | ||
2480 | struct ieee80211_hdr *hdr; | 2466 | struct ieee80211_hdr *hdr; |
2481 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 2467 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
2482 | 2468 | ||
@@ -2490,10 +2476,12 @@ struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | |||
2490 | if (!presp) | 2476 | if (!presp) |
2491 | goto out; | 2477 | goto out; |
2492 | 2478 | ||
2493 | skb = skb_copy(presp, GFP_ATOMIC); | 2479 | skb = dev_alloc_skb(presp->len); |
2494 | if (!skb) | 2480 | if (!skb) |
2495 | goto out; | 2481 | goto out; |
2496 | 2482 | ||
2483 | memcpy(skb_put(skb, presp->len), presp->data, presp->len); | ||
2484 | |||
2497 | hdr = (struct ieee80211_hdr *) skb->data; | 2485 | hdr = (struct ieee80211_hdr *) skb->data; |
2498 | memset(hdr->addr1, 0, sizeof(hdr->addr1)); | 2486 | memset(hdr->addr1, 0, sizeof(hdr->addr1)); |
2499 | 2487 | ||
@@ -2604,9 +2592,9 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | |||
2604 | memset(hdr, 0, sizeof(*hdr)); | 2592 | memset(hdr, 0, sizeof(*hdr)); |
2605 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 2593 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
2606 | IEEE80211_STYPE_PROBE_REQ); | 2594 | IEEE80211_STYPE_PROBE_REQ); |
2607 | memset(hdr->addr1, 0xff, ETH_ALEN); | 2595 | eth_broadcast_addr(hdr->addr1); |
2608 | memcpy(hdr->addr2, vif->addr, ETH_ALEN); | 2596 | memcpy(hdr->addr2, vif->addr, ETH_ALEN); |
2609 | memset(hdr->addr3, 0xff, ETH_ALEN); | 2597 | eth_broadcast_addr(hdr->addr3); |
2610 | 2598 | ||
2611 | pos = skb_put(skb, ie_ssid_len); | 2599 | pos = skb_put(skb, ie_ssid_len); |
2612 | *pos++ = WLAN_EID_SSID; | 2600 | *pos++ = WLAN_EID_SSID; |
@@ -2703,8 +2691,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2703 | info = IEEE80211_SKB_CB(skb); | 2691 | info = IEEE80211_SKB_CB(skb); |
2704 | 2692 | ||
2705 | tx.flags |= IEEE80211_TX_PS_BUFFERED; | 2693 | tx.flags |= IEEE80211_TX_PS_BUFFERED; |
2706 | tx.channel = local->hw.conf.channel; | 2694 | info->band = local->oper_channel->band; |
2707 | info->band = tx.channel->band; | ||
2708 | 2695 | ||
2709 | if (invoke_tx_handlers(&tx)) | 2696 | if (invoke_tx_handlers(&tx)) |
2710 | skb = NULL; | 2697 | skb = NULL; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 39b82fee4904..22ca35054dd0 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -276,6 +276,9 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) | |||
276 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 276 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
277 | int ac; | 277 | int ac; |
278 | 278 | ||
279 | if (!sdata->dev) | ||
280 | continue; | ||
281 | |||
279 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) | 282 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) |
280 | continue; | 283 | continue; |
281 | 284 | ||
@@ -364,6 +367,9 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
364 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 367 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
365 | int ac; | 368 | int ac; |
366 | 369 | ||
370 | if (!sdata->dev) | ||
371 | continue; | ||
372 | |||
367 | for (ac = 0; ac < n_acs; ac++) { | 373 | for (ac = 0; ac < n_acs; ac++) { |
368 | if (sdata->vif.hw_queue[ac] == queue || | 374 | if (sdata->vif.hw_queue[ac] == queue || |
369 | sdata->vif.cab_queue == queue) | 375 | sdata->vif.cab_queue == queue) |
@@ -768,8 +774,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
768 | elem_parse_failed = true; | 774 | elem_parse_failed = true; |
769 | break; | 775 | break; |
770 | case WLAN_EID_CHANNEL_SWITCH: | 776 | case WLAN_EID_CHANNEL_SWITCH: |
771 | elems->ch_switch_elem = pos; | 777 | if (elen != sizeof(struct ieee80211_channel_sw_ie)) { |
772 | elems->ch_switch_elem_len = elen; | 778 | elem_parse_failed = true; |
779 | break; | ||
780 | } | ||
781 | elems->ch_switch_ie = (void *)pos; | ||
773 | break; | 782 | break; |
774 | case WLAN_EID_QUIET: | 783 | case WLAN_EID_QUIET: |
775 | if (!elems->quiet_elem) { | 784 | if (!elems->quiet_elem) { |
@@ -783,8 +792,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
783 | elems->country_elem_len = elen; | 792 | elems->country_elem_len = elen; |
784 | break; | 793 | break; |
785 | case WLAN_EID_PWR_CONSTRAINT: | 794 | case WLAN_EID_PWR_CONSTRAINT: |
795 | if (elen != 1) { | ||
796 | elem_parse_failed = true; | ||
797 | break; | ||
798 | } | ||
786 | elems->pwr_constr_elem = pos; | 799 | elems->pwr_constr_elem = pos; |
787 | elems->pwr_constr_elem_len = elen; | ||
788 | break; | 800 | break; |
789 | case WLAN_EID_TIMEOUT_INTERVAL: | 801 | case WLAN_EID_TIMEOUT_INTERVAL: |
790 | elems->timeout_int = pos; | 802 | elems->timeout_int = pos; |
@@ -832,7 +844,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
832 | 844 | ||
833 | memset(&qparam, 0, sizeof(qparam)); | 845 | memset(&qparam, 0, sizeof(qparam)); |
834 | 846 | ||
835 | use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && | 847 | use_11b = (local->oper_channel->band == IEEE80211_BAND_2GHZ) && |
836 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); | 848 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); |
837 | 849 | ||
838 | /* | 850 | /* |
@@ -899,7 +911,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
899 | drv_conf_tx(local, sdata, ac, &qparam); | 911 | drv_conf_tx(local, sdata, ac, &qparam); |
900 | } | 912 | } |
901 | 913 | ||
902 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 914 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR && |
915 | sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) { | ||
903 | sdata->vif.bss_conf.qos = enable_qos; | 916 | sdata->vif.bss_conf.qos = enable_qos; |
904 | if (bss_notify) | 917 | if (bss_notify) |
905 | ieee80211_bss_info_change_notify(sdata, | 918 | ieee80211_bss_info_change_notify(sdata, |
@@ -919,7 +932,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
919 | if ((supp_rates[i] & 0x7f) * 5 > 110) | 932 | if ((supp_rates[i] & 0x7f) * 5 > 110) |
920 | have_higher_than_11mbit = 1; | 933 | have_higher_than_11mbit = 1; |
921 | 934 | ||
922 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 935 | if (local->oper_channel->band == IEEE80211_BAND_2GHZ && |
923 | have_higher_than_11mbit) | 936 | have_higher_than_11mbit) |
924 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 937 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
925 | else | 938 | else |
@@ -994,6 +1007,45 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
994 | ieee80211_tx_skb(sdata, skb); | 1007 | ieee80211_tx_skb(sdata, skb); |
995 | } | 1008 | } |
996 | 1009 | ||
1010 | void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | ||
1011 | const u8 *bssid, u16 stype, u16 reason, | ||
1012 | bool send_frame, u8 *frame_buf) | ||
1013 | { | ||
1014 | struct ieee80211_local *local = sdata->local; | ||
1015 | struct sk_buff *skb; | ||
1016 | struct ieee80211_mgmt *mgmt = (void *)frame_buf; | ||
1017 | |||
1018 | /* build frame */ | ||
1019 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); | ||
1020 | mgmt->duration = 0; /* initialize only */ | ||
1021 | mgmt->seq_ctrl = 0; /* initialize only */ | ||
1022 | memcpy(mgmt->da, bssid, ETH_ALEN); | ||
1023 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
1024 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | ||
1025 | /* u.deauth.reason_code == u.disassoc.reason_code */ | ||
1026 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); | ||
1027 | |||
1028 | if (send_frame) { | ||
1029 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
1030 | IEEE80211_DEAUTH_FRAME_LEN); | ||
1031 | if (!skb) | ||
1032 | return; | ||
1033 | |||
1034 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1035 | |||
1036 | /* copy in frame */ | ||
1037 | memcpy(skb_put(skb, IEEE80211_DEAUTH_FRAME_LEN), | ||
1038 | mgmt, IEEE80211_DEAUTH_FRAME_LEN); | ||
1039 | |||
1040 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | ||
1041 | !(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) | ||
1042 | IEEE80211_SKB_CB(skb)->flags |= | ||
1043 | IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1044 | |||
1045 | ieee80211_tx_skb(sdata, skb); | ||
1046 | } | ||
1047 | } | ||
1048 | |||
997 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1049 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
998 | const u8 *ie, size_t ie_len, | 1050 | const u8 *ie, size_t ie_len, |
999 | enum ieee80211_band band, u32 rate_mask, | 1051 | enum ieee80211_band band, u32 rate_mask, |
@@ -1100,6 +1152,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1100 | 1152 | ||
1101 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1153 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1102 | u8 *dst, u32 ratemask, | 1154 | u8 *dst, u32 ratemask, |
1155 | struct ieee80211_channel *chan, | ||
1103 | const u8 *ssid, size_t ssid_len, | 1156 | const u8 *ssid, size_t ssid_len, |
1104 | const u8 *ie, size_t ie_len, | 1157 | const u8 *ie, size_t ie_len, |
1105 | bool directed) | 1158 | bool directed) |
@@ -1109,7 +1162,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1109 | struct ieee80211_mgmt *mgmt; | 1162 | struct ieee80211_mgmt *mgmt; |
1110 | size_t buf_len; | 1163 | size_t buf_len; |
1111 | u8 *buf; | 1164 | u8 *buf; |
1112 | u8 chan; | 1165 | u8 chan_no; |
1113 | 1166 | ||
1114 | /* FIXME: come up with a proper value */ | 1167 | /* FIXME: come up with a proper value */ |
1115 | buf = kmalloc(200 + ie_len, GFP_KERNEL); | 1168 | buf = kmalloc(200 + ie_len, GFP_KERNEL); |
@@ -1122,14 +1175,12 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1122 | * badly-behaved APs don't respond when this parameter is included. | 1175 | * badly-behaved APs don't respond when this parameter is included. |
1123 | */ | 1176 | */ |
1124 | if (directed) | 1177 | if (directed) |
1125 | chan = 0; | 1178 | chan_no = 0; |
1126 | else | 1179 | else |
1127 | chan = ieee80211_frequency_to_channel( | 1180 | chan_no = ieee80211_frequency_to_channel(chan->center_freq); |
1128 | local->hw.conf.channel->center_freq); | ||
1129 | 1181 | ||
1130 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, | 1182 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, chan->band, |
1131 | local->hw.conf.channel->band, | 1183 | ratemask, chan_no); |
1132 | ratemask, chan); | ||
1133 | 1184 | ||
1134 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 1185 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
1135 | ssid, ssid_len, | 1186 | ssid, ssid_len, |
@@ -1154,11 +1205,13 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1154 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1205 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1155 | const u8 *ssid, size_t ssid_len, | 1206 | const u8 *ssid, size_t ssid_len, |
1156 | const u8 *ie, size_t ie_len, | 1207 | const u8 *ie, size_t ie_len, |
1157 | u32 ratemask, bool directed, bool no_cck) | 1208 | u32 ratemask, bool directed, bool no_cck, |
1209 | struct ieee80211_channel *channel) | ||
1158 | { | 1210 | { |
1159 | struct sk_buff *skb; | 1211 | struct sk_buff *skb; |
1160 | 1212 | ||
1161 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, | 1213 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, channel, |
1214 | ssid, ssid_len, | ||
1162 | ie, ie_len, directed); | 1215 | ie, ie_len, directed); |
1163 | if (skb) { | 1216 | if (skb) { |
1164 | if (no_cck) | 1217 | if (no_cck) |
@@ -1359,7 +1412,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1359 | switch (sdata->vif.type) { | 1412 | switch (sdata->vif.type) { |
1360 | case NL80211_IFTYPE_STATION: | 1413 | case NL80211_IFTYPE_STATION: |
1361 | changed |= BSS_CHANGED_ASSOC | | 1414 | changed |= BSS_CHANGED_ASSOC | |
1362 | BSS_CHANGED_ARP_FILTER; | 1415 | BSS_CHANGED_ARP_FILTER | |
1416 | BSS_CHANGED_PS; | ||
1363 | mutex_lock(&sdata->u.mgd.mtx); | 1417 | mutex_lock(&sdata->u.mgd.mtx); |
1364 | ieee80211_bss_info_change_notify(sdata, changed); | 1418 | ieee80211_bss_info_change_notify(sdata, changed); |
1365 | mutex_unlock(&sdata->u.mgd.mtx); | 1419 | mutex_unlock(&sdata->u.mgd.mtx); |
@@ -1385,6 +1439,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1385 | case NL80211_IFTYPE_MONITOR: | 1439 | case NL80211_IFTYPE_MONITOR: |
1386 | /* ignore virtual */ | 1440 | /* ignore virtual */ |
1387 | break; | 1441 | break; |
1442 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1443 | changed = BSS_CHANGED_IDLE; | ||
1444 | break; | ||
1388 | case NL80211_IFTYPE_UNSPECIFIED: | 1445 | case NL80211_IFTYPE_UNSPECIFIED: |
1389 | case NUM_NL80211_IFTYPES: | 1446 | case NUM_NL80211_IFTYPES: |
1390 | case NL80211_IFTYPE_P2P_CLIENT: | 1447 | case NL80211_IFTYPE_P2P_CLIENT: |
@@ -1549,14 +1606,13 @@ static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, | |||
1549 | return 0; | 1606 | return 0; |
1550 | } | 1607 | } |
1551 | 1608 | ||
1552 | /* must hold iflist_mtx */ | ||
1553 | void ieee80211_recalc_smps(struct ieee80211_local *local) | 1609 | void ieee80211_recalc_smps(struct ieee80211_local *local) |
1554 | { | 1610 | { |
1555 | struct ieee80211_sub_if_data *sdata; | 1611 | struct ieee80211_sub_if_data *sdata; |
1556 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; | 1612 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; |
1557 | int count = 0; | 1613 | int count = 0; |
1558 | 1614 | ||
1559 | lockdep_assert_held(&local->iflist_mtx); | 1615 | mutex_lock(&local->iflist_mtx); |
1560 | 1616 | ||
1561 | /* | 1617 | /* |
1562 | * This function could be improved to handle multiple | 1618 | * This function could be improved to handle multiple |
@@ -1571,6 +1627,8 @@ void ieee80211_recalc_smps(struct ieee80211_local *local) | |||
1571 | list_for_each_entry(sdata, &local->interfaces, list) { | 1627 | list_for_each_entry(sdata, &local->interfaces, list) { |
1572 | if (!ieee80211_sdata_running(sdata)) | 1628 | if (!ieee80211_sdata_running(sdata)) |
1573 | continue; | 1629 | continue; |
1630 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
1631 | continue; | ||
1574 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1632 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1575 | goto set; | 1633 | goto set; |
1576 | 1634 | ||
@@ -1583,12 +1641,14 @@ void ieee80211_recalc_smps(struct ieee80211_local *local) | |||
1583 | } | 1641 | } |
1584 | 1642 | ||
1585 | if (smps_mode == local->smps_mode) | 1643 | if (smps_mode == local->smps_mode) |
1586 | return; | 1644 | goto unlock; |
1587 | 1645 | ||
1588 | set: | 1646 | set: |
1589 | local->smps_mode = smps_mode; | 1647 | local->smps_mode = smps_mode; |
1590 | /* changed flag is auto-detected for this */ | 1648 | /* changed flag is auto-detected for this */ |
1591 | ieee80211_hw_config(local, 0); | 1649 | ieee80211_hw_config(local, 0); |
1650 | unlock: | ||
1651 | mutex_unlock(&local->iflist_mtx); | ||
1592 | } | 1652 | } |
1593 | 1653 | ||
1594 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) | 1654 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) |
@@ -1809,7 +1869,8 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) | |||
1809 | } | 1869 | } |
1810 | 1870 | ||
1811 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 1871 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
1812 | struct sk_buff *skb, bool need_basic) | 1872 | struct sk_buff *skb, bool need_basic, |
1873 | enum ieee80211_band band) | ||
1813 | { | 1874 | { |
1814 | struct ieee80211_local *local = sdata->local; | 1875 | struct ieee80211_local *local = sdata->local; |
1815 | struct ieee80211_supported_band *sband; | 1876 | struct ieee80211_supported_band *sband; |
@@ -1817,7 +1878,7 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1817 | u8 i, rates, *pos; | 1878 | u8 i, rates, *pos; |
1818 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 1879 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
1819 | 1880 | ||
1820 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1881 | sband = local->hw.wiphy->bands[band]; |
1821 | rates = sband->n_bitrates; | 1882 | rates = sband->n_bitrates; |
1822 | if (rates > 8) | 1883 | if (rates > 8) |
1823 | rates = 8; | 1884 | rates = 8; |
@@ -1840,7 +1901,8 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1840 | } | 1901 | } |
1841 | 1902 | ||
1842 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | 1903 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, |
1843 | struct sk_buff *skb, bool need_basic) | 1904 | struct sk_buff *skb, bool need_basic, |
1905 | enum ieee80211_band band) | ||
1844 | { | 1906 | { |
1845 | struct ieee80211_local *local = sdata->local; | 1907 | struct ieee80211_local *local = sdata->local; |
1846 | struct ieee80211_supported_band *sband; | 1908 | struct ieee80211_supported_band *sband; |
@@ -1848,7 +1910,7 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1848 | u8 i, exrates, *pos; | 1910 | u8 i, exrates, *pos; |
1849 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 1911 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
1850 | 1912 | ||
1851 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1913 | sband = local->hw.wiphy->bands[band]; |
1852 | exrates = sband->n_bitrates; | 1914 | exrates = sband->n_bitrates; |
1853 | if (exrates > 8) | 1915 | if (exrates > 8) |
1854 | exrates -= 8; | 1916 | exrates -= 8; |