diff options
author | Patrick McHardy <kaber@trash.net> | 2010-05-10 12:39:28 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-05-10 12:39:28 -0400 |
commit | 1e4b1057121bc756b91758a434b504d2010f6088 (patch) | |
tree | b016cf2c728289c7e36d9e4e488f30ab0bd0ae6e /net/mac80211 | |
parent | 3b254c54ec46eb022cb26ee6ab37fae23f5f7d6a (diff) | |
parent | 3ee943728fff536edaf8f59faa58aaa1aa7366e3 (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.c | 18 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 3 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 30 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 65 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 14 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 9 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 27 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/key.c | 1 | ||||
-rw-r--r-- | net/mac80211/main.c | 19 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 28 | ||||
-rw-r--r-- | net/mac80211/rx.c | 2 | ||||
-rw-r--r-- | net/mac80211/scan.c | 53 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 30 | ||||
-rw-r--r-- | net/mac80211/status.c | 7 | ||||
-rw-r--r-- | net/mac80211/tx.c | 12 | ||||
-rw-r--r-- | net/mac80211/work.c | 28 |
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 | ||
22 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 22 | static 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 | ||
79 | void __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 | ||
99 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 107 | static 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 | ||
413 | static 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 | |||
414 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 424 | static 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) \ | ||
43 | static 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 | } |
159 | STA_OPS(agg_status); | 166 | |
167 | static 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 | } | ||
222 | STA_OPS_RW(agg_status); | ||
160 | 223 | ||
161 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | 224 | static 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 | ||
154 | static inline int drv_hw_scan(struct ieee80211_local *local, | 154 | static 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 | ||
348 | static 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 | ||
348 | static inline void drv_rfkill_poll(struct ieee80211_local *local) | 358 | static 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 | ||
364 | TRACE_EVENT(drv_hw_scan, | 364 | TRACE_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 | ||
487 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 497 | static 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 */ |
1020 | void ieee80211_scan_work(struct work_struct *work); | 1020 | void ieee80211_scan_work(struct work_struct *work); |
1021 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | 1021 | int 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); | ||
1023 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 1024 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
1024 | struct cfg80211_scan_request *req); | 1025 | struct cfg80211_scan_request *req); |
1025 | void ieee80211_scan_cancel(struct ieee80211_local *local); | 1026 | void 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 | ||
730 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | 731 | int 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 | ||
578 | static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | 578 | static 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 | ||
613 | static int __must_check __sta_info_destroy(struct sta_info *sta) | 615 | static 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 | } |
855 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); | 866 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); |
@@ -857,14 +868,19 @@ EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); | |||
857 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, | 868 | struct 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 | } |
869 | EXPORT_SYMBOL(ieee80211_find_sta); | 885 | EXPORT_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 */ |