aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-07-22 20:01:44 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-22 20:01:44 -0400
commitf9035cd498486d5a82ad8ae9bcfdb91b3e57ec9d (patch)
treef90d0fc8abc1edf7fd161252704bb5675f3460d0 /net
parent1821f7cd65ad9ea56580b830ac79bf4c4fef59cb (diff)
parent41bf37117b47fc5ce2aae91f6a108e7e42e0b046 (diff)
Merge branch 'for-davem' of ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-rx.c10
-rw-r--r--net/mac80211/cfg.c4
-rw-r--r--net/mac80211/driver-ops.h31
-rw-r--r--net/mac80211/driver-trace.h43
-rw-r--r--net/mac80211/ieee80211_i.h7
-rw-r--r--net/mac80211/key.c2
-rw-r--r--net/mac80211/mlme.c30
-rw-r--r--net/mac80211/pm.c3
-rw-r--r--net/mac80211/scan.c6
-rw-r--r--net/mac80211/tkip.c11
-rw-r--r--net/mac80211/util.c71
-rw-r--r--net/mac80211/work.c28
-rw-r--r--net/wireless/core.c7
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/nl80211.c109
-rw-r--r--net/wireless/scan.c4
-rw-r--r--net/wireless/util.c38
17 files changed, 340 insertions, 68 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index ebadb9ac9a7e..fd1aaf2a4a6c 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -104,14 +104,22 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
104 const u8 *addr) 104 const u8 *addr)
105{ 105{
106 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 106 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
107 struct sta_info *sta = sta_info_get(sdata, addr); 107 struct sta_info *sta;
108 int i; 108 int i;
109 109
110 rcu_read_lock();
111 sta = sta_info_get(sdata, addr);
112 if (!sta) {
113 rcu_read_unlock();
114 return;
115 }
116
110 for (i = 0; i < STA_TID_NUM; i++) 117 for (i = 0; i < STA_TID_NUM; i++)
111 if (ba_rx_bitmap & BIT(i)) 118 if (ba_rx_bitmap & BIT(i))
112 set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested); 119 set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested);
113 120
114 ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); 121 ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
122 rcu_read_unlock();
115} 123}
116EXPORT_SYMBOL(ieee80211_stop_rx_ba_session); 124EXPORT_SYMBOL(ieee80211_stop_rx_ba_session);
117 125
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index bfc36e904764..3d1b091d9b2e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1255,6 +1255,10 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
1255 */ 1255 */
1256 p.uapsd = false; 1256 p.uapsd = false;
1257 1257
1258 if (params->queue >= local->hw.queues)
1259 return -EINVAL;
1260
1261 local->tx_conf[params->queue] = p;
1258 if (drv_conf_tx(local, params->queue, &p)) { 1262 if (drv_conf_tx(local, params->queue, &p)) {
1259 wiphy_debug(local->hw.wiphy, 1263 wiphy_debug(local->hw.wiphy,
1260 "failed to set TX queue parameters for queue %d\n", 1264 "failed to set TX queue parameters for queue %d\n",
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index b2d6bba44054..1425380983f7 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -130,6 +130,37 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
130 trace_drv_return_void(local); 130 trace_drv_return_void(local);
131} 131}
132 132
133static inline int drv_tx_sync(struct ieee80211_local *local,
134 struct ieee80211_sub_if_data *sdata,
135 const u8 *bssid,
136 enum ieee80211_tx_sync_type type)
137{
138 int ret = 0;
139
140 might_sleep();
141
142 trace_drv_tx_sync(local, sdata, bssid, type);
143 if (local->ops->tx_sync)
144 ret = local->ops->tx_sync(&local->hw, &sdata->vif,
145 bssid, type);
146 trace_drv_return_int(local, ret);
147 return ret;
148}
149
150static inline void drv_finish_tx_sync(struct ieee80211_local *local,
151 struct ieee80211_sub_if_data *sdata,
152 const u8 *bssid,
153 enum ieee80211_tx_sync_type type)
154{
155 might_sleep();
156
157 trace_drv_finish_tx_sync(local, sdata, bssid, type);
158 if (local->ops->finish_tx_sync)
159 local->ops->finish_tx_sync(&local->hw, &sdata->vif,
160 bssid, type);
161 trace_drv_return_void(local);
162}
163
133static inline u64 drv_prepare_multicast(struct ieee80211_local *local, 164static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
134 struct netdev_hw_addr_list *mc_list) 165 struct netdev_hw_addr_list *mc_list)
135{ 166{
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 4470f6e8b845..f47b00dc7afd 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -319,6 +319,49 @@ TRACE_EVENT(drv_bss_info_changed,
319 ) 319 )
320); 320);
321 321
322DECLARE_EVENT_CLASS(tx_sync_evt,
323 TP_PROTO(struct ieee80211_local *local,
324 struct ieee80211_sub_if_data *sdata,
325 const u8 *bssid,
326 enum ieee80211_tx_sync_type type),
327 TP_ARGS(local, sdata, bssid, type),
328
329 TP_STRUCT__entry(
330 LOCAL_ENTRY
331 VIF_ENTRY
332 __array(char, bssid, ETH_ALEN)
333 __field(u32, sync_type)
334 ),
335
336 TP_fast_assign(
337 LOCAL_ASSIGN;
338 VIF_ASSIGN;
339 memcpy(__entry->bssid, bssid, ETH_ALEN);
340 __entry->sync_type = type;
341 ),
342
343 TP_printk(
344 LOCAL_PR_FMT VIF_PR_FMT " bssid:%pM type:%d",
345 LOCAL_PR_ARG, VIF_PR_ARG, __entry->bssid, __entry->sync_type
346 )
347);
348
349DEFINE_EVENT(tx_sync_evt, drv_tx_sync,
350 TP_PROTO(struct ieee80211_local *local,
351 struct ieee80211_sub_if_data *sdata,
352 const u8 *bssid,
353 enum ieee80211_tx_sync_type type),
354 TP_ARGS(local, sdata, bssid, type)
355);
356
357DEFINE_EVENT(tx_sync_evt, drv_finish_tx_sync,
358 TP_PROTO(struct ieee80211_local *local,
359 struct ieee80211_sub_if_data *sdata,
360 const u8 *bssid,
361 enum ieee80211_tx_sync_type type),
362 TP_ARGS(local, sdata, bssid, type)
363);
364
322TRACE_EVENT(drv_prepare_multicast, 365TRACE_EVENT(drv_prepare_multicast,
323 TP_PROTO(struct ieee80211_local *local, int mc_count), 366 TP_PROTO(struct ieee80211_local *local, int mc_count),
324 367
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index dda0d1ab34f3..400c09bea639 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -323,6 +323,7 @@ struct ieee80211_work {
323 u8 key[WLAN_KEY_LEN_WEP104]; 323 u8 key[WLAN_KEY_LEN_WEP104];
324 u8 key_len, key_idx; 324 u8 key_len, key_idx;
325 bool privacy; 325 bool privacy;
326 bool synced;
326 } probe_auth; 327 } probe_auth;
327 struct { 328 struct {
328 struct cfg80211_bss *bss; 329 struct cfg80211_bss *bss;
@@ -336,6 +337,7 @@ struct ieee80211_work {
336 u8 ssid_len; 337 u8 ssid_len;
337 u8 supp_rates_len; 338 u8 supp_rates_len;
338 bool wmm_used, use_11n, uapsd_used; 339 bool wmm_used, use_11n, uapsd_used;
340 bool synced;
339 } assoc; 341 } assoc;
340 struct { 342 struct {
341 u32 duration; 343 u32 duration;
@@ -746,6 +748,7 @@ struct ieee80211_local {
746 struct workqueue_struct *workqueue; 748 struct workqueue_struct *workqueue;
747 749
748 unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; 750 unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
751 struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES];
749 /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ 752 /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
750 spinlock_t queue_stop_reason_lock; 753 spinlock_t queue_stop_reason_lock;
751 754
@@ -1376,14 +1379,14 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1376 enum ieee80211_band band, u32 rate_mask, 1379 enum ieee80211_band band, u32 rate_mask,
1377 u8 channel); 1380 u8 channel);
1378struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, 1381struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1379 u8 *dst, 1382 u8 *dst, u32 ratemask,
1380 const u8 *ssid, size_t ssid_len, 1383 const u8 *ssid, size_t ssid_len,
1381 const u8 *ie, size_t ie_len, 1384 const u8 *ie, size_t ie_len,
1382 bool directed); 1385 bool directed);
1383void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 1386void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
1384 const u8 *ssid, size_t ssid_len, 1387 const u8 *ssid, size_t ssid_len,
1385 const u8 *ie, size_t ie_len, 1388 const u8 *ie, size_t ie_len,
1386 bool directed); 1389 u32 ratemask, bool directed);
1387 1390
1388void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, 1391void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
1389 const size_t supp_rates_len, 1392 const size_t supp_rates_len,
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 739bee13e813..5150c6d11b57 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -278,7 +278,7 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
278 bool defunikey, defmultikey, defmgmtkey; 278 bool defunikey, defmultikey, defmgmtkey;
279 279
280 if (new) 280 if (new)
281 list_add(&new->list, &sdata->key_list); 281 list_add_tail(&new->list, &sdata->key_list);
282 282
283 if (sta && pairwise) { 283 if (sta && pairwise) {
284 rcu_assign_pointer(sta->ptk, new); 284 rcu_assign_pointer(sta->ptk, new);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index c99237cd4b98..d6470c7fd6ce 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -917,6 +917,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
917 params.aifs, params.cw_min, params.cw_max, 917 params.aifs, params.cw_min, params.cw_max,
918 params.txop, params.uapsd); 918 params.txop, params.uapsd);
919#endif 919#endif
920 local->tx_conf[queue] = params;
920 if (drv_conf_tx(local, queue, &params)) 921 if (drv_conf_tx(local, queue, &params))
921 wiphy_debug(local->hw.wiphy, 922 wiphy_debug(local->hw.wiphy,
922 "failed to set TX queue parameters for queue %d\n", 923 "failed to set TX queue parameters for queue %d\n",
@@ -1219,7 +1220,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1219 } else { 1220 } else {
1220 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1221 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1221 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, 1222 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0,
1222 true); 1223 (u32) -1, true);
1223 } 1224 }
1224 1225
1225 ifmgd->probe_send_count++; 1226 ifmgd->probe_send_count++;
@@ -1304,7 +1305,8 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1304 1305
1305 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1306 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1306 skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, 1307 skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid,
1307 ssid + 2, ssid[1], NULL, 0, true); 1308 (u32) -1, ssid + 2, ssid[1],
1309 NULL, 0, true);
1308 1310
1309 return skb; 1311 return skb;
1310} 1312}
@@ -2333,14 +2335,16 @@ static enum work_done_result
2333ieee80211_probe_auth_done(struct ieee80211_work *wk, 2335ieee80211_probe_auth_done(struct ieee80211_work *wk,
2334 struct sk_buff *skb) 2336 struct sk_buff *skb)
2335{ 2337{
2338 struct ieee80211_local *local = wk->sdata->local;
2339
2336 if (!skb) { 2340 if (!skb) {
2337 cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); 2341 cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta);
2338 return WORK_DONE_DESTROY; 2342 goto destroy;
2339 } 2343 }
2340 2344
2341 if (wk->type == IEEE80211_WORK_AUTH) { 2345 if (wk->type == IEEE80211_WORK_AUTH) {
2342 cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); 2346 cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len);
2343 return WORK_DONE_DESTROY; 2347 goto destroy;
2344 } 2348 }
2345 2349
2346 mutex_lock(&wk->sdata->u.mgd.mtx); 2350 mutex_lock(&wk->sdata->u.mgd.mtx);
@@ -2350,6 +2354,12 @@ ieee80211_probe_auth_done(struct ieee80211_work *wk,
2350 wk->type = IEEE80211_WORK_AUTH; 2354 wk->type = IEEE80211_WORK_AUTH;
2351 wk->probe_auth.tries = 0; 2355 wk->probe_auth.tries = 0;
2352 return WORK_DONE_REQUEUE; 2356 return WORK_DONE_REQUEUE;
2357 destroy:
2358 if (wk->probe_auth.synced)
2359 drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
2360 IEEE80211_TX_SYNC_AUTH);
2361
2362 return WORK_DONE_DESTROY;
2353} 2363}
2354 2364
2355int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, 2365int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
@@ -2422,6 +2432,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2422static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, 2432static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2423 struct sk_buff *skb) 2433 struct sk_buff *skb)
2424{ 2434{
2435 struct ieee80211_local *local = wk->sdata->local;
2425 struct ieee80211_mgmt *mgmt; 2436 struct ieee80211_mgmt *mgmt;
2426 struct ieee80211_rx_status *rx_status; 2437 struct ieee80211_rx_status *rx_status;
2427 struct ieee802_11_elems elems; 2438 struct ieee802_11_elems elems;
@@ -2429,7 +2440,7 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2429 2440
2430 if (!skb) { 2441 if (!skb) {
2431 cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); 2442 cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);
2432 return WORK_DONE_DESTROY; 2443 goto destroy;
2433 } 2444 }
2434 2445
2435 if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) { 2446 if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) {
@@ -2449,6 +2460,10 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2449 status = le16_to_cpu(mgmt->u.assoc_resp.status_code); 2460 status = le16_to_cpu(mgmt->u.assoc_resp.status_code);
2450 2461
2451 if (status == WLAN_STATUS_SUCCESS) { 2462 if (status == WLAN_STATUS_SUCCESS) {
2463 if (wk->assoc.synced)
2464 drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
2465 IEEE80211_TX_SYNC_ASSOC);
2466
2452 mutex_lock(&wk->sdata->u.mgd.mtx); 2467 mutex_lock(&wk->sdata->u.mgd.mtx);
2453 if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { 2468 if (!ieee80211_assoc_success(wk, mgmt, skb->len)) {
2454 mutex_unlock(&wk->sdata->u.mgd.mtx); 2469 mutex_unlock(&wk->sdata->u.mgd.mtx);
@@ -2462,6 +2477,11 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2462 } 2477 }
2463 2478
2464 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); 2479 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
2480 destroy:
2481 if (wk->assoc.synced)
2482 drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
2483 IEEE80211_TX_SYNC_ASSOC);
2484
2465 return WORK_DONE_DESTROY; 2485 return WORK_DONE_DESTROY;
2466} 2486}
2467 2487
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index f87e993e713b..6326d3439861 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -34,6 +34,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
34 struct ieee80211_sub_if_data *sdata; 34 struct ieee80211_sub_if_data *sdata;
35 struct sta_info *sta; 35 struct sta_info *sta;
36 36
37 if (!local->open_count)
38 goto suspend;
39
37 ieee80211_scan_cancel(local); 40 ieee80211_scan_cancel(local);
38 41
39 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 42 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 08a45ac3d6f8..6f09eca01112 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -228,7 +228,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
228static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) 228static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
229{ 229{
230 struct cfg80211_scan_request *req = local->scan_req; 230 struct cfg80211_scan_request *req = local->scan_req;
231 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
232 enum ieee80211_band band; 231 enum ieee80211_band band;
233 int i, ielen, n_chans; 232 int i, ielen, n_chans;
234 233
@@ -253,7 +252,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
253 252
254 ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, 253 ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
255 req->ie, req->ie_len, band, 254 req->ie, req->ie_len, band,
256 sdata->rc_rateidx_mask[band], 0); 255 req->rates[band], 0);
257 local->hw_scan_req->ie_len = ielen; 256 local->hw_scan_req->ie_len = ielen;
258 257
259 return true; 258 return true;
@@ -653,6 +652,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
653{ 652{
654 int i; 653 int i;
655 struct ieee80211_sub_if_data *sdata = local->scan_sdata; 654 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
655 enum ieee80211_band band = local->hw.conf.channel->band;
656 656
657 for (i = 0; i < local->scan_req->n_ssids; i++) 657 for (i = 0; i < local->scan_req->n_ssids; i++)
658 ieee80211_send_probe_req( 658 ieee80211_send_probe_req(
@@ -660,7 +660,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
660 local->scan_req->ssids[i].ssid, 660 local->scan_req->ssids[i].ssid,
661 local->scan_req->ssids[i].ssid_len, 661 local->scan_req->ssids[i].ssid_len,
662 local->scan_req->ie, local->scan_req->ie_len, 662 local->scan_req->ie, local->scan_req->ie_len,
663 false); 663 local->scan_req->rates[band], false);
664 664
665 /* 665 /*
666 * After sending probe requests, wait for probe responses 666 * After sending probe requests, wait for probe responses
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
index cc79e697cdb2..f49d00a4c7fd 100644
--- a/net/mac80211/tkip.c
+++ b/net/mac80211/tkip.c
@@ -185,6 +185,17 @@ void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf,
185} 185}
186EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv); 186EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv);
187 187
188void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf,
189 const u8 *ta, u32 iv32, u16 *p1k)
190{
191 const u8 *tk = &keyconf->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
192 struct tkip_ctx ctx;
193
194 tkip_mixing_phase1(tk, &ctx, ta, iv32);
195 memcpy(p1k, ctx.p1k, sizeof(ctx.p1k));
196}
197EXPORT_SYMBOL(ieee80211_get_tkip_rx_p1k);
198
188void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, 199void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
189 struct sk_buff *skb, u8 *p2k) 200 struct sk_buff *skb, u8 *p2k)
190{ 201{
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 5bfb80cba634..ddeb1b998383 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -799,6 +799,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
799 799
800 qparam.uapsd = false; 800 qparam.uapsd = false;
801 801
802 local->tx_conf[queue] = qparam;
802 drv_conf_tx(local, queue, &qparam); 803 drv_conf_tx(local, queue, &qparam);
803 } 804 }
804 805
@@ -1016,7 +1017,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1016} 1017}
1017 1018
1018struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, 1019struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1019 u8 *dst, 1020 u8 *dst, u32 ratemask,
1020 const u8 *ssid, size_t ssid_len, 1021 const u8 *ssid, size_t ssid_len,
1021 const u8 *ie, size_t ie_len, 1022 const u8 *ie, size_t ie_len,
1022 bool directed) 1023 bool directed)
@@ -1049,9 +1050,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1049 1050
1050 buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, 1051 buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
1051 local->hw.conf.channel->band, 1052 local->hw.conf.channel->band,
1052 sdata->rc_rateidx_mask 1053 ratemask, chan);
1053 [local->hw.conf.channel->band],
1054 chan);
1055 1054
1056 skb = ieee80211_probereq_get(&local->hw, &sdata->vif, 1055 skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
1057 ssid, ssid_len, 1056 ssid, ssid_len,
@@ -1072,12 +1071,12 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1072void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 1071void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
1073 const u8 *ssid, size_t ssid_len, 1072 const u8 *ssid, size_t ssid_len,
1074 const u8 *ie, size_t ie_len, 1073 const u8 *ie, size_t ie_len,
1075 bool directed) 1074 u32 ratemask, bool directed)
1076{ 1075{
1077 struct sk_buff *skb; 1076 struct sk_buff *skb;
1078 1077
1079 skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len, 1078 skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len,
1080 directed); 1079 ie, ie_len, directed);
1081 if (skb) 1080 if (skb)
1082 ieee80211_tx_skb(sdata, skb); 1081 ieee80211_tx_skb(sdata, skb);
1083} 1082}
@@ -1134,7 +1133,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1134 struct ieee80211_hw *hw = &local->hw; 1133 struct ieee80211_hw *hw = &local->hw;
1135 struct ieee80211_sub_if_data *sdata; 1134 struct ieee80211_sub_if_data *sdata;
1136 struct sta_info *sta; 1135 struct sta_info *sta;
1137 int res; 1136 int res, i;
1138 1137
1139#ifdef CONFIG_PM 1138#ifdef CONFIG_PM
1140 if (local->suspended) 1139 if (local->suspended)
@@ -1157,27 +1156,37 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1157 } 1156 }
1158#endif 1157#endif
1159 1158
1160 /* restart hardware */ 1159 /* setup fragmentation threshold */
1161 if (local->open_count) { 1160 drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
1162 /* 1161
1163 * Upon resume hardware can sometimes be goofy due to 1162 /* setup RTS threshold */
1164 * various platform / driver / bus issues, so restarting 1163 drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
1165 * the device may at times not work immediately. Propagate 1164
1166 * the error. 1165 /* reset coverage class */
1167 */ 1166 drv_set_coverage_class(local, hw->wiphy->coverage_class);
1168 res = drv_start(local); 1167
1169 if (res) { 1168 /* everything else happens only if HW was up & running */
1170 WARN(local->suspended, "Hardware became unavailable " 1169 if (!local->open_count)
1171 "upon resume. This could be a software issue " 1170 goto wake_up;
1172 "prior to suspend or a hardware issue.\n");
1173 return res;
1174 }
1175 1171
1176 ieee80211_led_radio(local, true); 1172 /*
1177 ieee80211_mod_tpt_led_trig(local, 1173 * Upon resume hardware can sometimes be goofy due to
1178 IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); 1174 * various platform / driver / bus issues, so restarting
1175 * the device may at times not work immediately. Propagate
1176 * the error.
1177 */
1178 res = drv_start(local);
1179 if (res) {
1180 WARN(local->suspended, "Hardware became unavailable "
1181 "upon resume. This could be a software issue "
1182 "prior to suspend or a hardware issue.\n");
1183 return res;
1179 } 1184 }
1180 1185
1186 ieee80211_led_radio(local, true);
1187 ieee80211_mod_tpt_led_trig(local,
1188 IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
1189
1181 /* add interfaces */ 1190 /* add interfaces */
1182 list_for_each_entry(sdata, &local->interfaces, list) { 1191 list_for_each_entry(sdata, &local->interfaces, list) {
1183 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 1192 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
@@ -1201,11 +1210,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1201 } 1210 }
1202 mutex_unlock(&local->sta_mtx); 1211 mutex_unlock(&local->sta_mtx);
1203 1212
1204 /* setup fragmentation threshold */ 1213 /* reconfigure tx conf */
1205 drv_set_frag_threshold(local, hw->wiphy->frag_threshold); 1214 for (i = 0; i < hw->queues; i++)
1206 1215 drv_conf_tx(local, i, &local->tx_conf[i]);
1207 /* setup RTS threshold */
1208 drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
1209 1216
1210 /* reconfigure hardware */ 1217 /* reconfigure hardware */
1211 ieee80211_hw_config(local, ~0); 1218 ieee80211_hw_config(local, ~0);
@@ -1287,9 +1294,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1287 if (ieee80211_sdata_running(sdata)) 1294 if (ieee80211_sdata_running(sdata))
1288 ieee80211_enable_keys(sdata); 1295 ieee80211_enable_keys(sdata);
1289 1296
1290#ifdef CONFIG_PM
1291 wake_up: 1297 wake_up:
1292#endif
1293 ieee80211_wake_queues_by_reason(hw, 1298 ieee80211_wake_queues_by_reason(hw,
1294 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 1299 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
1295 1300
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index edf8583280c9..380b9a7462b6 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -25,6 +25,7 @@
25 25
26#include "ieee80211_i.h" 26#include "ieee80211_i.h"
27#include "rate.h" 27#include "rate.h"
28#include "driver-ops.h"
28 29
29#define IEEE80211_AUTH_TIMEOUT (HZ / 5) 30#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
30#define IEEE80211_AUTH_MAX_TRIES 3 31#define IEEE80211_AUTH_MAX_TRIES 3
@@ -427,6 +428,14 @@ ieee80211_direct_probe(struct ieee80211_work *wk)
427 struct ieee80211_sub_if_data *sdata = wk->sdata; 428 struct ieee80211_sub_if_data *sdata = wk->sdata;
428 struct ieee80211_local *local = sdata->local; 429 struct ieee80211_local *local = sdata->local;
429 430
431 if (!wk->probe_auth.synced) {
432 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
433 IEEE80211_TX_SYNC_AUTH);
434 if (ret)
435 return WORK_ACT_TIMEOUT;
436 }
437 wk->probe_auth.synced = true;
438
430 wk->probe_auth.tries++; 439 wk->probe_auth.tries++;
431 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { 440 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
432 printk(KERN_DEBUG "%s: direct probe to %pM timed out\n", 441 printk(KERN_DEBUG "%s: direct probe to %pM timed out\n",
@@ -450,7 +459,8 @@ ieee80211_direct_probe(struct ieee80211_work *wk)
450 * will not answer to direct packet in unassociated state. 459 * will not answer to direct packet in unassociated state.
451 */ 460 */
452 ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, 461 ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid,
453 wk->probe_auth.ssid_len, NULL, 0, true); 462 wk->probe_auth.ssid_len, NULL, 0,
463 (u32) -1, true);
454 464
455 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; 465 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
456 run_again(local, wk->timeout); 466 run_again(local, wk->timeout);
@@ -465,6 +475,14 @@ ieee80211_authenticate(struct ieee80211_work *wk)
465 struct ieee80211_sub_if_data *sdata = wk->sdata; 475 struct ieee80211_sub_if_data *sdata = wk->sdata;
466 struct ieee80211_local *local = sdata->local; 476 struct ieee80211_local *local = sdata->local;
467 477
478 if (!wk->probe_auth.synced) {
479 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
480 IEEE80211_TX_SYNC_AUTH);
481 if (ret)
482 return WORK_ACT_TIMEOUT;
483 }
484 wk->probe_auth.synced = true;
485
468 wk->probe_auth.tries++; 486 wk->probe_auth.tries++;
469 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { 487 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
470 printk(KERN_DEBUG "%s: authentication with %pM" 488 printk(KERN_DEBUG "%s: authentication with %pM"
@@ -498,6 +516,14 @@ ieee80211_associate(struct ieee80211_work *wk)
498 struct ieee80211_sub_if_data *sdata = wk->sdata; 516 struct ieee80211_sub_if_data *sdata = wk->sdata;
499 struct ieee80211_local *local = sdata->local; 517 struct ieee80211_local *local = sdata->local;
500 518
519 if (!wk->assoc.synced) {
520 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
521 IEEE80211_TX_SYNC_ASSOC);
522 if (ret)
523 return WORK_ACT_TIMEOUT;
524 }
525 wk->assoc.synced = true;
526
501 wk->assoc.tries++; 527 wk->assoc.tries++;
502 if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { 528 if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) {
503 printk(KERN_DEBUG "%s: association with %pM" 529 printk(KERN_DEBUG "%s: association with %pM"
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 880dbe2e6f94..645437cfc464 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -488,6 +488,10 @@ int wiphy_register(struct wiphy *wiphy)
488 int i; 488 int i;
489 u16 ifmodes = wiphy->interface_modes; 489 u16 ifmodes = wiphy->interface_modes;
490 490
491 if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
492 !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
493 return -EINVAL;
494
491 if (WARN_ON(wiphy->addresses && !wiphy->n_addresses)) 495 if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
492 return -EINVAL; 496 return -EINVAL;
493 497
@@ -918,7 +922,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
918 * Configure power management to the driver here so that its 922 * Configure power management to the driver here so that its
919 * correctly set also after interface type changes etc. 923 * correctly set also after interface type changes etc.
920 */ 924 */
921 if (wdev->iftype == NL80211_IFTYPE_STATION && 925 if ((wdev->iftype == NL80211_IFTYPE_STATION ||
926 wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
922 rdev->ops->set_power_mgmt) 927 rdev->ops->set_power_mgmt)
923 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, 928 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
924 wdev->ps, 929 wdev->ps,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a570ff9214ec..8672e028022f 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -447,6 +447,10 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
447 447
448u16 cfg80211_calculate_bitrate(struct rate_info *rate); 448u16 cfg80211_calculate_bitrate(struct rate_info *rate);
449 449
450int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
451 const u8 *rates, unsigned int n_rates,
452 u32 *mask);
453
450int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, 454int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
451 u32 beacon_int); 455 u32 beacon_int);
452 456
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6a82c898f831..28d2aa109bee 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -177,6 +177,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
177 [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, 177 [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
178 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, 178 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
179 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, 179 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
180 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
180}; 181};
181 182
182/* policy for the key attributes */ 183/* policy for the key attributes */
@@ -205,6 +206,10 @@ nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
205 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG }, 206 [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
206 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG }, 207 [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
207 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED }, 208 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
209 [NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
210 [NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
211 [NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
212 [NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
208}; 213};
209 214
210/* policy for GTK rekey offload attributes */ 215/* policy for GTK rekey offload attributes */
@@ -692,8 +697,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
692 dev->wiphy.coverage_class); 697 dev->wiphy.coverage_class);
693 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, 698 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
694 dev->wiphy.max_scan_ssids); 699 dev->wiphy.max_scan_ssids);
700 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
701 dev->wiphy.max_sched_scan_ssids);
695 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, 702 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
696 dev->wiphy.max_scan_ie_len); 703 dev->wiphy.max_scan_ie_len);
704 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
705 dev->wiphy.max_sched_scan_ie_len);
697 706
698 if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) 707 if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)
699 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); 708 NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN);
@@ -929,6 +938,16 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
929 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); 938 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
930 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) 939 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT)
931 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); 940 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
941 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)
942 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED);
943 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE)
944 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
945 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ)
946 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
947 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE)
948 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
949 if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE)
950 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
932 if (dev->wiphy.wowlan.n_patterns) { 951 if (dev->wiphy.wowlan.n_patterns) {
933 struct nl80211_wowlan_pattern_support pat = { 952 struct nl80211_wowlan_pattern_support pat = {
934 .max_patterns = dev->wiphy.wowlan.n_patterns, 953 .max_patterns = dev->wiphy.wowlan.n_patterns,
@@ -3306,7 +3325,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3306 struct nlattr *attr; 3325 struct nlattr *attr;
3307 struct wiphy *wiphy; 3326 struct wiphy *wiphy;
3308 int err, tmp, n_ssids = 0, n_channels, i; 3327 int err, tmp, n_ssids = 0, n_channels, i;
3309 enum ieee80211_band band;
3310 size_t ie_len; 3328 size_t ie_len;
3311 3329
3312 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3330 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
@@ -3326,6 +3344,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3326 if (!n_channels) 3344 if (!n_channels)
3327 return -EINVAL; 3345 return -EINVAL;
3328 } else { 3346 } else {
3347 enum ieee80211_band band;
3329 n_channels = 0; 3348 n_channels = 0;
3330 3349
3331 for (band = 0; band < IEEE80211_NUM_BANDS; band++) 3350 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
@@ -3386,6 +3405,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3386 i++; 3405 i++;
3387 } 3406 }
3388 } else { 3407 } else {
3408 enum ieee80211_band band;
3409
3389 /* all channels */ 3410 /* all channels */
3390 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 3411 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
3391 int j; 3412 int j;
@@ -3432,6 +3453,30 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3432 request->ie_len); 3453 request->ie_len);
3433 } 3454 }
3434 3455
3456 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
3457 if (wiphy->bands[i])
3458 request->rates[i] =
3459 (1 << wiphy->bands[i]->n_bitrates) - 1;
3460
3461 if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
3462 nla_for_each_nested(attr,
3463 info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
3464 tmp) {
3465 enum ieee80211_band band = nla_type(attr);
3466
3467 if (band < 0 || band > IEEE80211_NUM_BANDS) {
3468 err = -EINVAL;
3469 goto out_free;
3470 }
3471 err = ieee80211_get_ratemask(wiphy->bands[band],
3472 nla_data(attr),
3473 nla_len(attr),
3474 &request->rates[band]);
3475 if (err)
3476 goto out_free;
3477 }
3478 }
3479
3435 request->dev = dev; 3480 request->dev = dev;
3436 request->wiphy = &rdev->wiphy; 3481 request->wiphy = &rdev->wiphy;
3437 3482
@@ -3497,7 +3542,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3497 tmp) 3542 tmp)
3498 n_ssids++; 3543 n_ssids++;
3499 3544
3500 if (n_ssids > wiphy->max_scan_ssids) 3545 if (n_ssids > wiphy->max_sched_scan_ssids)
3501 return -EINVAL; 3546 return -EINVAL;
3502 3547
3503 if (info->attrs[NL80211_ATTR_IE]) 3548 if (info->attrs[NL80211_ATTR_IE])
@@ -3505,7 +3550,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3505 else 3550 else
3506 ie_len = 0; 3551 ie_len = 0;
3507 3552
3508 if (ie_len > wiphy->max_scan_ie_len) 3553 if (ie_len > wiphy->max_sched_scan_ie_len)
3509 return -EINVAL; 3554 return -EINVAL;
3510 3555
3511 mutex_lock(&rdev->sched_scan_mtx); 3556 mutex_lock(&rdev->sched_scan_mtx);
@@ -4318,25 +4363,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4318 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 4363 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
4319 struct ieee80211_supported_band *sband = 4364 struct ieee80211_supported_band *sband =
4320 wiphy->bands[ibss.channel->band]; 4365 wiphy->bands[ibss.channel->band];
4321 int i, j; 4366 int err;
4322 4367
4323 if (n_rates == 0) 4368 err = ieee80211_get_ratemask(sband, rates, n_rates,
4324 return -EINVAL; 4369 &ibss.basic_rates);
4325 4370 if (err)
4326 for (i = 0; i < n_rates; i++) { 4371 return err;
4327 int rate = (rates[i] & 0x7f) * 5;
4328 bool found = false;
4329
4330 for (j = 0; j < sband->n_bitrates; j++) {
4331 if (sband->bitrates[j].bitrate == rate) {
4332 found = true;
4333 ibss.basic_rates |= BIT(j);
4334 break;
4335 }
4336 }
4337 if (!found)
4338 return -EINVAL;
4339 }
4340 } 4372 }
4341 4373
4342 if (info->attrs[NL80211_ATTR_MCAST_RATE] && 4374 if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
@@ -5272,6 +5304,14 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
5272 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); 5304 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
5273 if (rdev->wowlan->magic_pkt) 5305 if (rdev->wowlan->magic_pkt)
5274 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); 5306 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
5307 if (rdev->wowlan->gtk_rekey_failure)
5308 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
5309 if (rdev->wowlan->eap_identity_req)
5310 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
5311 if (rdev->wowlan->four_way_handshake)
5312 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
5313 if (rdev->wowlan->rfkill_release)
5314 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
5275 if (rdev->wowlan->n_patterns) { 5315 if (rdev->wowlan->n_patterns) {
5276 struct nlattr *nl_pats, *nl_pat; 5316 struct nlattr *nl_pats, *nl_pat;
5277 int i, pat_len; 5317 int i, pat_len;
@@ -5348,6 +5388,33 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
5348 new_triggers.magic_pkt = true; 5388 new_triggers.magic_pkt = true;
5349 } 5389 }
5350 5390
5391 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
5392 return -EINVAL;
5393
5394 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
5395 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
5396 return -EINVAL;
5397 new_triggers.gtk_rekey_failure = true;
5398 }
5399
5400 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
5401 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
5402 return -EINVAL;
5403 new_triggers.eap_identity_req = true;
5404 }
5405
5406 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
5407 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
5408 return -EINVAL;
5409 new_triggers.four_way_handshake = true;
5410 }
5411
5412 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
5413 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
5414 return -EINVAL;
5415 new_triggers.rfkill_release = true;
5416 }
5417
5351 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { 5418 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
5352 struct nlattr *pat; 5419 struct nlattr *pat;
5353 int n_patterns = 0; 5420 int n_patterns = 0;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 1c4672e35144..2936cb809152 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -862,6 +862,10 @@ int cfg80211_wext_siwscan(struct net_device *dev,
862 creq->n_ssids = 0; 862 creq->n_ssids = 0;
863 } 863 }
864 864
865 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
866 if (wiphy->bands[i])
867 creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
868
865 rdev->scan_req = creq; 869 rdev->scan_req = creq;
866 err = rdev->ops->scan(wiphy, dev, creq); 870 err = rdev->ops->scan(wiphy, dev, creq);
867 if (err) { 871 if (err) {
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 4d7b83fbc32f..be75a3a0424e 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1006,3 +1006,41 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
1006 1006
1007 return -EBUSY; 1007 return -EBUSY;
1008} 1008}
1009
1010int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
1011 const u8 *rates, unsigned int n_rates,
1012 u32 *mask)
1013{
1014 int i, j;
1015
1016 if (!sband)
1017 return -EINVAL;
1018
1019 if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES)
1020 return -EINVAL;
1021
1022 *mask = 0;
1023
1024 for (i = 0; i < n_rates; i++) {
1025 int rate = (rates[i] & 0x7f) * 5;
1026 bool found = false;
1027
1028 for (j = 0; j < sband->n_bitrates; j++) {
1029 if (sband->bitrates[j].bitrate == rate) {
1030 found = true;
1031 *mask |= BIT(j);
1032 break;
1033 }
1034 }
1035 if (!found)
1036 return -EINVAL;
1037 }
1038
1039 /*
1040 * mask must have at least one bit set here since we
1041 * didn't accept a 0-length rates array nor allowed
1042 * entries in the array that didn't exist
1043 */
1044
1045 return 0;
1046}