diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-03-16 13:45:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-03-16 13:45:25 -0400 |
commit | 01a282980937f9ca55a3cb06b9c6ff1cc49ea396 (patch) | |
tree | 07a043edc861e245a7a9764751af0898a1f1199a /net | |
parent | d5ddb4a59ed43b4c569b4efa8b508d50ef140cc6 (diff) | |
parent | 377526578f2c343ea281a918b18ece1fca65005c (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/ath/ath9k/hw.c
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/chan.c | 27 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 81 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 71 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 35 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 45 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 34 | ||||
-rw-r--r-- | net/mac80211/main.c | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 382 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 16 | ||||
-rw-r--r-- | net/mac80211/rx.c | 21 | ||||
-rw-r--r-- | net/mac80211/tx.c | 10 | ||||
-rw-r--r-- | net/mac80211/wep.c | 21 | ||||
-rw-r--r-- | net/mac80211/wep.h | 1 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 22 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 8 | ||||
-rw-r--r-- | net/wireless/scan.c | 7 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 3 |
17 files changed, 355 insertions, 431 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index d1f7abddb182..e00ce8c3e28e 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -3,6 +3,7 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/nl80211.h> | 5 | #include <linux/nl80211.h> |
6 | #include <net/cfg80211.h> | ||
6 | #include "ieee80211_i.h" | 7 | #include "ieee80211_i.h" |
7 | 8 | ||
8 | static enum ieee80211_chan_mode | 9 | static enum ieee80211_chan_mode |
@@ -134,3 +135,29 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
134 | 135 | ||
135 | return result; | 136 | return result; |
136 | } | 137 | } |
138 | |||
139 | /* | ||
140 | * ieee80211_get_tx_channel_type returns the channel type we should | ||
141 | * use for packet transmission, given the channel capability and | ||
142 | * whatever regulatory flags we have been given. | ||
143 | */ | ||
144 | enum nl80211_channel_type ieee80211_get_tx_channel_type( | ||
145 | struct ieee80211_local *local, | ||
146 | enum nl80211_channel_type channel_type) | ||
147 | { | ||
148 | switch (channel_type) { | ||
149 | case NL80211_CHAN_HT40PLUS: | ||
150 | if (local->hw.conf.channel->flags & | ||
151 | IEEE80211_CHAN_NO_HT40PLUS) | ||
152 | return NL80211_CHAN_HT20; | ||
153 | break; | ||
154 | case NL80211_CHAN_HT40MINUS: | ||
155 | if (local->hw.conf.channel->flags & | ||
156 | IEEE80211_CHAN_NO_HT40MINUS) | ||
157 | return NL80211_CHAN_HT20; | ||
158 | break; | ||
159 | default: | ||
160 | break; | ||
161 | } | ||
162 | return channel_type; | ||
163 | } | ||
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 483e96ed95c1..cc5b7a6e7e0b 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -97,85 +97,6 @@ static const struct file_operations reset_ops = { | |||
97 | .llseek = noop_llseek, | 97 | .llseek = noop_llseek, |
98 | }; | 98 | }; |
99 | 99 | ||
100 | static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf, | ||
101 | size_t count, loff_t *ppos) | ||
102 | { | ||
103 | struct ieee80211_local *local = file->private_data; | ||
104 | return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n", | ||
105 | local->uapsd_queues); | ||
106 | } | ||
107 | |||
108 | static ssize_t uapsd_queues_write(struct file *file, | ||
109 | const char __user *user_buf, | ||
110 | size_t count, loff_t *ppos) | ||
111 | { | ||
112 | struct ieee80211_local *local = file->private_data; | ||
113 | u8 val; | ||
114 | int ret; | ||
115 | |||
116 | ret = kstrtou8_from_user(user_buf, count, 0, &val); | ||
117 | if (ret) | ||
118 | return ret; | ||
119 | |||
120 | if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) | ||
121 | return -ERANGE; | ||
122 | |||
123 | local->uapsd_queues = val; | ||
124 | |||
125 | return count; | ||
126 | } | ||
127 | |||
128 | static const struct file_operations uapsd_queues_ops = { | ||
129 | .read = uapsd_queues_read, | ||
130 | .write = uapsd_queues_write, | ||
131 | .open = mac80211_open_file_generic, | ||
132 | .llseek = default_llseek, | ||
133 | }; | ||
134 | |||
135 | static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf, | ||
136 | size_t count, loff_t *ppos) | ||
137 | { | ||
138 | struct ieee80211_local *local = file->private_data; | ||
139 | |||
140 | return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n", | ||
141 | local->uapsd_max_sp_len); | ||
142 | } | ||
143 | |||
144 | static ssize_t uapsd_max_sp_len_write(struct file *file, | ||
145 | const char __user *user_buf, | ||
146 | size_t count, loff_t *ppos) | ||
147 | { | ||
148 | struct ieee80211_local *local = file->private_data; | ||
149 | unsigned long val; | ||
150 | char buf[10]; | ||
151 | size_t len; | ||
152 | int ret; | ||
153 | |||
154 | len = min(count, sizeof(buf) - 1); | ||
155 | if (copy_from_user(buf, user_buf, len)) | ||
156 | return -EFAULT; | ||
157 | buf[len] = '\0'; | ||
158 | |||
159 | ret = kstrtoul(buf, 0, &val); | ||
160 | |||
161 | if (ret) | ||
162 | return -EINVAL; | ||
163 | |||
164 | if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) | ||
165 | return -ERANGE; | ||
166 | |||
167 | local->uapsd_max_sp_len = val; | ||
168 | |||
169 | return count; | ||
170 | } | ||
171 | |||
172 | static const struct file_operations uapsd_max_sp_len_ops = { | ||
173 | .read = uapsd_max_sp_len_read, | ||
174 | .write = uapsd_max_sp_len_write, | ||
175 | .open = mac80211_open_file_generic, | ||
176 | .llseek = default_llseek, | ||
177 | }; | ||
178 | |||
179 | static ssize_t channel_type_read(struct file *file, char __user *user_buf, | 100 | static ssize_t channel_type_read(struct file *file, char __user *user_buf, |
180 | size_t count, loff_t *ppos) | 101 | size_t count, loff_t *ppos) |
181 | { | 102 | { |
@@ -362,8 +283,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
362 | DEBUGFS_ADD(wep_iv); | 283 | DEBUGFS_ADD(wep_iv); |
363 | DEBUGFS_ADD(queues); | 284 | DEBUGFS_ADD(queues); |
364 | DEBUGFS_ADD_MODE(reset, 0200); | 285 | DEBUGFS_ADD_MODE(reset, 0200); |
365 | DEBUGFS_ADD(uapsd_queues); | ||
366 | DEBUGFS_ADD(uapsd_max_sp_len); | ||
367 | DEBUGFS_ADD(channel_type); | 286 | DEBUGFS_ADD(channel_type); |
368 | DEBUGFS_ADD(hwflags); | 287 | DEBUGFS_ADD(hwflags); |
369 | DEBUGFS_ADD(user_power); | 288 | DEBUGFS_ADD(user_power); |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index f6de8a65f402..a32eeda04aa3 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -49,16 +49,15 @@ static ssize_t ieee80211_if_write( | |||
49 | size_t count, loff_t *ppos, | 49 | size_t count, loff_t *ppos, |
50 | ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) | 50 | ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) |
51 | { | 51 | { |
52 | u8 *buf; | 52 | char buf[64]; |
53 | ssize_t ret; | 53 | ssize_t ret; |
54 | 54 | ||
55 | buf = kmalloc(count, GFP_KERNEL); | 55 | if (count >= sizeof(buf)) |
56 | if (!buf) | 56 | return -E2BIG; |
57 | return -ENOMEM; | ||
58 | 57 | ||
59 | ret = -EFAULT; | ||
60 | if (copy_from_user(buf, userbuf, count)) | 58 | if (copy_from_user(buf, userbuf, count)) |
61 | goto freebuf; | 59 | return -EFAULT; |
60 | buf[count] = '\0'; | ||
62 | 61 | ||
63 | ret = -ENODEV; | 62 | ret = -ENODEV; |
64 | rtnl_lock(); | 63 | rtnl_lock(); |
@@ -66,8 +65,6 @@ static ssize_t ieee80211_if_write( | |||
66 | ret = (*write)(sdata, buf, count); | 65 | ret = (*write)(sdata, buf, count); |
67 | rtnl_unlock(); | 66 | rtnl_unlock(); |
68 | 67 | ||
69 | freebuf: | ||
70 | kfree(buf); | ||
71 | return ret; | 68 | return ret; |
72 | } | 69 | } |
73 | 70 | ||
@@ -340,6 +337,62 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( | |||
340 | 337 | ||
341 | __IEEE80211_IF_FILE_W(tkip_mic_test); | 338 | __IEEE80211_IF_FILE_W(tkip_mic_test); |
342 | 339 | ||
340 | static ssize_t ieee80211_if_fmt_uapsd_queues( | ||
341 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | ||
342 | { | ||
343 | const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
344 | |||
345 | return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_queues); | ||
346 | } | ||
347 | |||
348 | static ssize_t ieee80211_if_parse_uapsd_queues( | ||
349 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) | ||
350 | { | ||
351 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
352 | u8 val; | ||
353 | int ret; | ||
354 | |||
355 | ret = kstrtou8(buf, 0, &val); | ||
356 | if (ret) | ||
357 | return ret; | ||
358 | |||
359 | if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) | ||
360 | return -ERANGE; | ||
361 | |||
362 | ifmgd->uapsd_queues = val; | ||
363 | |||
364 | return buflen; | ||
365 | } | ||
366 | __IEEE80211_IF_FILE_W(uapsd_queues); | ||
367 | |||
368 | static ssize_t ieee80211_if_fmt_uapsd_max_sp_len( | ||
369 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | ||
370 | { | ||
371 | const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
372 | |||
373 | return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_max_sp_len); | ||
374 | } | ||
375 | |||
376 | static ssize_t ieee80211_if_parse_uapsd_max_sp_len( | ||
377 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) | ||
378 | { | ||
379 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
380 | unsigned long val; | ||
381 | int ret; | ||
382 | |||
383 | ret = kstrtoul(buf, 0, &val); | ||
384 | if (ret) | ||
385 | return -EINVAL; | ||
386 | |||
387 | if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) | ||
388 | return -ERANGE; | ||
389 | |||
390 | ifmgd->uapsd_max_sp_len = val; | ||
391 | |||
392 | return buflen; | ||
393 | } | ||
394 | __IEEE80211_IF_FILE_W(uapsd_max_sp_len); | ||
395 | |||
343 | /* AP attributes */ | 396 | /* AP attributes */ |
344 | IEEE80211_IF_FILE(num_sta_authorized, u.ap.num_sta_authorized, ATOMIC); | 397 | IEEE80211_IF_FILE(num_sta_authorized, u.ap.num_sta_authorized, ATOMIC); |
345 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 398 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
@@ -472,6 +525,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
472 | DEBUGFS_ADD(ave_beacon); | 525 | DEBUGFS_ADD(ave_beacon); |
473 | DEBUGFS_ADD_MODE(smps, 0600); | 526 | DEBUGFS_ADD_MODE(smps, 0600); |
474 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | 527 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); |
528 | DEBUGFS_ADD_MODE(uapsd_queues, 0600); | ||
529 | DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600); | ||
475 | } | 530 | } |
476 | 531 | ||
477 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 532 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 70dfb6415c20..af4691fed645 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -168,41 +168,6 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
168 | trace_drv_return_void(local); | 168 | trace_drv_return_void(local); |
169 | } | 169 | } |
170 | 170 | ||
171 | static inline int drv_tx_sync(struct ieee80211_local *local, | ||
172 | struct ieee80211_sub_if_data *sdata, | ||
173 | const u8 *bssid, | ||
174 | enum ieee80211_tx_sync_type type) | ||
175 | { | ||
176 | int ret = 0; | ||
177 | |||
178 | might_sleep(); | ||
179 | |||
180 | check_sdata_in_driver(sdata); | ||
181 | |||
182 | trace_drv_tx_sync(local, sdata, bssid, type); | ||
183 | if (local->ops->tx_sync) | ||
184 | ret = local->ops->tx_sync(&local->hw, &sdata->vif, | ||
185 | bssid, type); | ||
186 | trace_drv_return_int(local, ret); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static inline void drv_finish_tx_sync(struct ieee80211_local *local, | ||
191 | struct ieee80211_sub_if_data *sdata, | ||
192 | const u8 *bssid, | ||
193 | enum ieee80211_tx_sync_type type) | ||
194 | { | ||
195 | might_sleep(); | ||
196 | |||
197 | check_sdata_in_driver(sdata); | ||
198 | |||
199 | trace_drv_finish_tx_sync(local, sdata, bssid, type); | ||
200 | if (local->ops->finish_tx_sync) | ||
201 | local->ops->finish_tx_sync(&local->hw, &sdata->vif, | ||
202 | bssid, type); | ||
203 | trace_drv_return_void(local); | ||
204 | } | ||
205 | |||
206 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | 171 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, |
207 | struct netdev_hw_addr_list *mc_list) | 172 | struct netdev_hw_addr_list *mc_list) |
208 | { | 173 | { |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 384e2f08c187..21d6f5290a1c 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -296,7 +296,7 @@ TRACE_EVENT(drv_bss_info_changed, | |||
296 | __entry->dtimper = info->dtim_period; | 296 | __entry->dtimper = info->dtim_period; |
297 | __entry->bcnint = info->beacon_int; | 297 | __entry->bcnint = info->beacon_int; |
298 | __entry->assoc_cap = info->assoc_capability; | 298 | __entry->assoc_cap = info->assoc_capability; |
299 | __entry->timestamp = info->timestamp; | 299 | __entry->timestamp = info->last_tsf; |
300 | __entry->basic_rates = info->basic_rates; | 300 | __entry->basic_rates = info->basic_rates; |
301 | __entry->enable_beacon = info->enable_beacon; | 301 | __entry->enable_beacon = info->enable_beacon; |
302 | __entry->ht_operation_mode = info->ht_operation_mode; | 302 | __entry->ht_operation_mode = info->ht_operation_mode; |
@@ -308,49 +308,6 @@ TRACE_EVENT(drv_bss_info_changed, | |||
308 | ) | 308 | ) |
309 | ); | 309 | ); |
310 | 310 | ||
311 | DECLARE_EVENT_CLASS(tx_sync_evt, | ||
312 | TP_PROTO(struct ieee80211_local *local, | ||
313 | struct ieee80211_sub_if_data *sdata, | ||
314 | const u8 *bssid, | ||
315 | enum ieee80211_tx_sync_type type), | ||
316 | TP_ARGS(local, sdata, bssid, type), | ||
317 | |||
318 | TP_STRUCT__entry( | ||
319 | LOCAL_ENTRY | ||
320 | VIF_ENTRY | ||
321 | __array(char, bssid, ETH_ALEN) | ||
322 | __field(u32, sync_type) | ||
323 | ), | ||
324 | |||
325 | TP_fast_assign( | ||
326 | LOCAL_ASSIGN; | ||
327 | VIF_ASSIGN; | ||
328 | memcpy(__entry->bssid, bssid, ETH_ALEN); | ||
329 | __entry->sync_type = type; | ||
330 | ), | ||
331 | |||
332 | TP_printk( | ||
333 | LOCAL_PR_FMT VIF_PR_FMT " bssid:%pM type:%d", | ||
334 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->bssid, __entry->sync_type | ||
335 | ) | ||
336 | ); | ||
337 | |||
338 | DEFINE_EVENT(tx_sync_evt, drv_tx_sync, | ||
339 | TP_PROTO(struct ieee80211_local *local, | ||
340 | struct ieee80211_sub_if_data *sdata, | ||
341 | const u8 *bssid, | ||
342 | enum ieee80211_tx_sync_type type), | ||
343 | TP_ARGS(local, sdata, bssid, type) | ||
344 | ); | ||
345 | |||
346 | DEFINE_EVENT(tx_sync_evt, drv_finish_tx_sync, | ||
347 | TP_PROTO(struct ieee80211_local *local, | ||
348 | struct ieee80211_sub_if_data *sdata, | ||
349 | const u8 *bssid, | ||
350 | enum ieee80211_tx_sync_type type), | ||
351 | TP_ARGS(local, sdata, bssid, type) | ||
352 | ); | ||
353 | |||
354 | TRACE_EVENT(drv_prepare_multicast, | 311 | TRACE_EVENT(drv_prepare_multicast, |
355 | TP_PROTO(struct ieee80211_local *local, int mc_count), | 312 | TP_PROTO(struct ieee80211_local *local, int mc_count), |
356 | 313 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 796b13bfc953..d9798a307f20 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -388,7 +388,6 @@ struct ieee80211_mgd_auth_data { | |||
388 | 388 | ||
389 | u8 key[WLAN_KEY_LEN_WEP104]; | 389 | u8 key[WLAN_KEY_LEN_WEP104]; |
390 | u8 key_len, key_idx; | 390 | u8 key_len, key_idx; |
391 | bool synced; | ||
392 | bool done; | 391 | bool done; |
393 | 392 | ||
394 | size_t ie_len; | 393 | size_t ie_len; |
@@ -408,7 +407,7 @@ struct ieee80211_mgd_assoc_data { | |||
408 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 407 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
409 | u8 ssid_len; | 408 | u8 ssid_len; |
410 | u8 supp_rates_len; | 409 | u8 supp_rates_len; |
411 | bool wmm_used, uapsd_used; | 410 | bool wmm, uapsd; |
412 | bool have_beacon; | 411 | bool have_beacon; |
413 | bool sent_assoc; | 412 | bool sent_assoc; |
414 | bool synced; | 413 | bool synced; |
@@ -460,6 +459,20 @@ struct ieee80211_if_managed { | |||
460 | IEEE80211_MFP_REQUIRED | 459 | IEEE80211_MFP_REQUIRED |
461 | } mfp; /* management frame protection */ | 460 | } mfp; /* management frame protection */ |
462 | 461 | ||
462 | /* | ||
463 | * Bitmask of enabled u-apsd queues, | ||
464 | * IEEE80211_WMM_IE_STA_QOSINFO_AC_BE & co. Needs a new association | ||
465 | * to take effect. | ||
466 | */ | ||
467 | unsigned int uapsd_queues; | ||
468 | |||
469 | /* | ||
470 | * Maximum number of buffered frames AP can deliver during a | ||
471 | * service period, IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL or similar. | ||
472 | * Needs a new association to take effect. | ||
473 | */ | ||
474 | unsigned int uapsd_max_sp_len; | ||
475 | |||
463 | int wmm_last_param_set; | 476 | int wmm_last_param_set; |
464 | 477 | ||
465 | u8 use_4addr; | 478 | u8 use_4addr; |
@@ -1018,20 +1031,6 @@ struct ieee80211_local { | |||
1018 | */ | 1031 | */ |
1019 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ | 1032 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ |
1020 | 1033 | ||
1021 | /* | ||
1022 | * Bitmask of enabled u-apsd queues, | ||
1023 | * IEEE80211_WMM_IE_STA_QOSINFO_AC_BE & co. Needs a new association | ||
1024 | * to take effect. | ||
1025 | */ | ||
1026 | unsigned int uapsd_queues; | ||
1027 | |||
1028 | /* | ||
1029 | * Maximum number of buffered frames AP can deliver during a | ||
1030 | * service period, IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL or similar. | ||
1031 | * Needs a new association to take effect. | ||
1032 | */ | ||
1033 | unsigned int uapsd_max_sp_len; | ||
1034 | |||
1035 | bool pspolling; | 1034 | bool pspolling; |
1036 | bool offchannel_ps_enabled; | 1035 | bool offchannel_ps_enabled; |
1037 | /* | 1036 | /* |
@@ -1503,6 +1502,9 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
1503 | enum nl80211_channel_type chantype); | 1502 | enum nl80211_channel_type chantype); |
1504 | enum nl80211_channel_type | 1503 | enum nl80211_channel_type |
1505 | ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info); | 1504 | ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info); |
1505 | enum nl80211_channel_type ieee80211_get_tx_channel_type( | ||
1506 | struct ieee80211_local *local, | ||
1507 | enum nl80211_channel_type channel_type); | ||
1506 | 1508 | ||
1507 | #ifdef CONFIG_MAC80211_NOINLINE | 1509 | #ifdef CONFIG_MAC80211_NOINLINE |
1508 | #define debug_noinline noinline | 1510 | #define debug_noinline noinline |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 36fa8051296c..b581a24fa15c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -595,8 +595,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
595 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 595 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
596 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 596 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
597 | local->user_power_level = -1; | 597 | local->user_power_level = -1; |
598 | local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; | ||
599 | local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; | ||
600 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; | 598 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; |
601 | 599 | ||
602 | INIT_LIST_HEAD(&local->interfaces); | 600 | INIT_LIST_HEAD(&local->interfaces); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c08924aeac00..576fb25456dd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -189,40 +189,35 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
189 | u16 ht_opmode; | 189 | u16 ht_opmode; |
190 | bool enable_ht = true; | 190 | bool enable_ht = true; |
191 | enum nl80211_channel_type prev_chantype; | 191 | enum nl80211_channel_type prev_chantype; |
192 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 192 | enum nl80211_channel_type rx_channel_type = NL80211_CHAN_NO_HT; |
193 | enum nl80211_channel_type tx_channel_type; | ||
193 | 194 | ||
194 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 195 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
195 | |||
196 | prev_chantype = sdata->vif.bss_conf.channel_type; | 196 | prev_chantype = sdata->vif.bss_conf.channel_type; |
197 | 197 | ||
198 | /* HT is not supported */ | ||
199 | if (!sband->ht_cap.ht_supported) | ||
200 | enable_ht = false; | ||
201 | 198 | ||
202 | if (enable_ht) { | 199 | hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan, |
203 | hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan, | 200 | sband->band); |
204 | sband->band); | 201 | /* check that channel matches the right operating channel */ |
205 | /* check that channel matches the right operating channel */ | 202 | if (local->hw.conf.channel->center_freq != hti_cfreq) { |
206 | if (local->hw.conf.channel->center_freq != hti_cfreq) { | 203 | /* Some APs mess this up, evidently. |
207 | /* Some APs mess this up, evidently. | 204 | * Netgear WNDR3700 sometimes reports 4 higher than |
208 | * Netgear WNDR3700 sometimes reports 4 higher than | 205 | * the actual channel, for instance. |
209 | * the actual channel, for instance. | 206 | */ |
210 | */ | 207 | printk(KERN_DEBUG |
211 | printk(KERN_DEBUG | 208 | "%s: Wrong control channel in association" |
212 | "%s: Wrong control channel in association" | 209 | " response: configured center-freq: %d" |
213 | " response: configured center-freq: %d" | 210 | " hti-cfreq: %d hti->control_chan: %d" |
214 | " hti-cfreq: %d hti->control_chan: %d" | 211 | " band: %d. Disabling HT.\n", |
215 | " band: %d. Disabling HT.\n", | 212 | sdata->name, |
216 | sdata->name, | 213 | local->hw.conf.channel->center_freq, |
217 | local->hw.conf.channel->center_freq, | 214 | hti_cfreq, hti->control_chan, |
218 | hti_cfreq, hti->control_chan, | 215 | sband->band); |
219 | sband->band); | 216 | enable_ht = false; |
220 | enable_ht = false; | ||
221 | } | ||
222 | } | 217 | } |
223 | 218 | ||
224 | if (enable_ht) { | 219 | if (enable_ht) { |
225 | channel_type = NL80211_CHAN_HT20; | 220 | rx_channel_type = NL80211_CHAN_HT20; |
226 | 221 | ||
227 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | 222 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && |
228 | !ieee80111_cfg_override_disables_ht40(sdata) && | 223 | !ieee80111_cfg_override_disables_ht40(sdata) && |
@@ -230,29 +225,28 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
230 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { | 225 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { |
231 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 226 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
232 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 227 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
233 | if (!(local->hw.conf.channel->flags & | 228 | rx_channel_type = NL80211_CHAN_HT40PLUS; |
234 | IEEE80211_CHAN_NO_HT40PLUS)) | ||
235 | channel_type = NL80211_CHAN_HT40PLUS; | ||
236 | break; | 229 | break; |
237 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | 230 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: |
238 | if (!(local->hw.conf.channel->flags & | 231 | rx_channel_type = NL80211_CHAN_HT40MINUS; |
239 | IEEE80211_CHAN_NO_HT40MINUS)) | ||
240 | channel_type = NL80211_CHAN_HT40MINUS; | ||
241 | break; | 232 | break; |
242 | } | 233 | } |
243 | } | 234 | } |
244 | } | 235 | } |
245 | 236 | ||
237 | tx_channel_type = ieee80211_get_tx_channel_type(local, rx_channel_type); | ||
238 | |||
246 | if (local->tmp_channel) | 239 | if (local->tmp_channel) |
247 | local->tmp_channel_type = channel_type; | 240 | local->tmp_channel_type = rx_channel_type; |
248 | 241 | ||
249 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | 242 | if (!ieee80211_set_channel_type(local, sdata, rx_channel_type)) { |
250 | /* can only fail due to HT40+/- mismatch */ | 243 | /* can only fail due to HT40+/- mismatch */ |
251 | channel_type = NL80211_CHAN_HT20; | 244 | rx_channel_type = NL80211_CHAN_HT20; |
252 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); | 245 | WARN_ON(!ieee80211_set_channel_type(local, sdata, |
246 | rx_channel_type)); | ||
253 | } | 247 | } |
254 | 248 | ||
255 | if (beacon_htcap_ie && (prev_chantype != channel_type)) { | 249 | if (beacon_htcap_ie && (prev_chantype != rx_channel_type)) { |
256 | /* | 250 | /* |
257 | * Whenever the AP announces the HT mode change that can be | 251 | * Whenever the AP announces the HT mode change that can be |
258 | * 40MHz intolerant or etc., it would be safer to stop tx | 252 | * 40MHz intolerant or etc., it would be safer to stop tx |
@@ -270,13 +264,13 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
270 | /* channel_type change automatically detected */ | 264 | /* channel_type change automatically detected */ |
271 | ieee80211_hw_config(local, 0); | 265 | ieee80211_hw_config(local, 0); |
272 | 266 | ||
273 | if (prev_chantype != channel_type) { | 267 | if (prev_chantype != tx_channel_type) { |
274 | rcu_read_lock(); | 268 | rcu_read_lock(); |
275 | sta = sta_info_get(sdata, bssid); | 269 | sta = sta_info_get(sdata, bssid); |
276 | if (sta) | 270 | if (sta) |
277 | rate_control_rate_update(local, sband, sta, | 271 | rate_control_rate_update(local, sband, sta, |
278 | IEEE80211_RC_HT_CHANGED, | 272 | IEEE80211_RC_HT_CHANGED, |
279 | channel_type); | 273 | tx_channel_type); |
280 | rcu_read_unlock(); | 274 | rcu_read_unlock(); |
281 | 275 | ||
282 | if (beacon_htcap_ie) | 276 | if (beacon_htcap_ie) |
@@ -289,7 +283,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
289 | /* if bss configuration changed store the new one */ | 283 | /* if bss configuration changed store the new one */ |
290 | if (sdata->ht_opmode_valid != enable_ht || | 284 | if (sdata->ht_opmode_valid != enable_ht || |
291 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode || | 285 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode || |
292 | prev_chantype != channel_type) { | 286 | prev_chantype != rx_channel_type) { |
293 | changed |= BSS_CHANGED_HT; | 287 | changed |= BSS_CHANGED_HT; |
294 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | 288 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; |
295 | sdata->ht_opmode_valid = enable_ht; | 289 | sdata->ht_opmode_valid = enable_ht; |
@@ -335,9 +329,6 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | |||
335 | 329 | ||
336 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); | 330 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); |
337 | 331 | ||
338 | if (!sband->ht_cap.ht_supported) | ||
339 | return; | ||
340 | |||
341 | if (!ht_info_ie) | 332 | if (!ht_info_ie) |
342 | return; | 333 | return; |
343 | 334 | ||
@@ -405,7 +396,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
405 | u16 capab; | 396 | u16 capab; |
406 | struct ieee80211_supported_band *sband; | 397 | struct ieee80211_supported_band *sband; |
407 | u32 rates = 0; | 398 | u32 rates = 0; |
408 | struct ieee80211_bss *bss = (void *)assoc_data->bss->priv; | ||
409 | 399 | ||
410 | lockdep_assert_held(&ifmgd->mtx); | 400 | lockdep_assert_held(&ifmgd->mtx); |
411 | 401 | ||
@@ -566,8 +556,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
566 | offset = noffset; | 556 | offset = noffset; |
567 | } | 557 | } |
568 | 558 | ||
569 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N) && | 559 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
570 | bss->wmm_used && local->hw.queues >= 4) | ||
571 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie, | 560 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie, |
572 | sband, local->oper_channel, ifmgd->ap_smps); | 561 | sband, local->oper_channel, ifmgd->ap_smps); |
573 | 562 | ||
@@ -581,10 +570,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
581 | offset = noffset; | 570 | offset = noffset; |
582 | } | 571 | } |
583 | 572 | ||
584 | if (assoc_data->wmm_used && local->hw.queues >= 4) { | 573 | if (assoc_data->wmm) { |
585 | if (assoc_data->uapsd_used) { | 574 | if (assoc_data->uapsd) { |
586 | qos_info = local->uapsd_queues; | 575 | qos_info = ifmgd->uapsd_queues; |
587 | qos_info |= (local->uapsd_max_sp_len << | 576 | qos_info |= (ifmgd->uapsd_max_sp_len << |
588 | IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT); | 577 | IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT); |
589 | } else { | 578 | } else { |
590 | qos_info = 0; | 579 | qos_info = 0; |
@@ -1203,7 +1192,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1203 | return; | 1192 | return; |
1204 | 1193 | ||
1205 | if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) | 1194 | if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) |
1206 | uapsd_queues = local->uapsd_queues; | 1195 | uapsd_queues = ifmgd->uapsd_queues; |
1207 | 1196 | ||
1208 | count = wmm_param[6] & 0x0f; | 1197 | count = wmm_param[6] & 0x0f; |
1209 | if (count == ifmgd->wmm_last_param_set) | 1198 | if (count == ifmgd->wmm_last_param_set) |
@@ -1329,7 +1318,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1329 | bss_info_changed |= BSS_CHANGED_ASSOC; | 1318 | bss_info_changed |= BSS_CHANGED_ASSOC; |
1330 | /* set timing information */ | 1319 | /* set timing information */ |
1331 | bss_conf->beacon_int = cbss->beacon_interval; | 1320 | bss_conf->beacon_int = cbss->beacon_interval; |
1332 | bss_conf->timestamp = cbss->tsf; | 1321 | bss_conf->last_tsf = cbss->tsf; |
1333 | 1322 | ||
1334 | bss_info_changed |= BSS_CHANGED_BEACON_INT; | 1323 | bss_info_changed |= BSS_CHANGED_BEACON_INT; |
1335 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 1324 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
@@ -1355,15 +1344,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1355 | bss_conf->dtim_period = 0; | 1344 | bss_conf->dtim_period = 0; |
1356 | 1345 | ||
1357 | bss_conf->assoc = 1; | 1346 | bss_conf->assoc = 1; |
1358 | /* | ||
1359 | * For now just always ask the driver to update the basic rateset | ||
1360 | * when we have associated, we aren't checking whether it actually | ||
1361 | * changed or not. | ||
1362 | */ | ||
1363 | bss_info_changed |= BSS_CHANGED_BASIC_RATES; | ||
1364 | |||
1365 | /* And the BSSID changed - we're associated now */ | ||
1366 | bss_info_changed |= BSS_CHANGED_BSSID; | ||
1367 | 1347 | ||
1368 | /* Tell the driver to monitor connection quality (if supported) */ | 1348 | /* Tell the driver to monitor connection quality (if supported) */ |
1369 | if (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI && | 1349 | if (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI && |
@@ -1394,7 +1374,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1394 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1374 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1395 | struct ieee80211_local *local = sdata->local; | 1375 | struct ieee80211_local *local = sdata->local; |
1396 | struct sta_info *sta; | 1376 | struct sta_info *sta; |
1397 | u32 changed = 0, config_changed = 0; | 1377 | u32 changed = 0; |
1398 | u8 bssid[ETH_ALEN]; | 1378 | u8 bssid[ETH_ALEN]; |
1399 | 1379 | ||
1400 | ASSERT_MGD_MTX(ifmgd); | 1380 | ASSERT_MGD_MTX(ifmgd); |
@@ -1454,9 +1434,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1454 | changed |= BSS_CHANGED_ASSOC; | 1434 | changed |= BSS_CHANGED_ASSOC; |
1455 | sdata->vif.bss_conf.assoc = false; | 1435 | sdata->vif.bss_conf.assoc = false; |
1456 | 1436 | ||
1457 | /* channel(_type) changes are handled by ieee80211_hw_config */ | ||
1458 | WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); | ||
1459 | |||
1460 | /* on the next assoc, re-program HT parameters */ | 1437 | /* on the next assoc, re-program HT parameters */ |
1461 | sdata->ht_opmode_valid = false; | 1438 | sdata->ht_opmode_valid = false; |
1462 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); | 1439 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); |
@@ -1469,12 +1446,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1469 | 1446 | ||
1470 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 1447 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
1471 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | 1448 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; |
1472 | config_changed |= IEEE80211_CONF_CHANGE_PS; | 1449 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
1473 | } | 1450 | } |
1474 | local->ps_sdata = NULL; | 1451 | local->ps_sdata = NULL; |
1475 | 1452 | ||
1476 | ieee80211_hw_config(local, config_changed); | ||
1477 | |||
1478 | /* Disable ARP filtering */ | 1453 | /* Disable ARP filtering */ |
1479 | if (sdata->vif.bss_conf.arp_filter_enabled) { | 1454 | if (sdata->vif.bss_conf.arp_filter_enabled) { |
1480 | sdata->vif.bss_conf.arp_filter_enabled = false; | 1455 | sdata->vif.bss_conf.arp_filter_enabled = false; |
@@ -1488,6 +1463,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1488 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; | 1463 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; |
1489 | ieee80211_bss_info_change_notify(sdata, changed); | 1464 | ieee80211_bss_info_change_notify(sdata, changed); |
1490 | 1465 | ||
1466 | /* channel(_type) changes are handled by ieee80211_hw_config */ | ||
1467 | WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); | ||
1468 | ieee80211_hw_config(local, 0); | ||
1469 | |||
1491 | /* disassociated - set to defaults now */ | 1470 | /* disassociated - set to defaults now */ |
1492 | ieee80211_set_wmm_default(sdata, false); | 1471 | ieee80211_set_wmm_default(sdata, false); |
1493 | 1472 | ||
@@ -1770,11 +1749,6 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, | |||
1770 | 1749 | ||
1771 | lockdep_assert_held(&sdata->u.mgd.mtx); | 1750 | lockdep_assert_held(&sdata->u.mgd.mtx); |
1772 | 1751 | ||
1773 | if (auth_data->synced) | ||
1774 | drv_finish_tx_sync(sdata->local, sdata, | ||
1775 | auth_data->bss->bssid, | ||
1776 | IEEE80211_TX_SYNC_AUTH); | ||
1777 | |||
1778 | if (!assoc) { | 1752 | if (!assoc) { |
1779 | sta_info_destroy_addr(sdata, auth_data->bss->bssid); | 1753 | sta_info_destroy_addr(sdata, auth_data->bss->bssid); |
1780 | 1754 | ||
@@ -1862,10 +1836,6 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1862 | 1836 | ||
1863 | printk(KERN_DEBUG "%s: authenticated\n", sdata->name); | 1837 | printk(KERN_DEBUG "%s: authenticated\n", sdata->name); |
1864 | out: | 1838 | out: |
1865 | if (ifmgd->auth_data->synced) | ||
1866 | drv_finish_tx_sync(sdata->local, sdata, bssid, | ||
1867 | IEEE80211_TX_SYNC_AUTH); | ||
1868 | ifmgd->auth_data->synced = false; | ||
1869 | ifmgd->auth_data->done = true; | 1839 | ifmgd->auth_data->done = true; |
1870 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; | 1840 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; |
1871 | run_again(ifmgd, ifmgd->auth_data->timeout); | 1841 | run_again(ifmgd, ifmgd->auth_data->timeout); |
@@ -2005,11 +1975,6 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, | |||
2005 | 1975 | ||
2006 | lockdep_assert_held(&sdata->u.mgd.mtx); | 1976 | lockdep_assert_held(&sdata->u.mgd.mtx); |
2007 | 1977 | ||
2008 | if (assoc_data->synced) | ||
2009 | drv_finish_tx_sync(sdata->local, sdata, | ||
2010 | assoc_data->bss->bssid, | ||
2011 | IEEE80211_TX_SYNC_ASSOC); | ||
2012 | |||
2013 | if (!assoc) { | 1978 | if (!assoc) { |
2014 | sta_info_destroy_addr(sdata, assoc_data->bss->bssid); | 1979 | sta_info_destroy_addr(sdata, assoc_data->bss->bssid); |
2015 | 1980 | ||
@@ -2030,15 +1995,12 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2030 | struct ieee80211_supported_band *sband; | 1995 | struct ieee80211_supported_band *sband; |
2031 | struct sta_info *sta; | 1996 | struct sta_info *sta; |
2032 | u8 *pos; | 1997 | u8 *pos; |
2033 | u32 rates, basic_rates; | ||
2034 | u16 capab_info, aid; | 1998 | u16 capab_info, aid; |
2035 | struct ieee802_11_elems elems; | 1999 | struct ieee802_11_elems elems; |
2036 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 2000 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
2037 | u32 changed = 0; | 2001 | u32 changed = 0; |
2038 | int err; | 2002 | int err; |
2039 | bool have_higher_than_11mbit = false; | ||
2040 | u16 ap_ht_cap_flags; | 2003 | u16 ap_ht_cap_flags; |
2041 | int min_rate = INT_MAX, min_rate_index = -1; | ||
2042 | 2004 | ||
2043 | /* AssocResp and ReassocResp have identical structure */ | 2005 | /* AssocResp and ReassocResp have identical structure */ |
2044 | 2006 | ||
@@ -2083,39 +2045,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2083 | return false; | 2045 | return false; |
2084 | } | 2046 | } |
2085 | 2047 | ||
2086 | rates = 0; | ||
2087 | basic_rates = 0; | ||
2088 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 2048 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
2089 | 2049 | ||
2090 | ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len, | ||
2091 | &rates, &basic_rates, &have_higher_than_11mbit, | ||
2092 | &min_rate, &min_rate_index); | ||
2093 | |||
2094 | ieee80211_get_rates(sband, elems.ext_supp_rates, | ||
2095 | elems.ext_supp_rates_len, &rates, &basic_rates, | ||
2096 | &have_higher_than_11mbit, | ||
2097 | &min_rate, &min_rate_index); | ||
2098 | |||
2099 | /* | ||
2100 | * some buggy APs don't advertise basic_rates. use the lowest | ||
2101 | * supported rate instead. | ||
2102 | */ | ||
2103 | if (unlikely(!basic_rates) && min_rate_index >= 0) { | ||
2104 | printk(KERN_DEBUG "%s: No basic rates in AssocResp. " | ||
2105 | "Using min supported rate instead.\n", sdata->name); | ||
2106 | basic_rates = BIT(min_rate_index); | ||
2107 | } | ||
2108 | |||
2109 | sta->sta.supp_rates[local->oper_channel->band] = rates; | ||
2110 | sdata->vif.bss_conf.basic_rates = basic_rates; | ||
2111 | |||
2112 | /* cf. IEEE 802.11 9.2.12 */ | ||
2113 | if (local->oper_channel->band == IEEE80211_BAND_2GHZ && | ||
2114 | have_higher_than_11mbit) | ||
2115 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
2116 | else | ||
2117 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
2118 | |||
2119 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2050 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
2120 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 2051 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
2121 | elems.ht_cap_elem, &sta->sta.ht_cap); | 2052 | elems.ht_cap_elem, &sta->sta.ht_cap); |
@@ -2162,7 +2093,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2162 | changed |= BSS_CHANGED_QOS; | 2093 | changed |= BSS_CHANGED_QOS; |
2163 | 2094 | ||
2164 | if (elems.ht_info_elem && elems.wmm_param && | 2095 | if (elems.ht_info_elem && elems.wmm_param && |
2165 | (sdata->local->hw.queues >= 4) && | ||
2166 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2096 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
2167 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 2097 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, |
2168 | cbss->bssid, ap_ht_cap_flags, | 2098 | cbss->bssid, ap_ht_cap_flags, |
@@ -2255,14 +2185,6 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2255 | } else { | 2185 | } else { |
2256 | printk(KERN_DEBUG "%s: associated\n", sdata->name); | 2186 | printk(KERN_DEBUG "%s: associated\n", sdata->name); |
2257 | 2187 | ||
2258 | /* tell driver about sync done first */ | ||
2259 | if (assoc_data->synced) { | ||
2260 | drv_finish_tx_sync(sdata->local, sdata, | ||
2261 | assoc_data->bss->bssid, | ||
2262 | IEEE80211_TX_SYNC_ASSOC); | ||
2263 | assoc_data->synced = false; | ||
2264 | } | ||
2265 | |||
2266 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { | 2188 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { |
2267 | /* oops -- internal error -- send timeout for now */ | 2189 | /* oops -- internal error -- send timeout for now */ |
2268 | ieee80211_destroy_assoc_data(sdata, true); | 2190 | ieee80211_destroy_assoc_data(sdata, true); |
@@ -2747,14 +2669,6 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2747 | if (WARN_ON_ONCE(!auth_data)) | 2669 | if (WARN_ON_ONCE(!auth_data)) |
2748 | return -EINVAL; | 2670 | return -EINVAL; |
2749 | 2671 | ||
2750 | if (!auth_data->synced) { | ||
2751 | int ret = drv_tx_sync(local, sdata, auth_data->bss->bssid, | ||
2752 | IEEE80211_TX_SYNC_AUTH); | ||
2753 | if (ret) | ||
2754 | return ret; | ||
2755 | } | ||
2756 | auth_data->synced = true; | ||
2757 | |||
2758 | auth_data->tries++; | 2672 | auth_data->tries++; |
2759 | 2673 | ||
2760 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { | 2674 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { |
@@ -2811,14 +2725,6 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | |||
2811 | 2725 | ||
2812 | lockdep_assert_held(&sdata->u.mgd.mtx); | 2726 | lockdep_assert_held(&sdata->u.mgd.mtx); |
2813 | 2727 | ||
2814 | if (!assoc_data->synced) { | ||
2815 | int ret = drv_tx_sync(local, sdata, assoc_data->bss->bssid, | ||
2816 | IEEE80211_TX_SYNC_ASSOC); | ||
2817 | if (ret) | ||
2818 | return ret; | ||
2819 | } | ||
2820 | assoc_data->synced = true; | ||
2821 | |||
2822 | assoc_data->tries++; | 2728 | assoc_data->tries++; |
2823 | if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { | 2729 | if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { |
2824 | printk(KERN_DEBUG "%s: association with %pM timed out\n", | 2730 | printk(KERN_DEBUG "%s: association with %pM timed out\n", |
@@ -3107,6 +3013,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
3107 | 3013 | ||
3108 | ifmgd->flags = 0; | 3014 | ifmgd->flags = 0; |
3109 | ifmgd->powersave = sdata->wdev.ps; | 3015 | ifmgd->powersave = sdata->wdev.ps; |
3016 | ifmgd->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; | ||
3017 | ifmgd->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; | ||
3110 | 3018 | ||
3111 | mutex_init(&ifmgd->mtx); | 3019 | mutex_init(&ifmgd->mtx); |
3112 | 3020 | ||
@@ -3143,6 +3051,101 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
3143 | return 0; | 3051 | return 0; |
3144 | } | 3052 | } |
3145 | 3053 | ||
3054 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | ||
3055 | struct cfg80211_bss *cbss, bool assoc) | ||
3056 | { | ||
3057 | struct ieee80211_local *local = sdata->local; | ||
3058 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3059 | struct ieee80211_bss *bss = (void *)cbss->priv; | ||
3060 | struct sta_info *sta; | ||
3061 | bool have_sta = false; | ||
3062 | int err; | ||
3063 | |||
3064 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) | ||
3065 | return -EINVAL; | ||
3066 | |||
3067 | if (assoc) { | ||
3068 | rcu_read_lock(); | ||
3069 | have_sta = sta_info_get(sdata, cbss->bssid); | ||
3070 | rcu_read_unlock(); | ||
3071 | } | ||
3072 | |||
3073 | if (!have_sta) { | ||
3074 | sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); | ||
3075 | if (!sta) | ||
3076 | return -ENOMEM; | ||
3077 | } | ||
3078 | |||
3079 | mutex_lock(&local->mtx); | ||
3080 | ieee80211_recalc_idle(sdata->local); | ||
3081 | mutex_unlock(&local->mtx); | ||
3082 | |||
3083 | /* switch to the right channel */ | ||
3084 | local->oper_channel = cbss->channel; | ||
3085 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
3086 | |||
3087 | if (!have_sta) { | ||
3088 | struct ieee80211_supported_band *sband; | ||
3089 | u32 rates = 0, basic_rates = 0; | ||
3090 | bool have_higher_than_11mbit; | ||
3091 | int min_rate = INT_MAX, min_rate_index = -1; | ||
3092 | |||
3093 | sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; | ||
3094 | |||
3095 | ieee80211_get_rates(sband, bss->supp_rates, | ||
3096 | bss->supp_rates_len, | ||
3097 | &rates, &basic_rates, | ||
3098 | &have_higher_than_11mbit, | ||
3099 | &min_rate, &min_rate_index); | ||
3100 | |||
3101 | /* | ||
3102 | * This used to be a workaround for basic rates missing | ||
3103 | * in the association response frame. Now that we no | ||
3104 | * longer use the basic rates from there, it probably | ||
3105 | * doesn't happen any more, but keep the workaround so | ||
3106 | * in case some *other* APs are buggy in different ways | ||
3107 | * we can connect -- with a warning. | ||
3108 | */ | ||
3109 | if (!basic_rates && min_rate_index >= 0) { | ||
3110 | printk(KERN_DEBUG | ||
3111 | "%s: No basic rates, using min rate instead.\n", | ||
3112 | sdata->name); | ||
3113 | basic_rates = BIT(min_rate_index); | ||
3114 | } | ||
3115 | |||
3116 | sta->sta.supp_rates[cbss->channel->band] = rates; | ||
3117 | sdata->vif.bss_conf.basic_rates = basic_rates; | ||
3118 | |||
3119 | /* cf. IEEE 802.11 9.2.12 */ | ||
3120 | if (local->oper_channel->band == IEEE80211_BAND_2GHZ && | ||
3121 | have_higher_than_11mbit) | ||
3122 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
3123 | else | ||
3124 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
3125 | |||
3126 | memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN); | ||
3127 | |||
3128 | /* tell driver about BSSID and basic rates */ | ||
3129 | ieee80211_bss_info_change_notify(sdata, | ||
3130 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES); | ||
3131 | |||
3132 | if (assoc) | ||
3133 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | ||
3134 | |||
3135 | err = sta_info_insert(sta); | ||
3136 | sta = NULL; | ||
3137 | if (err) { | ||
3138 | printk(KERN_DEBUG | ||
3139 | "%s: failed to insert STA entry for the AP (error %d)\n", | ||
3140 | sdata->name, err); | ||
3141 | return err; | ||
3142 | } | ||
3143 | } else | ||
3144 | WARN_ON_ONCE(compare_ether_addr(ifmgd->bssid, cbss->bssid)); | ||
3145 | |||
3146 | return 0; | ||
3147 | } | ||
3148 | |||
3146 | /* config hooks */ | 3149 | /* config hooks */ |
3147 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 3150 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
3148 | struct cfg80211_auth_request *req) | 3151 | struct cfg80211_auth_request *req) |
@@ -3150,7 +3153,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
3150 | struct ieee80211_local *local = sdata->local; | 3153 | struct ieee80211_local *local = sdata->local; |
3151 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3154 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3152 | struct ieee80211_mgd_auth_data *auth_data; | 3155 | struct ieee80211_mgd_auth_data *auth_data; |
3153 | struct sta_info *sta; | ||
3154 | u16 auth_alg; | 3156 | u16 auth_alg; |
3155 | int err; | 3157 | int err; |
3156 | 3158 | ||
@@ -3216,38 +3218,12 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
3216 | printk(KERN_DEBUG "%s: authenticate with %pM\n", | 3218 | printk(KERN_DEBUG "%s: authenticate with %pM\n", |
3217 | sdata->name, req->bss->bssid); | 3219 | sdata->name, req->bss->bssid); |
3218 | 3220 | ||
3219 | mutex_lock(&local->mtx); | 3221 | err = ieee80211_prep_connection(sdata, req->bss, false); |
3220 | ieee80211_recalc_idle(sdata->local); | 3222 | if (err) |
3221 | mutex_unlock(&local->mtx); | ||
3222 | |||
3223 | /* switch to the right channel */ | ||
3224 | local->oper_channel = req->bss->channel; | ||
3225 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
3226 | |||
3227 | /* set BSSID */ | ||
3228 | memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN); | ||
3229 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | ||
3230 | |||
3231 | /* add station entry */ | ||
3232 | sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL); | ||
3233 | if (!sta) { | ||
3234 | err = -ENOMEM; | ||
3235 | goto err_clear; | 3223 | goto err_clear; |
3236 | } | ||
3237 | |||
3238 | err = sta_info_insert(sta); | ||
3239 | if (err) { | ||
3240 | printk(KERN_DEBUG | ||
3241 | "%s: failed to insert STA entry for the AP %pM (error %d)\n", | ||
3242 | sdata->name, req->bss->bssid, err); | ||
3243 | goto err_clear; | ||
3244 | } | ||
3245 | 3224 | ||
3246 | err = ieee80211_probe_auth(sdata); | 3225 | err = ieee80211_probe_auth(sdata); |
3247 | if (err) { | 3226 | if (err) { |
3248 | if (auth_data->synced) | ||
3249 | drv_finish_tx_sync(local, sdata, req->bss->bssid, | ||
3250 | IEEE80211_TX_SYNC_AUTH); | ||
3251 | sta_info_destroy_addr(sdata, req->bss->bssid); | 3227 | sta_info_destroy_addr(sdata, req->bss->bssid); |
3252 | goto err_clear; | 3228 | goto err_clear; |
3253 | } | 3229 | } |
@@ -3274,7 +3250,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3274 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3250 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3275 | struct ieee80211_bss *bss = (void *)req->bss->priv; | 3251 | struct ieee80211_bss *bss = (void *)req->bss->priv; |
3276 | struct ieee80211_mgd_assoc_data *assoc_data; | 3252 | struct ieee80211_mgd_assoc_data *assoc_data; |
3277 | struct sta_info *sta; | 3253 | struct ieee80211_supported_band *sband; |
3278 | const u8 *ssidie; | 3254 | const u8 *ssidie; |
3279 | int i, err; | 3255 | int i, err; |
3280 | 3256 | ||
@@ -3316,6 +3292,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3316 | 3292 | ||
3317 | ifmgd->beacon_crc_valid = false; | 3293 | ifmgd->beacon_crc_valid = false; |
3318 | 3294 | ||
3295 | /* | ||
3296 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. | ||
3297 | * We still associate in non-HT mode (11a/b/g) if any one of these | ||
3298 | * ciphers is configured as pairwise. | ||
3299 | * We can set this to true for non-11n hardware, that'll be checked | ||
3300 | * separately along with the peer capabilities. | ||
3301 | */ | ||
3319 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) | 3302 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) |
3320 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 3303 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
3321 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 3304 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
@@ -3325,6 +3308,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3325 | if (req->flags & ASSOC_REQ_DISABLE_HT) | 3308 | if (req->flags & ASSOC_REQ_DISABLE_HT) |
3326 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3309 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3327 | 3310 | ||
3311 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | ||
3312 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | ||
3313 | if (!sband->ht_cap.ht_supported || | ||
3314 | local->hw.queues < 4 || !bss->wmm_used) | ||
3315 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | ||
3316 | |||
3328 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); | 3317 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); |
3329 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, | 3318 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, |
3330 | sizeof(ifmgd->ht_capa_mask)); | 3319 | sizeof(ifmgd->ht_capa_mask)); |
@@ -3344,15 +3333,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3344 | } else | 3333 | } else |
3345 | ifmgd->ap_smps = ifmgd->req_smps; | 3334 | ifmgd->ap_smps = ifmgd->req_smps; |
3346 | 3335 | ||
3347 | /* | ||
3348 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. | ||
3349 | * We still associate in non-HT mode (11a/b/g) if any one of these | ||
3350 | * ciphers is configured as pairwise. | ||
3351 | * We can set this to true for non-11n hardware, that'll be checked | ||
3352 | * separately along with the peer capabilities. | ||
3353 | */ | ||
3354 | assoc_data->capability = req->bss->capability; | 3336 | assoc_data->capability = req->bss->capability; |
3355 | assoc_data->wmm_used = bss->wmm_used; | 3337 | assoc_data->wmm = bss->wmm_used && (local->hw.queues >= 4); |
3356 | assoc_data->supp_rates = bss->supp_rates; | 3338 | assoc_data->supp_rates = bss->supp_rates; |
3357 | assoc_data->supp_rates_len = bss->supp_rates_len; | 3339 | assoc_data->supp_rates_len = bss->supp_rates_len; |
3358 | assoc_data->ht_information_ie = | 3340 | assoc_data->ht_information_ie = |
@@ -3360,10 +3342,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3360 | 3342 | ||
3361 | if (bss->wmm_used && bss->uapsd_supported && | 3343 | if (bss->wmm_used && bss->uapsd_supported && |
3362 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 3344 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
3363 | assoc_data->uapsd_used = true; | 3345 | assoc_data->uapsd = true; |
3364 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; | 3346 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; |
3365 | } else { | 3347 | } else { |
3366 | assoc_data->uapsd_used = false; | 3348 | assoc_data->uapsd = false; |
3367 | ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; | 3349 | ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; |
3368 | } | 3350 | } |
3369 | 3351 | ||
@@ -3393,41 +3375,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3393 | 3375 | ||
3394 | ifmgd->assoc_data = assoc_data; | 3376 | ifmgd->assoc_data = assoc_data; |
3395 | 3377 | ||
3396 | mutex_lock(&local->mtx); | 3378 | err = ieee80211_prep_connection(sdata, req->bss, true); |
3397 | ieee80211_recalc_idle(sdata->local); | 3379 | if (err) |
3398 | mutex_unlock(&local->mtx); | 3380 | goto err_clear; |
3399 | |||
3400 | /* switch to the right channel */ | ||
3401 | local->oper_channel = req->bss->channel; | ||
3402 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
3403 | |||
3404 | rcu_read_lock(); | ||
3405 | sta = sta_info_get(sdata, req->bss->bssid); | ||
3406 | rcu_read_unlock(); | ||
3407 | |||
3408 | if (!sta) { | ||
3409 | /* set BSSID */ | ||
3410 | memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN); | ||
3411 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | ||
3412 | |||
3413 | sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL); | ||
3414 | if (!sta) { | ||
3415 | err = -ENOMEM; | ||
3416 | goto err_clear; | ||
3417 | } | ||
3418 | |||
3419 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | ||
3420 | |||
3421 | err = sta_info_insert(sta); | ||
3422 | sta = NULL; | ||
3423 | if (err) { | ||
3424 | printk(KERN_DEBUG | ||
3425 | "%s: failed to insert STA entry for the AP (error %d)\n", | ||
3426 | sdata->name, err); | ||
3427 | goto err_clear; | ||
3428 | } | ||
3429 | } else | ||
3430 | WARN_ON_ONCE(compare_ether_addr(ifmgd->bssid, req->bss->bssid)); | ||
3431 | 3381 | ||
3432 | if (!bss->dtim_period && | 3382 | if (!bss->dtim_period && |
3433 | sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { | 3383 | sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index ff5f7b84e825..16e0b277b9a8 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -568,6 +568,13 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
568 | minstrel_next_sample_idx(mi); | 568 | minstrel_next_sample_idx(mi); |
569 | 569 | ||
570 | /* | 570 | /* |
571 | * Sampling might add some overhead (RTS, no aggregation) | ||
572 | * to the frame. Hence, don't use sampling for the currently | ||
573 | * used max TP rate. | ||
574 | */ | ||
575 | if (sample_idx == mi->max_tp_rate) | ||
576 | return -1; | ||
577 | /* | ||
571 | * When not using MRR, do not sample if the probability is already | 578 | * When not using MRR, do not sample if the probability is already |
572 | * higher than 95% to avoid wasting airtime | 579 | * higher than 95% to avoid wasting airtime |
573 | */ | 580 | */ |
@@ -692,6 +699,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
692 | int ack_dur; | 699 | int ack_dur; |
693 | int stbc; | 700 | int stbc; |
694 | int i; | 701 | int i; |
702 | unsigned int smps; | ||
695 | 703 | ||
696 | /* fall back to the old minstrel for legacy stations */ | 704 | /* fall back to the old minstrel for legacy stations */ |
697 | if (!sta->ht_cap.ht_supported) | 705 | if (!sta->ht_cap.ht_supported) |
@@ -731,6 +739,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
731 | oper_chan_type != NL80211_CHAN_HT40PLUS) | 739 | oper_chan_type != NL80211_CHAN_HT40PLUS) |
732 | sta_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 740 | sta_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
733 | 741 | ||
742 | smps = (sta_cap & IEEE80211_HT_CAP_SM_PS) >> | ||
743 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
744 | |||
734 | for (i = 0; i < ARRAY_SIZE(mi->groups); i++) { | 745 | for (i = 0; i < ARRAY_SIZE(mi->groups); i++) { |
735 | u16 req = 0; | 746 | u16 req = 0; |
736 | 747 | ||
@@ -748,6 +759,11 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
748 | if ((sta_cap & req) != req) | 759 | if ((sta_cap & req) != req) |
749 | continue; | 760 | continue; |
750 | 761 | ||
762 | /* Mark MCS > 7 as unsupported if STA is in static SMPS mode */ | ||
763 | if (smps == WLAN_HT_CAP_SM_PS_STATIC && | ||
764 | minstrel_mcs_groups[i].streams > 1) | ||
765 | continue; | ||
766 | |||
751 | mi->groups[i].supported = | 767 | mi->groups[i].supported = |
752 | mcs->rx_mask[minstrel_mcs_groups[i].streams - 1]; | 768 | mcs->rx_mask[minstrel_mcs_groups[i].streams - 1]; |
753 | 769 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5f6e32ca0858..bcfe8c77c839 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1063,20 +1063,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1063 | return RX_DROP_MONITOR; | 1063 | return RX_DROP_MONITOR; |
1064 | } | 1064 | } |
1065 | 1065 | ||
1066 | if (skb_linearize(rx->skb)) | ||
1067 | return RX_DROP_UNUSABLE; | ||
1068 | /* the hdr variable is invalid now! */ | ||
1069 | |||
1070 | switch (rx->key->conf.cipher) { | 1066 | switch (rx->key->conf.cipher) { |
1071 | case WLAN_CIPHER_SUITE_WEP40: | 1067 | case WLAN_CIPHER_SUITE_WEP40: |
1072 | case WLAN_CIPHER_SUITE_WEP104: | 1068 | case WLAN_CIPHER_SUITE_WEP104: |
1073 | /* Check for weak IVs if possible */ | ||
1074 | if (rx->sta && ieee80211_is_data(fc) && | ||
1075 | (!(status->flag & RX_FLAG_IV_STRIPPED) || | ||
1076 | !(status->flag & RX_FLAG_DECRYPTED)) && | ||
1077 | ieee80211_wep_is_weak_iv(rx->skb, rx->key)) | ||
1078 | rx->sta->wep_weak_iv_count++; | ||
1079 | |||
1080 | result = ieee80211_crypto_wep_decrypt(rx); | 1069 | result = ieee80211_crypto_wep_decrypt(rx); |
1081 | break; | 1070 | break; |
1082 | case WLAN_CIPHER_SUITE_TKIP: | 1071 | case WLAN_CIPHER_SUITE_TKIP: |
@@ -1096,6 +1085,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1096 | return RX_DROP_UNUSABLE; | 1085 | return RX_DROP_UNUSABLE; |
1097 | } | 1086 | } |
1098 | 1087 | ||
1088 | /* the hdr variable is invalid after the decrypt handlers */ | ||
1089 | |||
1099 | /* either the frame has been decrypted or will be dropped */ | 1090 | /* either the frame has been decrypted or will be dropped */ |
1100 | status->flag |= RX_FLAG_DECRYPTED; | 1091 | status->flag |= RX_FLAG_DECRYPTED; |
1101 | 1092 | ||
@@ -2278,9 +2269,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2278 | 2269 | ||
2279 | sband = rx->local->hw.wiphy->bands[status->band]; | 2270 | sband = rx->local->hw.wiphy->bands[status->band]; |
2280 | 2271 | ||
2281 | rate_control_rate_update(local, sband, rx->sta, | 2272 | rate_control_rate_update( |
2282 | IEEE80211_RC_SMPS_CHANGED, | 2273 | local, sband, rx->sta, |
2283 | local->_oper_channel_type); | 2274 | IEEE80211_RC_SMPS_CHANGED, |
2275 | ieee80211_get_tx_channel_type( | ||
2276 | local, local->_oper_channel_type)); | ||
2284 | goto handled; | 2277 | goto handled; |
2285 | } | 2278 | } |
2286 | default: | 2279 | default: |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 570737df2d22..782a60198df4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -226,12 +226,12 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) | |||
226 | * have correct qos tag for some reason, due the network or the | 226 | * have correct qos tag for some reason, due the network or the |
227 | * peer application. | 227 | * peer application. |
228 | * | 228 | * |
229 | * Note: local->uapsd_queues access is racy here. If the value is | 229 | * Note: ifmgd->uapsd_queues access is racy here. If the value is |
230 | * changed via debugfs, user needs to reassociate manually to have | 230 | * changed via debugfs, user needs to reassociate manually to have |
231 | * everything in sync. | 231 | * everything in sync. |
232 | */ | 232 | */ |
233 | if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) | 233 | if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) |
234 | && (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) | 234 | && (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) |
235 | && skb_get_queue_mapping(tx->skb) == 0) | 235 | && skb_get_queue_mapping(tx->skb) == 0) |
236 | return TX_CONTINUE; | 236 | return TX_CONTINUE; |
237 | 237 | ||
@@ -1065,6 +1065,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | |||
1065 | { | 1065 | { |
1066 | bool queued = false; | 1066 | bool queued = false; |
1067 | bool reset_agg_timer = false; | 1067 | bool reset_agg_timer = false; |
1068 | struct sk_buff *purge_skb = NULL; | ||
1068 | 1069 | ||
1069 | if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { | 1070 | if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { |
1070 | info->flags |= IEEE80211_TX_CTL_AMPDU; | 1071 | info->flags |= IEEE80211_TX_CTL_AMPDU; |
@@ -1106,8 +1107,13 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | |||
1106 | info->control.vif = &tx->sdata->vif; | 1107 | info->control.vif = &tx->sdata->vif; |
1107 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1108 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1108 | __skb_queue_tail(&tid_tx->pending, skb); | 1109 | __skb_queue_tail(&tid_tx->pending, skb); |
1110 | if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER) | ||
1111 | purge_skb = __skb_dequeue(&tid_tx->pending); | ||
1109 | } | 1112 | } |
1110 | spin_unlock(&tx->sta->lock); | 1113 | spin_unlock(&tx->sta->lock); |
1114 | |||
1115 | if (purge_skb) | ||
1116 | dev_kfree_skb(purge_skb); | ||
1111 | } | 1117 | } |
1112 | 1118 | ||
1113 | /* reset session timer */ | 1119 | /* reset session timer */ |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 68ad351479df..7aa31bbfaa3b 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -263,16 +263,14 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, | |||
263 | } | 263 | } |
264 | 264 | ||
265 | 265 | ||
266 | bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) | 266 | static bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, |
267 | struct ieee80211_key *key) | ||
267 | { | 268 | { |
268 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 269 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
269 | unsigned int hdrlen; | 270 | unsigned int hdrlen; |
270 | u8 *ivpos; | 271 | u8 *ivpos; |
271 | u32 iv; | 272 | u32 iv; |
272 | 273 | ||
273 | if (!ieee80211_has_protected(hdr->frame_control)) | ||
274 | return false; | ||
275 | |||
276 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 274 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
277 | ivpos = skb->data + hdrlen; | 275 | ivpos = skb->data + hdrlen; |
278 | iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; | 276 | iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; |
@@ -286,18 +284,27 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) | |||
286 | struct sk_buff *skb = rx->skb; | 284 | struct sk_buff *skb = rx->skb; |
287 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 285 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
288 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 286 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
287 | __le16 fc = hdr->frame_control; | ||
289 | 288 | ||
290 | if (!ieee80211_is_data(hdr->frame_control) && | 289 | if (!ieee80211_is_data(fc) && !ieee80211_is_auth(fc)) |
291 | !ieee80211_is_auth(hdr->frame_control)) | ||
292 | return RX_CONTINUE; | 290 | return RX_CONTINUE; |
293 | 291 | ||
294 | if (!(status->flag & RX_FLAG_DECRYPTED)) { | 292 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
293 | if (skb_linearize(rx->skb)) | ||
294 | return RX_DROP_UNUSABLE; | ||
295 | if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key)) | ||
296 | rx->sta->wep_weak_iv_count++; | ||
295 | if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) | 297 | if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) |
296 | return RX_DROP_UNUSABLE; | 298 | return RX_DROP_UNUSABLE; |
297 | } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) { | 299 | } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) { |
300 | if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + WEP_IV_LEN)) | ||
301 | return RX_DROP_UNUSABLE; | ||
302 | if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key)) | ||
303 | rx->sta->wep_weak_iv_count++; | ||
298 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); | 304 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); |
299 | /* remove ICV */ | 305 | /* remove ICV */ |
300 | skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN); | 306 | if (pskb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN)) |
307 | return RX_DROP_UNUSABLE; | ||
301 | } | 308 | } |
302 | 309 | ||
303 | return RX_CONTINUE; | 310 | return RX_CONTINUE; |
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h index 01e54840a628..9615749d1f65 100644 --- a/net/mac80211/wep.h +++ b/net/mac80211/wep.h | |||
@@ -25,7 +25,6 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, | |||
25 | const u8 *key, int keylen, int keyidx); | 25 | const u8 *key, int keylen, int keyidx); |
26 | int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, | 26 | int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, |
27 | size_t klen, u8 *data, size_t data_len); | 27 | size_t klen, u8 *data, size_t data_len); |
28 | bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); | ||
29 | 28 | ||
30 | ieee80211_rx_result | 29 | ieee80211_rx_result |
31 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx); | 30 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx); |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index b758350919ff..0ae23c60968c 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -138,6 +138,10 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
138 | if (skb->len < hdrlen + MICHAEL_MIC_LEN) | 138 | if (skb->len < hdrlen + MICHAEL_MIC_LEN) |
139 | return RX_DROP_UNUSABLE; | 139 | return RX_DROP_UNUSABLE; |
140 | 140 | ||
141 | if (skb_linearize(rx->skb)) | ||
142 | return RX_DROP_UNUSABLE; | ||
143 | hdr = (void *)skb->data; | ||
144 | |||
141 | data = skb->data + hdrlen; | 145 | data = skb->data + hdrlen; |
142 | data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; | 146 | data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; |
143 | key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; | 147 | key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; |
@@ -253,6 +257,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
253 | if (!rx->sta || skb->len - hdrlen < 12) | 257 | if (!rx->sta || skb->len - hdrlen < 12) |
254 | return RX_DROP_UNUSABLE; | 258 | return RX_DROP_UNUSABLE; |
255 | 259 | ||
260 | /* it may be possible to optimize this a bit more */ | ||
261 | if (skb_linearize(rx->skb)) | ||
262 | return RX_DROP_UNUSABLE; | ||
263 | hdr = (void *)skb->data; | ||
264 | |||
256 | /* | 265 | /* |
257 | * Let TKIP code verify IV, but skip decryption. | 266 | * Let TKIP code verify IV, but skip decryption. |
258 | * In the case where hardware checks the IV as well, | 267 | * In the case where hardware checks the IV as well, |
@@ -484,6 +493,14 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
484 | if (!rx->sta || data_len < 0) | 493 | if (!rx->sta || data_len < 0) |
485 | return RX_DROP_UNUSABLE; | 494 | return RX_DROP_UNUSABLE; |
486 | 495 | ||
496 | if (status->flag & RX_FLAG_DECRYPTED) { | ||
497 | if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN)) | ||
498 | return RX_DROP_UNUSABLE; | ||
499 | } else { | ||
500 | if (skb_linearize(rx->skb)) | ||
501 | return RX_DROP_UNUSABLE; | ||
502 | } | ||
503 | |||
487 | ccmp_hdr2pn(pn, skb->data + hdrlen); | 504 | ccmp_hdr2pn(pn, skb->data + hdrlen); |
488 | 505 | ||
489 | queue = rx->security_idx; | 506 | queue = rx->security_idx; |
@@ -509,7 +526,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
509 | memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); | 526 | memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); |
510 | 527 | ||
511 | /* Remove CCMP header and MIC */ | 528 | /* Remove CCMP header and MIC */ |
512 | skb_trim(skb, skb->len - CCMP_MIC_LEN); | 529 | if (pskb_trim(skb, skb->len - CCMP_MIC_LEN)) |
530 | return RX_DROP_UNUSABLE; | ||
513 | memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen); | 531 | memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen); |
514 | skb_pull(skb, CCMP_HDR_LEN); | 532 | skb_pull(skb, CCMP_HDR_LEN); |
515 | 533 | ||
@@ -609,6 +627,8 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | |||
609 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 627 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
610 | return RX_CONTINUE; | 628 | return RX_CONTINUE; |
611 | 629 | ||
630 | /* management frames are already linear */ | ||
631 | |||
612 | if (skb->len < 24 + sizeof(*mmie)) | 632 | if (skb->len < 24 + sizeof(*mmie)) |
613 | return RX_DROP_UNUSABLE; | 633 | return RX_DROP_UNUSABLE; |
614 | 634 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 39dbdf2adb12..4c1eb9472ddb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -205,6 +205,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
205 | }, | 205 | }, |
206 | [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, | 206 | [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, |
207 | [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 }, | 207 | [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 }, |
208 | [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 }, | ||
208 | }; | 209 | }; |
209 | 210 | ||
210 | /* policy for the key attributes */ | 211 | /* policy for the key attributes */ |
@@ -5116,6 +5117,13 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
5116 | 5117 | ||
5117 | wiphy = &rdev->wiphy; | 5118 | wiphy = &rdev->wiphy; |
5118 | 5119 | ||
5120 | connect.bg_scan_period = -1; | ||
5121 | if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] && | ||
5122 | (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) { | ||
5123 | connect.bg_scan_period = | ||
5124 | nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]); | ||
5125 | } | ||
5126 | |||
5119 | if (info->attrs[NL80211_ATTR_MAC]) | 5127 | if (info->attrs[NL80211_ATTR_MAC]) |
5120 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 5128 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
5121 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 5129 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index afde7e5f0010..70faadf16a32 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -734,9 +734,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
734 | struct cfg80211_bss* | 734 | struct cfg80211_bss* |
735 | cfg80211_inform_bss(struct wiphy *wiphy, | 735 | cfg80211_inform_bss(struct wiphy *wiphy, |
736 | struct ieee80211_channel *channel, | 736 | struct ieee80211_channel *channel, |
737 | const u8 *bssid, | 737 | const u8 *bssid, u64 tsf, u16 capability, |
738 | u64 timestamp, u16 capability, u16 beacon_interval, | 738 | u16 beacon_interval, const u8 *ie, size_t ielen, |
739 | const u8 *ie, size_t ielen, | ||
740 | s32 signal, gfp_t gfp) | 739 | s32 signal, gfp_t gfp) |
741 | { | 740 | { |
742 | struct cfg80211_internal_bss *res; | 741 | struct cfg80211_internal_bss *res; |
@@ -758,7 +757,7 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
758 | memcpy(res->pub.bssid, bssid, ETH_ALEN); | 757 | memcpy(res->pub.bssid, bssid, ETH_ALEN); |
759 | res->pub.channel = channel; | 758 | res->pub.channel = channel; |
760 | res->pub.signal = signal; | 759 | res->pub.signal = signal; |
761 | res->pub.tsf = timestamp; | 760 | res->pub.tsf = tsf; |
762 | res->pub.beacon_interval = beacon_interval; | 761 | res->pub.beacon_interval = beacon_interval; |
763 | res->pub.capability = capability; | 762 | res->pub.capability = capability; |
764 | /* | 763 | /* |
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 326750b99151..7c01c2f3b6cf 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -30,6 +30,9 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | |||
30 | wdev->wext.connect.ie = wdev->wext.ie; | 30 | wdev->wext.connect.ie = wdev->wext.ie; |
31 | wdev->wext.connect.ie_len = wdev->wext.ie_len; | 31 | wdev->wext.connect.ie_len = wdev->wext.ie_len; |
32 | 32 | ||
33 | /* Use default background scan period */ | ||
34 | wdev->wext.connect.bg_scan_period = -1; | ||
35 | |||
33 | if (wdev->wext.keys) { | 36 | if (wdev->wext.keys) { |
34 | wdev->wext.keys->def = wdev->wext.default_key; | 37 | wdev->wext.keys->def = wdev->wext.default_key; |
35 | wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; | 38 | wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; |