aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-09-24 14:34:40 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-09-24 14:34:40 -0400
commit9b4e9e756541fd5d1223b323ed5a8a8545dd11cd (patch)
tree3eed3a2582532bd1fd890b58eadd472fcd2b1dc7 /net
parent7a5f799becc51c842ec1a3aeb8dd82651aea7036 (diff)
parent9385d04f2872057a2029901190391fe192b18693 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c34
-rw-r--r--net/mac80211/chan.c67
-rw-r--r--net/mac80211/ibss.c33
-rw-r--r--net/mac80211/ieee80211_i.h23
-rw-r--r--net/mac80211/iface.c15
-rw-r--r--net/mac80211/key.c2
-rw-r--r--net/mac80211/main.c10
-rw-r--r--net/mac80211/mesh_plink.c3
-rw-r--r--net/mac80211/mlme.c205
-rw-r--r--net/mac80211/offchannel.c3
-rw-r--r--net/mac80211/scan.c41
-rw-r--r--net/mac80211/sta_info.c121
-rw-r--r--net/mac80211/sta_info.h2
-rw-r--r--net/mac80211/status.c48
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/mac80211/util.c51
16 files changed, 415 insertions, 245 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 03fe6d1cff42..9bd56a744982 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -170,6 +170,38 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
170 } 170 }
171 } 171 }
172 172
173 switch (sdata->vif.type) {
174 case NL80211_IFTYPE_STATION:
175 if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED)
176 key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
177 break;
178 case NL80211_IFTYPE_AP:
179 case NL80211_IFTYPE_AP_VLAN:
180 /* Keys without a station are used for TX only */
181 if (key->sta && test_sta_flag(key->sta, WLAN_STA_MFP))
182 key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
183 break;
184 case NL80211_IFTYPE_ADHOC:
185 /* no MFP (yet) */
186 break;
187 case NL80211_IFTYPE_MESH_POINT:
188#ifdef CONFIG_MAC80211_MESH
189 if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)
190 key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
191 break;
192#endif
193 case NL80211_IFTYPE_WDS:
194 case NL80211_IFTYPE_MONITOR:
195 case NL80211_IFTYPE_P2P_DEVICE:
196 case NL80211_IFTYPE_UNSPECIFIED:
197 case NUM_NL80211_IFTYPES:
198 case NL80211_IFTYPE_P2P_CLIENT:
199 case NL80211_IFTYPE_P2P_GO:
200 /* shouldn't happen */
201 WARN_ON_ONCE(1);
202 break;
203 }
204
173 err = ieee80211_key_link(key, sdata, sta); 205 err = ieee80211_key_link(key, sdata, sta);
174 if (err) 206 if (err)
175 ieee80211_key_free(sdata->local, key); 207 ieee80211_key_free(sdata->local, key);
@@ -2038,9 +2070,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
2038 */ 2070 */
2039 if (!sdata->u.mgd.associated || 2071 if (!sdata->u.mgd.associated ||
2040 sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { 2072 sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) {
2041 mutex_lock(&sdata->local->iflist_mtx);
2042 ieee80211_recalc_smps(sdata->local); 2073 ieee80211_recalc_smps(sdata->local);
2043 mutex_unlock(&sdata->local->iflist_mtx);
2044 return 0; 2074 return 0;
2045 } 2075 }
2046 2076
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
71bool ieee80211_set_channel_type(struct ieee80211_local *local, 71static enum nl80211_channel_type
72 struct ieee80211_sub_if_data *sdata, 72ieee80211_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
109static bool
110ieee80211_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
151bool 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/ibss.c b/net/mac80211/ibss.c
index a9d93285dba7..7c082517f0c7 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -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
335static 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
335static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, 349static 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
@@ -902,6 +930,9 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
902 case IEEE80211_STYPE_AUTH: 930 case IEEE80211_STYPE_AUTH:
903 ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len); 931 ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len);
904 break; 932 break;
933 case IEEE80211_STYPE_DEAUTH:
934 ieee80211_rx_mgmt_deauth_ibss(sdata, mgmt, skb->len);
935 break;
905 } 936 }
906 937
907 mgmt_out: 938 mgmt_out:
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 204bfedba306..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
71struct ieee80211_fragment_entry { 73struct ieee80211_fragment_entry {
72 unsigned long first_frag_time; 74 unsigned long first_frag_time;
73 unsigned int seq; 75 unsigned int seq;
@@ -411,6 +413,7 @@ struct ieee80211_if_managed {
411 struct work_struct monitor_work; 413 struct work_struct monitor_work;
412 struct work_struct chswitch_work; 414 struct work_struct chswitch_work;
413 struct work_struct beacon_connection_loss_work; 415 struct work_struct beacon_connection_loss_work;
416 struct work_struct csa_connection_drop_work;
414 417
415 unsigned long beacon_timeout; 418 unsigned long beacon_timeout;
416 unsigned long probe_timeout; 419 unsigned long probe_timeout;
@@ -970,7 +973,6 @@ struct ieee80211_local {
970 int scan_channel_idx; 973 int scan_channel_idx;
971 int scan_ies_len; 974 int scan_ies_len;
972 975
973 struct ieee80211_sched_scan_ies sched_scan_ies;
974 struct work_struct sched_scan_stopped_work; 976 struct work_struct sched_scan_stopped_work;
975 struct ieee80211_sub_if_data __rcu *sched_scan_sdata; 977 struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
976 978
@@ -1057,7 +1059,7 @@ struct ieee80211_local {
1057 bool disable_dynamic_ps; 1059 bool disable_dynamic_ps;
1058 1060
1059 int user_power_level; /* in dBm */ 1061 int user_power_level; /* in dBm */
1060 int power_constr_level; /* in dBm */ 1062 int ap_power_level; /* in dBm */
1061 1063
1062 enum ieee80211_smps_mode smps_mode; 1064 enum ieee80211_smps_mode smps_mode;
1063 1065
@@ -1165,7 +1167,6 @@ struct ieee802_11_elems {
1165 u8 prep_len; 1167 u8 prep_len;
1166 u8 perr_len; 1168 u8 perr_len;
1167 u8 country_elem_len; 1169 u8 country_elem_len;
1168 u8 pwr_constr_elem_len;
1169 u8 quiet_elem_len; 1170 u8 quiet_elem_len;
1170 u8 num_of_quiet_elem; /* can be more the one */ 1171 u8 num_of_quiet_elem; /* can be more the one */
1171 u8 timeout_int_len; 1172 u8 timeout_int_len;
@@ -1367,7 +1368,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
1367int ieee80211_reconfig(struct ieee80211_local *local); 1368int ieee80211_reconfig(struct ieee80211_local *local);
1368void ieee80211_stop_device(struct ieee80211_local *local); 1369void ieee80211_stop_device(struct ieee80211_local *local);
1369 1370
1370#ifdef CONFIG_PM
1371int __ieee80211_suspend(struct ieee80211_hw *hw, 1371int __ieee80211_suspend(struct ieee80211_hw *hw,
1372 struct cfg80211_wowlan *wowlan); 1372 struct cfg80211_wowlan *wowlan);
1373 1373
@@ -1381,18 +1381,6 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw)
1381 1381
1382 return ieee80211_reconfig(hw_to_local(hw)); 1382 return ieee80211_reconfig(hw_to_local(hw));
1383} 1383}
1384#else
1385static inline int __ieee80211_suspend(struct ieee80211_hw *hw,
1386 struct cfg80211_wowlan *wowlan)
1387{
1388 return 0;
1389}
1390
1391static inline int __ieee80211_resume(struct ieee80211_hw *hw)
1392{
1393 return 0;
1394}
1395#endif
1396 1384
1397/* utility functions/constants */ 1385/* utility functions/constants */
1398extern void *mac80211_wiphy_privid; /* for wiphy privid */ 1386extern void *mac80211_wiphy_privid; /* for wiphy privid */
@@ -1459,6 +1447,9 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1459 u16 transaction, u16 auth_alg, 1447 u16 transaction, u16 auth_alg,
1460 u8 *extra, size_t extra_len, const u8 *bssid, 1448 u8 *extra, size_t extra_len, const u8 *bssid,
1461 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);
1450void 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);
1462int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 1453int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1463 const u8 *ie, size_t ie_len, 1454 const u8 *ie, size_t ie_len,
1464 enum ieee80211_band band, u32 rate_mask, 1455 enum ieee80211_band band, u32 rate_mask,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index d747da541747..6f8a73c64fb3 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -793,11 +793,20 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
793 flush_work(&sdata->work); 793 flush_work(&sdata->work);
794 /* 794 /*
795 * When we get here, the interface is marked down. 795 * When we get here, the interface is marked down.
796 * Call synchronize_rcu() to wait for the RX path 796 * Call rcu_barrier() to wait both for the RX path
797 * should it be using the interface and enqueuing 797 * should it be using the interface and enqueuing
798 * 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.
799 */ 800 */
800 synchronize_rcu(); 801 rcu_barrier();
802
803 /*
804 * free_sta_rcu() enqueues a work for the actual
805 * sta cleanup, so we need to flush it while
806 * sdata is still valid.
807 */
808 flush_workqueue(local->workqueue);
809
801 skb_queue_purge(&sdata->skb_queue); 810 skb_queue_purge(&sdata->skb_queue);
802 811
803 /* 812 /*
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 bd7529363193..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);
@@ -366,9 +364,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
366 struct ieee80211_local *local = 364 struct ieee80211_local *local =
367 container_of(work, struct ieee80211_local, recalc_smps); 365 container_of(work, struct ieee80211_local, recalc_smps);
368 366
369 mutex_lock(&local->iflist_mtx);
370 ieee80211_recalc_smps(local); 367 ieee80211_recalc_smps(local);
371 mutex_unlock(&local->iflist_mtx);
372} 368}
373 369
374#ifdef CONFIG_INET 370#ifdef CONFIG_INET
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 9d7ad366ef09..3ab34d816897 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -537,7 +537,8 @@ int mesh_plink_open(struct sta_info *sta)
537 spin_lock_bh(&sta->lock); 537 spin_lock_bh(&sta->lock);
538 get_random_bytes(&llid, 2); 538 get_random_bytes(&llid, 2);
539 sta->llid = llid; 539 sta->llid = llid;
540 if (sta->plink_state != NL80211_PLINK_LISTEN) { 540 if (sta->plink_state != NL80211_PLINK_LISTEN &&
541 sta->plink_state != NL80211_PLINK_BLOCKED) {
541 spin_unlock_bh(&sta->lock); 542 spin_unlock_bh(&sta->lock);
542 return -EBUSY; 543 return -EBUSY;
543 } 544 }
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 5d77650d4363..2dbd9e1e3583 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
@@ -574,46 +572,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
574 ieee80211_tx_skb(sdata, skb); 572 ieee80211_tx_skb(sdata, skb);
575} 573}
576 574
577static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
578 const u8 *bssid, u16 stype,
579 u16 reason, bool send_frame,
580 u8 *frame_buf)
581{
582 struct ieee80211_local *local = sdata->local;
583 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
584 struct sk_buff *skb;
585 struct ieee80211_mgmt *mgmt = (void *)frame_buf;
586
587 /* build frame */
588 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
589 mgmt->duration = 0; /* initialize only */
590 mgmt->seq_ctrl = 0; /* initialize only */
591 memcpy(mgmt->da, bssid, ETH_ALEN);
592 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
593 memcpy(mgmt->bssid, bssid, ETH_ALEN);
594 /* u.deauth.reason_code == u.disassoc.reason_code */
595 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
596
597 if (send_frame) {
598 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
599 DEAUTH_DISASSOC_LEN);
600 if (!skb)
601 return;
602
603 skb_reserve(skb, local->hw.extra_tx_headroom);
604
605 /* copy in frame */
606 memcpy(skb_put(skb, DEAUTH_DISASSOC_LEN),
607 mgmt, DEAUTH_DISASSOC_LEN);
608
609 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
610 IEEE80211_SKB_CB(skb)->flags |=
611 IEEE80211_TX_INTFL_DONT_ENCRYPT;
612
613 ieee80211_tx_skb(sdata, skb);
614 }
615}
616
617void ieee80211_send_pspoll(struct ieee80211_local *local, 575void ieee80211_send_pspoll(struct ieee80211_local *local,
618 struct ieee80211_sub_if_data *sdata) 576 struct ieee80211_sub_if_data *sdata)
619{ 577{
@@ -730,16 +688,13 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
730 688
731 trace_api_chswitch_done(sdata, success); 689 trace_api_chswitch_done(sdata, success);
732 if (!success) { 690 if (!success) {
733 /* 691 sdata_info(sdata,
734 * If the channel switch was not successful, stay 692 "driver channel switch failed, disconnecting\n");
735 * around on the old channel. We currently lack 693 ieee80211_queue_work(&sdata->local->hw,
736 * good handling of this situation, possibly we 694 &ifmgd->csa_connection_drop_work);
737 * should just drop the association. 695 } else {
738 */ 696 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
739 sdata->local->csa_channel = sdata->local->oper_channel;
740 } 697 }
741
742 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
743} 698}
744EXPORT_SYMBOL(ieee80211_chswitch_done); 699EXPORT_SYMBOL(ieee80211_chswitch_done);
745 700
@@ -784,8 +739,14 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
784 return; 739 return;
785 740
786 new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); 741 new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
787 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);
788 return; 748 return;
749 }
789 750
790 sdata->local->csa_channel = new_ch; 751 sdata->local->csa_channel = new_ch;
791 752
@@ -818,23 +779,71 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
818} 779}
819 780
820static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, 781static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
821 u16 capab_info, u8 *pwr_constr_elem, 782 struct ieee80211_channel *channel,
822 u8 pwr_constr_elem_len) 783 const u8 *country_ie, u8 country_ie_len,
784 const u8 *pwr_constr_elem)
823{ 785{
824 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;
825 790
826 if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT)) 791 /* Invalid IE */
792 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
827 return; 793 return;
828 794
829 /* Power constraint IE length should be 1 octet */ 795 triplet = (void *)(country_ie + 3);
830 if (pwr_constr_elem_len != 1) 796 country_ie_len -= 3;
831 return;
832 797
833 if ((*pwr_constr_elem <= conf->channel->max_reg_power) && 798 switch (channel->band) {
834 (*pwr_constr_elem != sdata->local->power_constr_level)) { 799 default:
835 sdata->local->power_constr_level = *pwr_constr_elem; 800 WARN_ON_ONCE(1);
836 ieee80211_hw_config(sdata->local, 0); 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;
837 } 809 }
810
811 /* find channel */
812 while (country_ie_len >= 3) {
813 u8 first_channel = triplet->chans.first_channel;
814
815 if (first_channel >= IEEE80211_COUNTRY_EXTENSION_ID)
816 goto next;
817
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;
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);
838} 847}
839 848
840void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) 849void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
@@ -1339,9 +1348,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1339 1348
1340 mutex_lock(&local->iflist_mtx); 1349 mutex_lock(&local->iflist_mtx);
1341 ieee80211_recalc_ps(local, -1); 1350 ieee80211_recalc_ps(local, -1);
1342 ieee80211_recalc_smps(local);
1343 mutex_unlock(&local->iflist_mtx); 1351 mutex_unlock(&local->iflist_mtx);
1344 1352
1353 ieee80211_recalc_smps(local);
1345 ieee80211_recalc_ps_vif(sdata); 1354 ieee80211_recalc_ps_vif(sdata);
1346 1355
1347 netif_tx_start_all_queues(sdata->dev); 1356 netif_tx_start_all_queues(sdata->dev);
@@ -1438,7 +1447,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1438 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); 1447 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
1439 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); 1448 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
1440 1449
1441 local->power_constr_level = 0; 1450 local->ap_power_level = 0;
1442 1451
1443 del_timer_sync(&local->dynamic_ps_timer); 1452 del_timer_sync(&local->dynamic_ps_timer);
1444 cancel_work_sync(&local->dynamic_ps_enable_work); 1453 cancel_work_sync(&local->dynamic_ps_enable_work);
@@ -1692,11 +1701,12 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1692} 1701}
1693EXPORT_SYMBOL(ieee80211_ap_probereq_get); 1702EXPORT_SYMBOL(ieee80211_ap_probereq_get);
1694 1703
1695static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) 1704static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata,
1705 bool transmit_frame)
1696{ 1706{
1697 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1707 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1698 struct ieee80211_local *local = sdata->local; 1708 struct ieee80211_local *local = sdata->local;
1699 u8 frame_buf[DEAUTH_DISASSOC_LEN]; 1709 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
1700 1710
1701 mutex_lock(&ifmgd->mtx); 1711 mutex_lock(&ifmgd->mtx);
1702 if (!ifmgd->associated) { 1712 if (!ifmgd->associated) {
@@ -1704,19 +1714,17 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1704 return; 1714 return;
1705 } 1715 }
1706 1716
1707 sdata_info(sdata, "Connection to AP %pM lost\n",
1708 ifmgd->associated->bssid);
1709
1710 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, 1717 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
1711 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 1718 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1712 false, frame_buf); 1719 transmit_frame, frame_buf);
1720 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
1713 mutex_unlock(&ifmgd->mtx); 1721 mutex_unlock(&ifmgd->mtx);
1714 1722
1715 /* 1723 /*
1716 * must be outside lock due to cfg80211, 1724 * must be outside lock due to cfg80211,
1717 * but that's not a problem. 1725 * but that's not a problem.
1718 */ 1726 */
1719 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 1727 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
1720 1728
1721 mutex_lock(&local->mtx); 1729 mutex_lock(&local->mtx);
1722 ieee80211_recalc_idle(local); 1730 ieee80211_recalc_idle(local);
@@ -1739,10 +1747,24 @@ static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
1739 rcu_read_unlock(); 1747 rcu_read_unlock();
1740 } 1748 }
1741 1749
1742 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) 1750 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) {
1743 __ieee80211_connection_loss(sdata); 1751 sdata_info(sdata, "Connection to AP %pM lost\n",
1744 else 1752 ifmgd->bssid);
1753 __ieee80211_disconnect(sdata, false);
1754 } else {
1745 ieee80211_mgd_probe_ap(sdata, true); 1755 ieee80211_mgd_probe_ap(sdata, true);
1756 }
1757}
1758
1759static 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);
1746} 1768}
1747 1769
1748void ieee80211_beacon_loss(struct ieee80211_vif *vif) 1770void ieee80211_beacon_loss(struct ieee80211_vif *vif)
@@ -2530,15 +2552,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2530 bssid, true); 2552 bssid, true);
2531 } 2553 }
2532 2554
2533 /* Note: country IE parsing is done for us by cfg80211 */ 2555 if (elems.country_elem && elems.pwr_constr_elem &&
2534 if (elems.country_elem) { 2556 mgmt->u.probe_resp.capab_info &
2535 /* TODO: IBSS also needs this */ 2557 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
2536 if (elems.pwr_constr_elem) 2558 ieee80211_handle_pwr_constr(sdata, local->oper_channel,
2537 ieee80211_handle_pwr_constr(sdata, 2559 elems.country_elem,
2538 le16_to_cpu(mgmt->u.probe_resp.capab_info), 2560 elems.country_elem_len,
2539 elems.pwr_constr_elem, 2561 elems.pwr_constr_elem);
2540 elems.pwr_constr_elem_len);
2541 }
2542 2562
2543 ieee80211_bss_info_change_notify(sdata, changed); 2563 ieee80211_bss_info_change_notify(sdata, changed);
2544} 2564}
@@ -2635,7 +2655,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2635{ 2655{
2636 struct ieee80211_local *local = sdata->local; 2656 struct ieee80211_local *local = sdata->local;
2637 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2657 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2638 u8 frame_buf[DEAUTH_DISASSOC_LEN]; 2658 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
2639 2659
2640 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, 2660 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
2641 false, frame_buf); 2661 false, frame_buf);
@@ -2645,7 +2665,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2645 * must be outside lock due to cfg80211, 2665 * must be outside lock due to cfg80211,
2646 * but that's not a problem. 2666 * but that's not a problem.
2647 */ 2667 */
2648 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 2668 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
2649 2669
2650 mutex_lock(&local->mtx); 2670 mutex_lock(&local->mtx);
2651 ieee80211_recalc_idle(local); 2671 ieee80211_recalc_idle(local);
@@ -2929,6 +2949,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
2929 2949
2930 cancel_work_sync(&ifmgd->monitor_work); 2950 cancel_work_sync(&ifmgd->monitor_work);
2931 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);
2932 if (del_timer_sync(&ifmgd->timer)) 2953 if (del_timer_sync(&ifmgd->timer))
2933 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); 2954 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
2934 2955
@@ -2985,6 +3006,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2985 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); 3006 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
2986 INIT_WORK(&ifmgd->beacon_connection_loss_work, 3007 INIT_WORK(&ifmgd->beacon_connection_loss_work,
2987 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);
2988 INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); 3011 INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work);
2989 setup_timer(&ifmgd->timer, ieee80211_sta_timer, 3012 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
2990 (unsigned long) sdata); 3013 (unsigned long) sdata);
@@ -3525,7 +3548,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
3525 struct cfg80211_deauth_request *req) 3548 struct cfg80211_deauth_request *req)
3526{ 3549{
3527 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3550 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3528 u8 frame_buf[DEAUTH_DISASSOC_LEN]; 3551 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3529 3552
3530 mutex_lock(&ifmgd->mtx); 3553 mutex_lock(&ifmgd->mtx);
3531 3554
@@ -3553,7 +3576,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
3553 3576
3554 mutex_unlock(&ifmgd->mtx); 3577 mutex_unlock(&ifmgd->mtx);
3555 3578
3556 __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 3579 __cfg80211_send_deauth(sdata->dev, frame_buf,
3580 IEEE80211_DEAUTH_FRAME_LEN);
3557 3581
3558 mutex_lock(&sdata->local->mtx); 3582 mutex_lock(&sdata->local->mtx);
3559 ieee80211_recalc_idle(sdata->local); 3583 ieee80211_recalc_idle(sdata->local);
@@ -3567,7 +3591,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
3567{ 3591{
3568 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3592 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3569 u8 bssid[ETH_ALEN]; 3593 u8 bssid[ETH_ALEN];
3570 u8 frame_buf[DEAUTH_DISASSOC_LEN]; 3594 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3571 3595
3572 mutex_lock(&ifmgd->mtx); 3596 mutex_lock(&ifmgd->mtx);
3573 3597
@@ -3592,7 +3616,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
3592 frame_buf); 3616 frame_buf);
3593 mutex_unlock(&ifmgd->mtx); 3617 mutex_unlock(&ifmgd->mtx);
3594 3618
3595 __cfg80211_send_disassoc(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 3619 __cfg80211_send_disassoc(sdata->dev, frame_buf,
3620 IEEE80211_DEAUTH_FRAME_LEN);
3596 3621
3597 mutex_lock(&sdata->local->mtx); 3622 mutex_lock(&sdata->local->mtx);
3598 ieee80211_recalc_idle(sdata->local); 3623 ieee80211_recalc_idle(sdata->local);
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 507121dad082..83608ac16780 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -233,8 +233,7 @@ static void ieee80211_hw_roc_start(struct work_struct *work)
233 u32 dur = dep->duration; 233 u32 dur = dep->duration;
234 dep->duration = dur - roc->duration; 234 dep->duration = dur - roc->duration;
235 roc->duration = dur; 235 roc->duration = dur;
236 list_del(&dep->list); 236 list_move(&dep->list, &roc->list);
237 list_add(&dep->list, &roc->list);
238 } 237 }
239 } 238 }
240 out_unlock: 239 out_unlock:
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 740e414d44f4..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(
@@ -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
962out_free: 958out_free:
963 while (i > 0) 959 while (i > 0)
964 kfree(local->sched_scan_ies.ie[--i]); 960 kfree(sched_scan_ies.ie[--i]);
965out: 961out:
966 mutex_unlock(&local->mtx); 962 mutex_unlock(&local->mtx);
967 return ret; 963 return ret;
@@ -970,7 +966,7 @@ out:
970int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) 966int 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
988out: 981out:
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..9c8cd8b8f753 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
94static 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
151static 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 */
95struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, 159struct 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
@@ -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 {
287struct sta_info { 287struct 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 b0801b7d572d..2ce89732d0f2 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -517,29 +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 if (ieee80211_is_nullfunc(hdr->frame_control) || 524 rcu_read_lock();
523 ieee80211_is_qos_nullfunc(hdr->frame_control)) { 525
524 cfg80211_probe_status(skb->dev, hdr->addr1, 526 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
525 cookie, acked, GFP_ATOMIC); 527 if (!sdata->dev)
526 } else if (skb->dev) { 528 continue;
527 cfg80211_mgmt_tx_status(
528 skb->dev->ieee80211_ptr, cookie, skb->data,
529 skb->len, acked, GFP_ATOMIC);
530 } else {
531 struct ieee80211_sub_if_data *p2p_sdata;
532 529
533 rcu_read_lock(); 530 if (skb->dev != sdata->dev)
531 continue;
534 532
535 p2p_sdata = rcu_dereference(local->p2p_sdata); 533 found = true;
536 if (p2p_sdata) { 534 break;
537 cfg80211_mgmt_tx_status( 535 }
538 &p2p_sdata->wdev, cookie, skb->data, 536
539 skb->len, acked, GFP_ATOMIC); 537 if (!skb->dev) {
540 } 538 sdata = rcu_dereference(local->p2p_sdata);
541 rcu_read_unlock(); 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,
548 cookie, acked, GFP_ATOMIC);
549 } else {
550 cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data,
551 skb->len, acked, GFP_ATOMIC);
542 } 552 }
553
554 rcu_read_unlock();
543 } 555 }
544 556
545 if (unlikely(info->ack_frame_id)) { 557 if (unlikely(info->ack_frame_id)) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 29eb4e678235..e0e0d1d0e830 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -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:
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 471fb0516c99..22ca35054dd0 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -792,8 +792,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
792 elems->country_elem_len = elen; 792 elems->country_elem_len = elen;
793 break; 793 break;
794 case WLAN_EID_PWR_CONSTRAINT: 794 case WLAN_EID_PWR_CONSTRAINT:
795 if (elen != 1) {
796 elem_parse_failed = true;
797 break;
798 }
795 elems->pwr_constr_elem = pos; 799 elems->pwr_constr_elem = pos;
796 elems->pwr_constr_elem_len = elen;
797 break; 800 break;
798 case WLAN_EID_TIMEOUT_INTERVAL: 801 case WLAN_EID_TIMEOUT_INTERVAL:
799 elems->timeout_int = pos; 802 elems->timeout_int = pos;
@@ -1004,6 +1007,45 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1004 ieee80211_tx_skb(sdata, skb); 1007 ieee80211_tx_skb(sdata, skb);
1005} 1008}
1006 1009
1010void 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
1007int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 1049int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1008 const u8 *ie, size_t ie_len, 1050 const u8 *ie, size_t ie_len,
1009 enum ieee80211_band band, u32 rate_mask, 1051 enum ieee80211_band band, u32 rate_mask,
@@ -1564,14 +1606,13 @@ static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
1564 return 0; 1606 return 0;
1565} 1607}
1566 1608
1567/* must hold iflist_mtx */
1568void ieee80211_recalc_smps(struct ieee80211_local *local) 1609void ieee80211_recalc_smps(struct ieee80211_local *local)
1569{ 1610{
1570 struct ieee80211_sub_if_data *sdata; 1611 struct ieee80211_sub_if_data *sdata;
1571 enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; 1612 enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
1572 int count = 0; 1613 int count = 0;
1573 1614
1574 lockdep_assert_held(&local->iflist_mtx); 1615 mutex_lock(&local->iflist_mtx);
1575 1616
1576 /* 1617 /*
1577 * This function could be improved to handle multiple 1618 * This function could be improved to handle multiple
@@ -1600,12 +1641,14 @@ void ieee80211_recalc_smps(struct ieee80211_local *local)
1600 } 1641 }
1601 1642
1602 if (smps_mode == local->smps_mode) 1643 if (smps_mode == local->smps_mode)
1603 return; 1644 goto unlock;
1604 1645
1605 set: 1646 set:
1606 local->smps_mode = smps_mode; 1647 local->smps_mode = smps_mode;
1607 /* changed flag is auto-detected for this */ 1648 /* changed flag is auto-detected for this */
1608 ieee80211_hw_config(local, 0); 1649 ieee80211_hw_config(local, 0);
1650 unlock:
1651 mutex_unlock(&local->iflist_mtx);
1609} 1652}
1610 1653
1611static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) 1654static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)