aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-05-05 16:14:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-05-05 16:14:16 -0400
commit83163244f845c296a118ce85c653872dbff6abfe (patch)
treece2eac695a1c198f23d537e20ed86c16ece21f7e /net/mac80211
parent0a12761bcd5646691c5d16dd93df84d1b8849285 (diff)
parentadfba3c7c026a6a5560d2a43fefc9b198cb74462 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: drivers/net/wireless/libertas_tf/cmd.c drivers/net/wireless/libertas_tf/main.c
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c18
-rw-r--r--net/mac80211/debugfs_sta.c65
-rw-r--r--net/mac80211/driver-ops.h5
-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/main.c19
-rw-r--r--net/mac80211/mlme.c21
-rw-r--r--net/mac80211/rx.c2
-rw-r--r--net/mac80211/scan.c53
-rw-r--r--net/mac80211/sta_info.c17
-rw-r--r--net/mac80211/status.c7
-rw-r--r--net/mac80211/tx.c5
-rw-r--r--net/mac80211/work.c28
14 files changed, 216 insertions, 63 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 845a6e6b9d89..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
@@ -1115,6 +1114,13 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
1115 changed |= BSS_CHANGED_BASIC_RATES; 1114 changed |= BSS_CHANGED_BASIC_RATES;
1116 } 1115 }
1117 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
1118 ieee80211_bss_info_change_notify(sdata, changed); 1124 ieee80211_bss_info_change_notify(sdata, changed);
1119 1125
1120 return 0; 1126 return 0;
@@ -1399,11 +1405,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1399 return -EOPNOTSUPP; 1405 return -EOPNOTSUPP;
1400 1406
1401 if (enabled == sdata->u.mgd.powersave && 1407 if (enabled == sdata->u.mgd.powersave &&
1402 timeout == conf->dynamic_ps_timeout) 1408 timeout == conf->dynamic_ps_forced_timeout)
1403 return 0; 1409 return 0;
1404 1410
1405 sdata->u.mgd.powersave = enabled; 1411 sdata->u.mgd.powersave = enabled;
1406 conf->dynamic_ps_timeout = timeout; 1412 conf->dynamic_ps_forced_timeout = timeout;
1407 1413
1408 /* no change, but if automatic follow powersave */ 1414 /* no change, but if automatic follow powersave */
1409 mutex_lock(&sdata->u.mgd.mtx); 1415 mutex_lock(&sdata->u.mgd.mtx);
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 35e1e581e806..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
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/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 425f66c70013..358226f63b81 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -478,6 +478,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
478{ 478{
479 struct ieee80211_sub_if_data *sdata, *found = NULL; 479 struct ieee80211_sub_if_data *sdata, *found = NULL;
480 int count = 0; 480 int count = 0;
481 int timeout;
481 482
482 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) { 483 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) {
483 local->ps_sdata = NULL; 484 local->ps_sdata = NULL;
@@ -511,6 +512,26 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
511 beaconint_us = ieee80211_tu_to_usec( 512 beaconint_us = ieee80211_tu_to_usec(
512 found->vif.bss_conf.beacon_int); 513 found->vif.bss_conf.beacon_int);
513 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
514 if (beaconint_us > latency) { 535 if (beaconint_us > latency) {
515 local->ps_sdata = NULL; 536 local->ps_sdata = NULL;
516 } else { 537 } else {
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 3de7a2260d65..730197591ab5 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -855,8 +855,12 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
855 struct sta_info *sta, *nxt; 855 struct sta_info *sta, *nxt;
856 856
857 /* Just return a random station ... first in list ... */ 857 /* Just return a random station ... first in list ... */
858 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;
859 return &sta->sta; 861 return &sta->sta;
862 }
863
860 return NULL; 864 return NULL;
861} 865}
862EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); 866EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
@@ -864,14 +868,19 @@ EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
864struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, 868struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
865 const u8 *addr) 869 const u8 *addr)
866{ 870{
867 struct ieee80211_sub_if_data *sdata; 871 struct sta_info *sta;
868 872
869 if (!vif) 873 if (!vif)
870 return NULL; 874 return NULL;
871 875
872 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;
873 882
874 return ieee80211_find_sta_by_hw(&sdata->local->hw, addr); 883 return &sta->sta;
875} 884}
876EXPORT_SYMBOL(ieee80211_find_sta); 885EXPORT_SYMBOL(ieee80211_find_sta);
877 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 e2aa972d584f..f3841f43249e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -593,7 +593,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
593 struct ieee80211_hdr *hdr = (void *)tx->skb->data; 593 struct ieee80211_hdr *hdr = (void *)tx->skb->data;
594 struct ieee80211_supported_band *sband; 594 struct ieee80211_supported_band *sband;
595 struct ieee80211_rate *rate; 595 struct ieee80211_rate *rate;
596 int i, len; 596 int i;
597 u32 len;
597 bool inval = false, rts = false, short_preamble = false; 598 bool inval = false, rts = false, short_preamble = false;
598 struct ieee80211_tx_rate_control txrc; 599 struct ieee80211_tx_rate_control txrc;
599 u32 sta_flags; 600 u32 sta_flags;
@@ -602,7 +603,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
602 603
603 sband = tx->local->hw.wiphy->bands[tx->channel->band]; 604 sband = tx->local->hw.wiphy->bands[tx->channel->band];
604 605
605 len = min_t(int, tx->skb->len + FCS_LEN, 606 len = min_t(u32, tx->skb->len + FCS_LEN,
606 tx->local->hw.wiphy->frag_threshold); 607 tx->local->hw.wiphy->frag_threshold);
607 608
608 /* 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 */