aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-05-10 12:39:28 -0400
committerPatrick McHardy <kaber@trash.net>2010-05-10 12:39:28 -0400
commit1e4b1057121bc756b91758a434b504d2010f6088 (patch)
treeb016cf2c728289c7e36d9e4e488f30ab0bd0ae6e /net/mac80211
parent3b254c54ec46eb022cb26ee6ab37fae23f5f7d6a (diff)
parent3ee943728fff536edaf8f59faa58aaa1aa7366e3 (diff)
Merge branch 'master' of /repos/git/net-next-2.6
Conflicts: net/bridge/br_device.c net/bridge/br_forward.c Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/agg-rx.c18
-rw-r--r--net/mac80211/agg-tx.c3
-rw-r--r--net/mac80211/cfg.c30
-rw-r--r--net/mac80211/debugfs_sta.c65
-rw-r--r--net/mac80211/driver-ops.h14
-rw-r--r--net/mac80211/driver-trace.h9
-rw-r--r--net/mac80211/ibss.c27
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/key.c1
-rw-r--r--net/mac80211/main.c19
-rw-r--r--net/mac80211/mlme.c28
-rw-r--r--net/mac80211/rx.c2
-rw-r--r--net/mac80211/scan.c53
-rw-r--r--net/mac80211/sta_info.c30
-rw-r--r--net/mac80211/status.c7
-rw-r--r--net/mac80211/tx.c12
-rw-r--r--net/mac80211/work.c28
17 files changed, 276 insertions, 73 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 9598fdb4ad01..6bb9a9a94960 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -19,8 +19,9 @@
19#include "ieee80211_i.h" 19#include "ieee80211_i.h"
20#include "driver-ops.h" 20#include "driver-ops.h"
21 21
22void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 22static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
23 u16 initiator, u16 reason) 23 u16 initiator, u16 reason,
24 bool from_timer)
24{ 25{
25 struct ieee80211_local *local = sta->local; 26 struct ieee80211_local *local = sta->local;
26 struct tid_ampdu_rx *tid_rx; 27 struct tid_ampdu_rx *tid_rx;
@@ -70,10 +71,17 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
70 71
71 spin_unlock_bh(&sta->lock); 72 spin_unlock_bh(&sta->lock);
72 73
73 del_timer_sync(&tid_rx->session_timer); 74 if (!from_timer)
75 del_timer_sync(&tid_rx->session_timer);
74 kfree(tid_rx); 76 kfree(tid_rx);
75} 77}
76 78
79void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
80 u16 initiator, u16 reason)
81{
82 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, false);
83}
84
77/* 85/*
78 * After accepting the AddBA Request we activated a timer, 86 * After accepting the AddBA Request we activated a timer,
79 * resetting it after each frame that arrives from the originator. 87 * resetting it after each frame that arrives from the originator.
@@ -92,8 +100,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
92#ifdef CONFIG_MAC80211_HT_DEBUG 100#ifdef CONFIG_MAC80211_HT_DEBUG
93 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); 101 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
94#endif 102#endif
95 __ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, 103 ___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT,
96 WLAN_REASON_QSTA_TIMEOUT); 104 WLAN_REASON_QSTA_TIMEOUT, true);
97} 105}
98 106
99static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, 107static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 608063f11797..c163d0a149f4 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -184,10 +184,9 @@ static void sta_addba_resp_timer_expired(unsigned long data)
184 HT_AGG_STATE_REQ_STOP_BA_MSK)) != 184 HT_AGG_STATE_REQ_STOP_BA_MSK)) !=
185 HT_ADDBA_REQUESTED_MSK) { 185 HT_ADDBA_REQUESTED_MSK) {
186 spin_unlock_bh(&sta->lock); 186 spin_unlock_bh(&sta->lock);
187 *state = HT_AGG_STATE_IDLE;
188#ifdef CONFIG_MAC80211_HT_DEBUG 187#ifdef CONFIG_MAC80211_HT_DEBUG
189 printk(KERN_DEBUG "timer expired on tid %d but we are not " 188 printk(KERN_DEBUG "timer expired on tid %d but we are not "
190 "(or no longer) expecting addBA response there", 189 "(or no longer) expecting addBA response there\n",
191 tid); 190 tid);
192#endif 191#endif
193 return; 192 return;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7dd7cda75cfa..ae37270a0633 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -97,9 +97,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
97 params->mesh_id_len, 97 params->mesh_id_len,
98 params->mesh_id); 98 params->mesh_id);
99 99
100 if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
101 return 0;
102
103 if (type == NL80211_IFTYPE_AP_VLAN && 100 if (type == NL80211_IFTYPE_AP_VLAN &&
104 params && params->use_4addr == 0) 101 params && params->use_4addr == 0)
105 rcu_assign_pointer(sdata->u.vlan.sta, NULL); 102 rcu_assign_pointer(sdata->u.vlan.sta, NULL);
@@ -107,7 +104,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
107 params && params->use_4addr >= 0) 104 params && params->use_4addr >= 0)
108 sdata->u.mgd.use_4addr = params->use_4addr; 105 sdata->u.mgd.use_4addr = params->use_4addr;
109 106
110 sdata->u.mntr_flags = *flags; 107 if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags)
108 sdata->u.mntr_flags = *flags;
109
111 return 0; 110 return 0;
112} 111}
113 112
@@ -411,6 +410,17 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
411 return ret; 410 return ret;
412} 411}
413 412
413static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
414 int idx, struct survey_info *survey)
415{
416 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
417
418 if (!local->ops->get_survey)
419 return -EOPNOTSUPP;
420
421 return drv_get_survey(local, idx, survey);
422}
423
414static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, 424static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
415 u8 *mac, struct station_info *sinfo) 425 u8 *mac, struct station_info *sinfo)
416{ 426{
@@ -1104,6 +1114,13 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
1104 changed |= BSS_CHANGED_BASIC_RATES; 1114 changed |= BSS_CHANGED_BASIC_RATES;
1105 } 1115 }
1106 1116
1117 if (params->ap_isolate >= 0) {
1118 if (params->ap_isolate)
1119 sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS;
1120 else
1121 sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS;
1122 }
1123
1107 ieee80211_bss_info_change_notify(sdata, changed); 1124 ieee80211_bss_info_change_notify(sdata, changed);
1108 1125
1109 return 0; 1126 return 0;
@@ -1388,11 +1405,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1388 return -EOPNOTSUPP; 1405 return -EOPNOTSUPP;
1389 1406
1390 if (enabled == sdata->u.mgd.powersave && 1407 if (enabled == sdata->u.mgd.powersave &&
1391 timeout == conf->dynamic_ps_timeout) 1408 timeout == conf->dynamic_ps_forced_timeout)
1392 return 0; 1409 return 0;
1393 1410
1394 sdata->u.mgd.powersave = enabled; 1411 sdata->u.mgd.powersave = enabled;
1395 conf->dynamic_ps_timeout = timeout; 1412 conf->dynamic_ps_forced_timeout = timeout;
1396 1413
1397 /* no change, but if automatic follow powersave */ 1414 /* no change, but if automatic follow powersave */
1398 mutex_lock(&sdata->u.mgd.mtx); 1415 mutex_lock(&sdata->u.mgd.mtx);
@@ -1508,6 +1525,7 @@ struct cfg80211_ops mac80211_config_ops = {
1508 .change_station = ieee80211_change_station, 1525 .change_station = ieee80211_change_station,
1509 .get_station = ieee80211_get_station, 1526 .get_station = ieee80211_get_station,
1510 .dump_station = ieee80211_dump_station, 1527 .dump_station = ieee80211_dump_station,
1528 .dump_survey = ieee80211_dump_survey,
1511#ifdef CONFIG_MAC80211_MESH 1529#ifdef CONFIG_MAC80211_MESH
1512 .add_mpath = ieee80211_add_mpath, 1530 .add_mpath = ieee80211_add_mpath,
1513 .del_mpath = ieee80211_del_mpath, 1531 .del_mpath = ieee80211_del_mpath,
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 6bc9b07c3eda..e763f1529ddb 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -39,6 +39,13 @@ static const struct file_operations sta_ ##name## _ops = { \
39 .open = mac80211_open_file_generic, \ 39 .open = mac80211_open_file_generic, \
40} 40}
41 41
42#define STA_OPS_RW(name) \
43static const struct file_operations sta_ ##name## _ops = { \
44 .read = sta_##name##_read, \
45 .write = sta_##name##_write, \
46 .open = mac80211_open_file_generic, \
47}
48
42#define STA_FILE(name, field, format) \ 49#define STA_FILE(name, field, format) \
43 STA_READ_##format(name, field) \ 50 STA_READ_##format(name, field) \
44 STA_OPS(name) 51 STA_OPS(name)
@@ -156,7 +163,63 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
156 163
157 return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); 164 return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
158} 165}
159STA_OPS(agg_status); 166
167static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf,
168 size_t count, loff_t *ppos)
169{
170 char _buf[12], *buf = _buf;
171 struct sta_info *sta = file->private_data;
172 bool start, tx;
173 unsigned long tid;
174 int ret;
175
176 if (count > sizeof(_buf))
177 return -EINVAL;
178
179 if (copy_from_user(buf, userbuf, count))
180 return -EFAULT;
181
182 buf[sizeof(_buf) - 1] = '\0';
183
184 if (strncmp(buf, "tx ", 3) == 0) {
185 buf += 3;
186 tx = true;
187 } else if (strncmp(buf, "rx ", 3) == 0) {
188 buf += 3;
189 tx = false;
190 } else
191 return -EINVAL;
192
193 if (strncmp(buf, "start ", 6) == 0) {
194 buf += 6;
195 start = true;
196 if (!tx)
197 return -EINVAL;
198 } else if (strncmp(buf, "stop ", 5) == 0) {
199 buf += 5;
200 start = false;
201 } else
202 return -EINVAL;
203
204 tid = simple_strtoul(buf, NULL, 0);
205
206 if (tid >= STA_TID_NUM)
207 return -EINVAL;
208
209 if (tx) {
210 if (start)
211 ret = ieee80211_start_tx_ba_session(&sta->sta, tid);
212 else
213 ret = ieee80211_stop_tx_ba_session(&sta->sta, tid,
214 WLAN_BACK_RECIPIENT);
215 } else {
216 __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3);
217 ret = 0;
218 }
219
220 return ret ?: count;
221}
222STA_OPS_RW(agg_status);
160 223
161static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, 224static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
162 size_t count, loff_t *ppos) 225 size_t count, loff_t *ppos)
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 9179196da264..ee8b63f92f71 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -152,14 +152,15 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local,
152} 152}
153 153
154static inline int drv_hw_scan(struct ieee80211_local *local, 154static inline int drv_hw_scan(struct ieee80211_local *local,
155 struct ieee80211_sub_if_data *sdata,
155 struct cfg80211_scan_request *req) 156 struct cfg80211_scan_request *req)
156{ 157{
157 int ret; 158 int ret;
158 159
159 might_sleep(); 160 might_sleep();
160 161
161 ret = local->ops->hw_scan(&local->hw, req); 162 ret = local->ops->hw_scan(&local->hw, &sdata->vif, req);
162 trace_drv_hw_scan(local, req, ret); 163 trace_drv_hw_scan(local, sdata, req, ret);
163 return ret; 164 return ret;
164} 165}
165 166
@@ -344,6 +345,15 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,
344 return ret; 345 return ret;
345} 346}
346 347
348static inline int drv_get_survey(struct ieee80211_local *local, int idx,
349 struct survey_info *survey)
350{
351 int ret = -EOPNOTSUPP;
352 if (local->ops->conf_tx)
353 ret = local->ops->get_survey(&local->hw, idx, survey);
354 /* trace_drv_get_survey(local, idx, survey, ret); */
355 return ret;
356}
347 357
348static inline void drv_rfkill_poll(struct ieee80211_local *local) 358static inline void drv_rfkill_poll(struct ieee80211_local *local)
349{ 359{
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index e209cb82ff29..ce734b58d07a 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -363,23 +363,26 @@ TRACE_EVENT(drv_update_tkip_key,
363 363
364TRACE_EVENT(drv_hw_scan, 364TRACE_EVENT(drv_hw_scan,
365 TP_PROTO(struct ieee80211_local *local, 365 TP_PROTO(struct ieee80211_local *local,
366 struct ieee80211_sub_if_data *sdata,
366 struct cfg80211_scan_request *req, int ret), 367 struct cfg80211_scan_request *req, int ret),
367 368
368 TP_ARGS(local, req, ret), 369 TP_ARGS(local, sdata, req, ret),
369 370
370 TP_STRUCT__entry( 371 TP_STRUCT__entry(
371 LOCAL_ENTRY 372 LOCAL_ENTRY
373 VIF_ENTRY
372 __field(int, ret) 374 __field(int, ret)
373 ), 375 ),
374 376
375 TP_fast_assign( 377 TP_fast_assign(
376 LOCAL_ASSIGN; 378 LOCAL_ASSIGN;
379 VIF_ASSIGN;
377 __entry->ret = ret; 380 __entry->ret = ret;
378 ), 381 ),
379 382
380 TP_printk( 383 TP_printk(
381 LOCAL_PR_FMT " ret:%d", 384 LOCAL_PR_FMT VIF_PR_FMT " ret:%d",
382 LOCAL_PR_ARG, __entry->ret 385 LOCAL_PR_ARG,VIF_PR_ARG, __entry->ret
383 ) 386 )
384); 387);
385 388
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index e6f3b0c7a71f..b72ee6435fa3 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -92,6 +92,12 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
92 if (memcmp(ifibss->bssid, bssid, ETH_ALEN)) 92 if (memcmp(ifibss->bssid, bssid, ETH_ALEN))
93 sta_info_flush(sdata->local, sdata); 93 sta_info_flush(sdata->local, sdata);
94 94
95 /* if merging, indicate to driver that we leave the old IBSS */
96 if (sdata->vif.bss_conf.ibss_joined) {
97 sdata->vif.bss_conf.ibss_joined = false;
98 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
99 }
100
95 memcpy(ifibss->bssid, bssid, ETH_ALEN); 101 memcpy(ifibss->bssid, bssid, ETH_ALEN);
96 102
97 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; 103 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
@@ -171,6 +177,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
171 bss_change |= BSS_CHANGED_BSSID; 177 bss_change |= BSS_CHANGED_BSSID;
172 bss_change |= BSS_CHANGED_BEACON; 178 bss_change |= BSS_CHANGED_BEACON;
173 bss_change |= BSS_CHANGED_BEACON_ENABLED; 179 bss_change |= BSS_CHANGED_BEACON_ENABLED;
180 bss_change |= BSS_CHANGED_IBSS;
181 sdata->vif.bss_conf.ibss_joined = true;
174 ieee80211_bss_info_change_notify(sdata, bss_change); 182 ieee80211_bss_info_change_notify(sdata, bss_change);
175 183
176 ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); 184 ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates);
@@ -481,7 +489,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
481 printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " 489 printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
482 "IBSS networks with same SSID (merge)\n", sdata->name); 490 "IBSS networks with same SSID (merge)\n", sdata->name);
483 491
484 ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); 492 ieee80211_request_internal_scan(sdata,
493 ifibss->ssid, ifibss->ssid_len,
494 ifibss->fixed_channel ? ifibss->channel : NULL);
485} 495}
486 496
487static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) 497static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -588,8 +598,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
588 printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " 598 printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
589 "join\n", sdata->name); 599 "join\n", sdata->name);
590 600
591 ieee80211_request_internal_scan(sdata, ifibss->ssid, 601 ieee80211_request_internal_scan(sdata,
592 ifibss->ssid_len); 602 ifibss->ssid, ifibss->ssid_len,
603 ifibss->fixed_channel ? ifibss->channel : NULL);
593 } else { 604 } else {
594 int interval = IEEE80211_SCAN_INTERVAL; 605 int interval = IEEE80211_SCAN_INTERVAL;
595 606
@@ -897,6 +908,12 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
897 sdata->u.ibss.channel = params->channel; 908 sdata->u.ibss.channel = params->channel;
898 sdata->u.ibss.fixed_channel = params->channel_fixed; 909 sdata->u.ibss.fixed_channel = params->channel_fixed;
899 910
911 /* fix ourselves to that channel now already */
912 if (params->channel_fixed) {
913 sdata->local->oper_channel = params->channel;
914 sdata->local->oper_channel_type = NL80211_CHAN_NO_HT;
915 }
916
900 if (params->ie) { 917 if (params->ie) {
901 sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, 918 sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len,
902 GFP_KERNEL); 919 GFP_KERNEL);
@@ -951,7 +968,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
951 kfree(sdata->u.ibss.ie); 968 kfree(sdata->u.ibss.ie);
952 skb = sdata->u.ibss.presp; 969 skb = sdata->u.ibss.presp;
953 rcu_assign_pointer(sdata->u.ibss.presp, NULL); 970 rcu_assign_pointer(sdata->u.ibss.presp, NULL);
954 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); 971 sdata->vif.bss_conf.ibss_joined = false;
972 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
973 BSS_CHANGED_IBSS);
955 synchronize_rcu(); 974 synchronize_rcu();
956 kfree_skb(skb); 975 kfree_skb(skb);
957 976
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c9712f35e596..cbaf4981e110 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1019,7 +1019,8 @@ void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata);
1019/* scan/BSS handling */ 1019/* scan/BSS handling */
1020void ieee80211_scan_work(struct work_struct *work); 1020void ieee80211_scan_work(struct work_struct *work);
1021int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, 1021int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
1022 const u8 *ssid, u8 ssid_len); 1022 const u8 *ssid, u8 ssid_len,
1023 struct ieee80211_channel *chan);
1023int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, 1024int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
1024 struct cfg80211_scan_request *req); 1025 struct cfg80211_scan_request *req);
1025void ieee80211_scan_cancel(struct ieee80211_local *local); 1026void ieee80211_scan_cancel(struct ieee80211_local *local);
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index e8f6e3b252d8..8d4b41787dcf 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -140,6 +140,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
140 struct ieee80211_sub_if_data, 140 struct ieee80211_sub_if_data,
141 u.ap); 141 u.ap);
142 142
143 key->conf.ap_addr = sdata->dev->dev_addr;
143 ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); 144 ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
144 145
145 if (!ret) { 146 if (!ret) {
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 011ee85bcd57..bd632e1ee2c5 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -442,7 +442,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
442 struct ieee80211_local *local = hw_to_local(hw); 442 struct ieee80211_local *local = hw_to_local(hw);
443 int result; 443 int result;
444 enum ieee80211_band band; 444 enum ieee80211_band band;
445 int channels, i, j, max_bitrates; 445 int channels, max_bitrates;
446 bool supp_ht; 446 bool supp_ht;
447 static const u32 cipher_suites[] = { 447 static const u32 cipher_suites[] = {
448 WLAN_CIPHER_SUITE_WEP40, 448 WLAN_CIPHER_SUITE_WEP40,
@@ -572,6 +572,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
572 572
573 local->hw.conf.listen_interval = local->hw.max_listen_interval; 573 local->hw.conf.listen_interval = local->hw.max_listen_interval;
574 574
575 local->hw.conf.dynamic_ps_forced_timeout = -1;
576
575 result = sta_info_start(local); 577 result = sta_info_start(local);
576 if (result < 0) 578 if (result < 0)
577 goto fail_sta_info; 579 goto fail_sta_info;
@@ -606,21 +608,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
606 608
607 ieee80211_led_init(local); 609 ieee80211_led_init(local);
608 610
609 /* alloc internal scan request */
610 i = 0;
611 local->int_scan_req->ssids = &local->scan_ssid;
612 local->int_scan_req->n_ssids = 1;
613 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
614 if (!hw->wiphy->bands[band])
615 continue;
616 for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
617 local->int_scan_req->channels[i] =
618 &hw->wiphy->bands[band]->channels[j];
619 i++;
620 }
621 }
622 local->int_scan_req->n_channels = i;
623
624 local->network_latency_notifier.notifier_call = 611 local->network_latency_notifier.notifier_call =
625 ieee80211_max_network_latency; 612 ieee80211_max_network_latency;
626 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, 613 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 35d850223a75..358226f63b81 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -175,6 +175,8 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
175 ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || 175 ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||
176 channel_type != local->hw.conf.channel_type; 176 channel_type != local->hw.conf.channel_type;
177 177
178 if (local->tmp_channel)
179 local->tmp_channel_type = channel_type;
178 local->oper_channel_type = channel_type; 180 local->oper_channel_type = channel_type;
179 181
180 if (ht_changed) { 182 if (ht_changed) {
@@ -476,6 +478,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
476{ 478{
477 struct ieee80211_sub_if_data *sdata, *found = NULL; 479 struct ieee80211_sub_if_data *sdata, *found = NULL;
478 int count = 0; 480 int count = 0;
481 int timeout;
479 482
480 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) { 483 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) {
481 local->ps_sdata = NULL; 484 local->ps_sdata = NULL;
@@ -509,6 +512,26 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
509 beaconint_us = ieee80211_tu_to_usec( 512 beaconint_us = ieee80211_tu_to_usec(
510 found->vif.bss_conf.beacon_int); 513 found->vif.bss_conf.beacon_int);
511 514
515 timeout = local->hw.conf.dynamic_ps_forced_timeout;
516 if (timeout < 0) {
517 /*
518 * The 2 second value is there for compatibility until
519 * the PM_QOS_NETWORK_LATENCY is configured with real
520 * values.
521 */
522 if (latency == 2000000000)
523 timeout = 100;
524 else if (latency <= 50000)
525 timeout = 300;
526 else if (latency <= 100000)
527 timeout = 100;
528 else if (latency <= 500000)
529 timeout = 50;
530 else
531 timeout = 0;
532 }
533 local->hw.conf.dynamic_ps_timeout = timeout;
534
512 if (beaconint_us > latency) { 535 if (beaconint_us > latency) {
513 local->ps_sdata = NULL; 536 local->ps_sdata = NULL;
514 } else { 537 } else {
@@ -1331,12 +1354,17 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1331 mutex_lock(&sdata->local->iflist_mtx); 1354 mutex_lock(&sdata->local->iflist_mtx);
1332 ieee80211_recalc_ps(sdata->local, -1); 1355 ieee80211_recalc_ps(sdata->local, -1);
1333 mutex_unlock(&sdata->local->iflist_mtx); 1356 mutex_unlock(&sdata->local->iflist_mtx);
1357
1358 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
1359 return;
1360
1334 /* 1361 /*
1335 * We've received a probe response, but are not sure whether 1362 * We've received a probe response, but are not sure whether
1336 * we have or will be receiving any beacons or data, so let's 1363 * we have or will be receiving any beacons or data, so let's
1337 * schedule the timers again, just in case. 1364 * schedule the timers again, just in case.
1338 */ 1365 */
1339 mod_beacon_timer(sdata); 1366 mod_beacon_timer(sdata);
1367
1340 mod_timer(&ifmgd->conn_mon_timer, 1368 mod_timer(&ifmgd->conn_mon_timer,
1341 round_jiffies_up(jiffies + 1369 round_jiffies_up(jiffies +
1342 IEEE80211_CONNECTION_IDLE_TIME)); 1370 IEEE80211_CONNECTION_IDLE_TIME));
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 72efbd87c1eb..9a08f2c446c6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -81,8 +81,6 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
81 len += 8; 81 len += 8;
82 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 82 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
83 len += 1; 83 len += 1;
84 if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
85 len += 1;
86 84
87 if (len & 1) /* padding for RX_FLAGS if necessary */ 85 if (len & 1) /* padding for RX_FLAGS if necessary */
88 len++; 86 len++;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index e1a3defdf581..e14c44195ae9 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -85,7 +85,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
85{ 85{
86 struct cfg80211_bss *cbss; 86 struct cfg80211_bss *cbss;
87 struct ieee80211_bss *bss; 87 struct ieee80211_bss *bss;
88 int clen; 88 int clen, srlen;
89 s32 signal = 0; 89 s32 signal = 0;
90 90
91 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 91 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
@@ -114,23 +114,24 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
114 bss->dtim_period = tim_ie->dtim_period; 114 bss->dtim_period = tim_ie->dtim_period;
115 } 115 }
116 116
117 bss->supp_rates_len = 0; 117 /* replace old supported rates if we get new values */
118 srlen = 0;
118 if (elems->supp_rates) { 119 if (elems->supp_rates) {
119 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; 120 clen = IEEE80211_MAX_SUPP_RATES;
120 if (clen > elems->supp_rates_len) 121 if (clen > elems->supp_rates_len)
121 clen = elems->supp_rates_len; 122 clen = elems->supp_rates_len;
122 memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, 123 memcpy(bss->supp_rates, elems->supp_rates, clen);
123 clen); 124 srlen += clen;
124 bss->supp_rates_len += clen;
125 } 125 }
126 if (elems->ext_supp_rates) { 126 if (elems->ext_supp_rates) {
127 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; 127 clen = IEEE80211_MAX_SUPP_RATES - srlen;
128 if (clen > elems->ext_supp_rates_len) 128 if (clen > elems->ext_supp_rates_len)
129 clen = elems->ext_supp_rates_len; 129 clen = elems->ext_supp_rates_len;
130 memcpy(&bss->supp_rates[bss->supp_rates_len], 130 memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen);
131 elems->ext_supp_rates, clen); 131 srlen += clen;
132 bss->supp_rates_len += clen;
133 } 132 }
133 if (srlen)
134 bss->supp_rates_len = srlen;
134 135
135 bss->wmm_used = elems->wmm_param || elems->wmm_info; 136 bss->wmm_used = elems->wmm_param || elems->wmm_info;
136 bss->uapsd_supported = is_uapsd_supported(elems); 137 bss->uapsd_supported = is_uapsd_supported(elems);
@@ -411,7 +412,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
411 412
412 if (local->ops->hw_scan) { 413 if (local->ops->hw_scan) {
413 WARN_ON(!ieee80211_prep_hw_scan(local)); 414 WARN_ON(!ieee80211_prep_hw_scan(local));
414 rc = drv_hw_scan(local, local->hw_scan_req); 415 rc = drv_hw_scan(local, sdata, local->hw_scan_req);
415 } else 416 } else
416 rc = ieee80211_start_sw_scan(local); 417 rc = ieee80211_start_sw_scan(local);
417 418
@@ -655,7 +656,7 @@ void ieee80211_scan_work(struct work_struct *work)
655 } 656 }
656 657
657 if (local->hw_scan_req) { 658 if (local->hw_scan_req) {
658 int rc = drv_hw_scan(local, local->hw_scan_req); 659 int rc = drv_hw_scan(local, sdata, local->hw_scan_req);
659 mutex_unlock(&local->scan_mtx); 660 mutex_unlock(&local->scan_mtx);
660 if (rc) 661 if (rc)
661 ieee80211_scan_completed(&local->hw, true); 662 ieee80211_scan_completed(&local->hw, true);
@@ -728,10 +729,12 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
728} 729}
729 730
730int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, 731int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
731 const u8 *ssid, u8 ssid_len) 732 const u8 *ssid, u8 ssid_len,
733 struct ieee80211_channel *chan)
732{ 734{
733 struct ieee80211_local *local = sdata->local; 735 struct ieee80211_local *local = sdata->local;
734 int ret = -EBUSY; 736 int ret = -EBUSY;
737 enum nl80211_band band;
735 738
736 mutex_lock(&local->scan_mtx); 739 mutex_lock(&local->scan_mtx);
737 740
@@ -739,6 +742,30 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
739 if (local->scan_req) 742 if (local->scan_req)
740 goto unlock; 743 goto unlock;
741 744
745 /* fill internal scan request */
746 if (!chan) {
747 int i, nchan = 0;
748
749 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
750 if (!local->hw.wiphy->bands[band])
751 continue;
752 for (i = 0;
753 i < local->hw.wiphy->bands[band]->n_channels;
754 i++) {
755 local->int_scan_req->channels[nchan] =
756 &local->hw.wiphy->bands[band]->channels[i];
757 nchan++;
758 }
759 }
760
761 local->int_scan_req->n_channels = nchan;
762 } else {
763 local->int_scan_req->channels[0] = chan;
764 local->int_scan_req->n_channels = 1;
765 }
766
767 local->int_scan_req->ssids = &local->scan_ssid;
768 local->int_scan_req->n_ssids = 1;
742 memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); 769 memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
743 local->int_scan_req->ssids[0].ssid_len = ssid_len; 770 local->int_scan_req->ssids[0].ssid_len = ssid_len;
744 771
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index ff0eb948917b..730197591ab5 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -575,7 +575,7 @@ static int sta_info_buffer_expired(struct sta_info *sta,
575} 575}
576 576
577 577
578static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, 578static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
579 struct sta_info *sta) 579 struct sta_info *sta)
580{ 580{
581 unsigned long flags; 581 unsigned long flags;
@@ -583,7 +583,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
583 struct ieee80211_sub_if_data *sdata; 583 struct ieee80211_sub_if_data *sdata;
584 584
585 if (skb_queue_empty(&sta->ps_tx_buf)) 585 if (skb_queue_empty(&sta->ps_tx_buf))
586 return; 586 return false;
587 587
588 for (;;) { 588 for (;;) {
589 spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); 589 spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
@@ -608,6 +608,8 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
608 if (skb_queue_empty(&sta->ps_tx_buf)) 608 if (skb_queue_empty(&sta->ps_tx_buf))
609 sta_info_clear_tim_bit(sta); 609 sta_info_clear_tim_bit(sta);
610 } 610 }
611
612 return true;
611} 613}
612 614
613static int __must_check __sta_info_destroy(struct sta_info *sta) 615static int __must_check __sta_info_destroy(struct sta_info *sta)
@@ -755,15 +757,20 @@ static void sta_info_cleanup(unsigned long data)
755{ 757{
756 struct ieee80211_local *local = (struct ieee80211_local *) data; 758 struct ieee80211_local *local = (struct ieee80211_local *) data;
757 struct sta_info *sta; 759 struct sta_info *sta;
760 bool timer_needed = false;
758 761
759 rcu_read_lock(); 762 rcu_read_lock();
760 list_for_each_entry_rcu(sta, &local->sta_list, list) 763 list_for_each_entry_rcu(sta, &local->sta_list, list)
761 sta_info_cleanup_expire_buffered(local, sta); 764 if (sta_info_cleanup_expire_buffered(local, sta))
765 timer_needed = true;
762 rcu_read_unlock(); 766 rcu_read_unlock();
763 767
764 if (local->quiescing) 768 if (local->quiescing)
765 return; 769 return;
766 770
771 if (!timer_needed)
772 return;
773
767 local->sta_cleanup.expires = 774 local->sta_cleanup.expires =
768 round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); 775 round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
769 add_timer(&local->sta_cleanup); 776 add_timer(&local->sta_cleanup);
@@ -848,8 +855,12 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
848 struct sta_info *sta, *nxt; 855 struct sta_info *sta, *nxt;
849 856
850 /* Just return a random station ... first in list ... */ 857 /* Just return a random station ... first in list ... */
851 for_each_sta_info(hw_to_local(hw), addr, sta, nxt) 858 for_each_sta_info(hw_to_local(hw), addr, sta, nxt) {
859 if (!sta->uploaded)
860 return NULL;
852 return &sta->sta; 861 return &sta->sta;
862 }
863
853 return NULL; 864 return NULL;
854} 865}
855EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); 866EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
@@ -857,14 +868,19 @@ EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
857struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, 868struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
858 const u8 *addr) 869 const u8 *addr)
859{ 870{
860 struct ieee80211_sub_if_data *sdata; 871 struct sta_info *sta;
861 872
862 if (!vif) 873 if (!vif)
863 return NULL; 874 return NULL;
864 875
865 sdata = vif_to_sdata(vif); 876 sta = sta_info_get_bss(vif_to_sdata(vif), addr);
877 if (!sta)
878 return NULL;
879
880 if (!sta->uploaded)
881 return NULL;
866 882
867 return ieee80211_find_sta_by_hw(&sdata->local->hw, addr); 883 return &sta->sta;
868} 884}
869EXPORT_SYMBOL(ieee80211_find_sta); 885EXPORT_SYMBOL(ieee80211_find_sta);
870 886
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 11805a3a626f..94613af009f3 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -171,6 +171,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
171 struct net_device *prev_dev = NULL; 171 struct net_device *prev_dev = NULL;
172 struct sta_info *sta, *tmp; 172 struct sta_info *sta, *tmp;
173 int retry_count = -1, i; 173 int retry_count = -1, i;
174 int rates_idx = -1;
174 bool send_to_cooked; 175 bool send_to_cooked;
175 176
176 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 177 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
@@ -178,6 +179,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
178 if (i >= hw->max_rates) { 179 if (i >= hw->max_rates) {
179 info->status.rates[i].idx = -1; 180 info->status.rates[i].idx = -1;
180 info->status.rates[i].count = 0; 181 info->status.rates[i].count = 0;
182 } else if (info->status.rates[i].idx >= 0) {
183 rates_idx = i;
181 } 184 }
182 185
183 retry_count += info->status.rates[i].count; 186 retry_count += info->status.rates[i].count;
@@ -206,6 +209,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
206 return; 209 return;
207 } 210 }
208 211
212 if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) &&
213 (rates_idx != -1))
214 sta->last_tx_rate = info->status.rates[rates_idx];
215
209 if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && 216 if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
210 (ieee80211_is_data_qos(fc))) { 217 (ieee80211_is_data_qos(fc))) {
211 u16 tid, ssn; 218 u16 tid, ssn;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 2cb77267f733..f3841f43249e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -429,6 +429,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
429 struct sta_info *sta = tx->sta; 429 struct sta_info *sta = tx->sta;
430 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 430 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
431 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 431 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
432 struct ieee80211_local *local = tx->local;
432 u32 staflags; 433 u32 staflags;
433 434
434 if (unlikely(!sta || 435 if (unlikely(!sta ||
@@ -476,6 +477,12 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
476 info->control.vif = &tx->sdata->vif; 477 info->control.vif = &tx->sdata->vif;
477 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 478 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
478 skb_queue_tail(&sta->ps_tx_buf, tx->skb); 479 skb_queue_tail(&sta->ps_tx_buf, tx->skb);
480
481 if (!timer_pending(&local->sta_cleanup))
482 mod_timer(&local->sta_cleanup,
483 round_jiffies(jiffies +
484 STA_INFO_CLEANUP_INTERVAL));
485
479 return TX_QUEUED; 486 return TX_QUEUED;
480 } 487 }
481#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG 488#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
@@ -586,7 +593,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
586 struct ieee80211_hdr *hdr = (void *)tx->skb->data; 593 struct ieee80211_hdr *hdr = (void *)tx->skb->data;
587 struct ieee80211_supported_band *sband; 594 struct ieee80211_supported_band *sband;
588 struct ieee80211_rate *rate; 595 struct ieee80211_rate *rate;
589 int i, len; 596 int i;
597 u32 len;
590 bool inval = false, rts = false, short_preamble = false; 598 bool inval = false, rts = false, short_preamble = false;
591 struct ieee80211_tx_rate_control txrc; 599 struct ieee80211_tx_rate_control txrc;
592 u32 sta_flags; 600 u32 sta_flags;
@@ -595,7 +603,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
595 603
596 sband = tx->local->hw.wiphy->bands[tx->channel->band]; 604 sband = tx->local->hw.wiphy->bands[tx->channel->band];
597 605
598 len = min_t(int, tx->skb->len + FCS_LEN, 606 len = min_t(u32, tx->skb->len + FCS_LEN,
599 tx->local->hw.wiphy->frag_threshold); 607 tx->local->hw.wiphy->frag_threshold);
600 608
601 /* set up the tx rate control struct we give the RC algo */ 609 /* set up the tx rate control struct we give the RC algo */
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index bdb1d05b16fc..3dd07600199d 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -213,15 +213,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
213 213
214 sband = local->hw.wiphy->bands[wk->chan->band]; 214 sband = local->hw.wiphy->bands[wk->chan->band];
215 215
216 /* 216 if (wk->assoc.supp_rates_len) {
217 * Get all rates supported by the device and the AP as 217 /*
218 * some APs don't like getting a superset of their rates 218 * Get all rates supported by the device and the AP as
219 * in the association request (e.g. D-Link DAP 1353 in 219 * some APs don't like getting a superset of their rates
220 * b-only mode)... 220 * in the association request (e.g. D-Link DAP 1353 in
221 */ 221 * b-only mode)...
222 rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, 222 */
223 wk->assoc.supp_rates_len, 223 rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates,
224 sband, &rates); 224 wk->assoc.supp_rates_len,
225 sband, &rates);
226 } else {
227 /*
228 * In case AP not provide any supported rates information
229 * before association, we send information element(s) with
230 * all rates that we support.
231 */
232 rates = ~0;
233 rates_len = sband->n_bitrates;
234 }
225 235
226 skb = alloc_skb(local->hw.extra_tx_headroom + 236 skb = alloc_skb(local->hw.extra_tx_headroom +
227 sizeof(*mgmt) + /* bit too much but doesn't matter */ 237 sizeof(*mgmt) + /* bit too much but doesn't matter */