diff options
Diffstat (limited to 'net/mac80211')
36 files changed, 1188 insertions, 377 deletions
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index b9b595c0811..0785e95c992 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <crypto/aes.h> | ||
14 | 15 | ||
15 | #include <net/mac80211.h> | 16 | #include <net/mac80211.h> |
16 | #include "key.h" | 17 | #include "key.h" |
@@ -21,21 +22,21 @@ static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a) | |||
21 | int i; | 22 | int i; |
22 | u8 *b_0, *aad, *b, *s_0; | 23 | u8 *b_0, *aad, *b, *s_0; |
23 | 24 | ||
24 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 25 | b_0 = scratch + 3 * AES_BLOCK_SIZE; |
25 | aad = scratch + 4 * AES_BLOCK_LEN; | 26 | aad = scratch + 4 * AES_BLOCK_SIZE; |
26 | b = scratch; | 27 | b = scratch; |
27 | s_0 = scratch + AES_BLOCK_LEN; | 28 | s_0 = scratch + AES_BLOCK_SIZE; |
28 | 29 | ||
29 | crypto_cipher_encrypt_one(tfm, b, b_0); | 30 | crypto_cipher_encrypt_one(tfm, b, b_0); |
30 | 31 | ||
31 | /* Extra Authenticate-only data (always two AES blocks) */ | 32 | /* Extra Authenticate-only data (always two AES blocks) */ |
32 | for (i = 0; i < AES_BLOCK_LEN; i++) | 33 | for (i = 0; i < AES_BLOCK_SIZE; i++) |
33 | aad[i] ^= b[i]; | 34 | aad[i] ^= b[i]; |
34 | crypto_cipher_encrypt_one(tfm, b, aad); | 35 | crypto_cipher_encrypt_one(tfm, b, aad); |
35 | 36 | ||
36 | aad += AES_BLOCK_LEN; | 37 | aad += AES_BLOCK_SIZE; |
37 | 38 | ||
38 | for (i = 0; i < AES_BLOCK_LEN; i++) | 39 | for (i = 0; i < AES_BLOCK_SIZE; i++) |
39 | aad[i] ^= b[i]; | 40 | aad[i] ^= b[i]; |
40 | crypto_cipher_encrypt_one(tfm, a, aad); | 41 | crypto_cipher_encrypt_one(tfm, a, aad); |
41 | 42 | ||
@@ -57,12 +58,12 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
57 | u8 *pos, *cpos, *b, *s_0, *e, *b_0; | 58 | u8 *pos, *cpos, *b, *s_0, *e, *b_0; |
58 | 59 | ||
59 | b = scratch; | 60 | b = scratch; |
60 | s_0 = scratch + AES_BLOCK_LEN; | 61 | s_0 = scratch + AES_BLOCK_SIZE; |
61 | e = scratch + 2 * AES_BLOCK_LEN; | 62 | e = scratch + 2 * AES_BLOCK_SIZE; |
62 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 63 | b_0 = scratch + 3 * AES_BLOCK_SIZE; |
63 | 64 | ||
64 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); | 65 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); |
65 | last_len = data_len % AES_BLOCK_LEN; | 66 | last_len = data_len % AES_BLOCK_SIZE; |
66 | aes_ccm_prepare(tfm, scratch, b); | 67 | aes_ccm_prepare(tfm, scratch, b); |
67 | 68 | ||
68 | /* Process payload blocks */ | 69 | /* Process payload blocks */ |
@@ -70,7 +71,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
70 | cpos = cdata; | 71 | cpos = cdata; |
71 | for (j = 1; j <= num_blocks; j++) { | 72 | for (j = 1; j <= num_blocks; j++) { |
72 | int blen = (j == num_blocks && last_len) ? | 73 | int blen = (j == num_blocks && last_len) ? |
73 | last_len : AES_BLOCK_LEN; | 74 | last_len : AES_BLOCK_SIZE; |
74 | 75 | ||
75 | /* Authentication followed by encryption */ | 76 | /* Authentication followed by encryption */ |
76 | for (i = 0; i < blen; i++) | 77 | for (i = 0; i < blen; i++) |
@@ -96,12 +97,12 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
96 | u8 *pos, *cpos, *b, *s_0, *a, *b_0; | 97 | u8 *pos, *cpos, *b, *s_0, *a, *b_0; |
97 | 98 | ||
98 | b = scratch; | 99 | b = scratch; |
99 | s_0 = scratch + AES_BLOCK_LEN; | 100 | s_0 = scratch + AES_BLOCK_SIZE; |
100 | a = scratch + 2 * AES_BLOCK_LEN; | 101 | a = scratch + 2 * AES_BLOCK_SIZE; |
101 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 102 | b_0 = scratch + 3 * AES_BLOCK_SIZE; |
102 | 103 | ||
103 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); | 104 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); |
104 | last_len = data_len % AES_BLOCK_LEN; | 105 | last_len = data_len % AES_BLOCK_SIZE; |
105 | aes_ccm_prepare(tfm, scratch, a); | 106 | aes_ccm_prepare(tfm, scratch, a); |
106 | 107 | ||
107 | /* Process payload blocks */ | 108 | /* Process payload blocks */ |
@@ -109,7 +110,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
109 | pos = data; | 110 | pos = data; |
110 | for (j = 1; j <= num_blocks; j++) { | 111 | for (j = 1; j <= num_blocks; j++) { |
111 | int blen = (j == num_blocks && last_len) ? | 112 | int blen = (j == num_blocks && last_len) ? |
112 | last_len : AES_BLOCK_LEN; | 113 | last_len : AES_BLOCK_SIZE; |
113 | 114 | ||
114 | /* Decryption followed by authentication */ | 115 | /* Decryption followed by authentication */ |
115 | b_0[14] = (j >> 8) & 0xff; | 116 | b_0[14] = (j >> 8) & 0xff; |
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h index 6e7820ef344..5b7d744e237 100644 --- a/net/mac80211/aes_ccm.h +++ b/net/mac80211/aes_ccm.h | |||
@@ -12,8 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/crypto.h> | 13 | #include <linux/crypto.h> |
14 | 14 | ||
15 | #define AES_BLOCK_LEN 16 | ||
16 | |||
17 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); | 15 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); |
18 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | 16 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, |
19 | u8 *data, size_t data_len, | 17 | u8 *data, size_t data_len, |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index d502b2684a6..8dfd70d8fcf 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -11,12 +11,12 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <crypto/aes.h> | ||
14 | 15 | ||
15 | #include <net/mac80211.h> | 16 | #include <net/mac80211.h> |
16 | #include "key.h" | 17 | #include "key.h" |
17 | #include "aes_cmac.h" | 18 | #include "aes_cmac.h" |
18 | 19 | ||
19 | #define AES_BLOCK_SIZE 16 | ||
20 | #define AES_CMAC_KEY_LEN 16 | 20 | #define AES_CMAC_KEY_LEN 16 |
21 | #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ | 21 | #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ |
22 | #define AAD_LEN 20 | 22 | #define AAD_LEN 20 |
@@ -35,10 +35,10 @@ static void gf_mulx(u8 *pad) | |||
35 | } | 35 | } |
36 | 36 | ||
37 | 37 | ||
38 | static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch, | 38 | static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, |
39 | size_t num_elem, | ||
40 | const u8 *addr[], const size_t *len, u8 *mac) | 39 | const u8 *addr[], const size_t *len, u8 *mac) |
41 | { | 40 | { |
41 | u8 scratch[2 * AES_BLOCK_SIZE]; | ||
42 | u8 *cbc, *pad; | 42 | u8 *cbc, *pad; |
43 | const u8 *pos, *end; | 43 | const u8 *pos, *end; |
44 | size_t i, e, left, total_len; | 44 | size_t i, e, left, total_len; |
@@ -95,7 +95,7 @@ static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch, | |||
95 | } | 95 | } |
96 | 96 | ||
97 | 97 | ||
98 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, | 98 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, |
99 | const u8 *data, size_t data_len, u8 *mic) | 99 | const u8 *data, size_t data_len, u8 *mic) |
100 | { | 100 | { |
101 | const u8 *addr[3]; | 101 | const u8 *addr[3]; |
@@ -110,7 +110,7 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, | |||
110 | addr[2] = zero; | 110 | addr[2] = zero; |
111 | len[2] = CMAC_TLEN; | 111 | len[2] = CMAC_TLEN; |
112 | 112 | ||
113 | aes_128_cmac_vector(tfm, scratch, 3, addr, len, mic); | 113 | aes_128_cmac_vector(tfm, 3, addr, len, mic); |
114 | } | 114 | } |
115 | 115 | ||
116 | 116 | ||
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h index 0eb9a483150..20785a64725 100644 --- a/net/mac80211/aes_cmac.h +++ b/net/mac80211/aes_cmac.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | 13 | ||
14 | struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); | 14 | struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); |
15 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, | 15 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, |
16 | const u8 *data, size_t data_len, u8 *mic); | 16 | const u8 *data, size_t data_len, u8 *mic); |
17 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); | 17 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); |
18 | 18 | ||
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 9c0d76cdca9..fd1aaf2a4a6 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -100,6 +100,29 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
100 | mutex_unlock(&sta->ampdu_mlme.mtx); | 100 | mutex_unlock(&sta->ampdu_mlme.mtx); |
101 | } | 101 | } |
102 | 102 | ||
103 | void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap, | ||
104 | const u8 *addr) | ||
105 | { | ||
106 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
107 | struct sta_info *sta; | ||
108 | int i; | ||
109 | |||
110 | rcu_read_lock(); | ||
111 | sta = sta_info_get(sdata, addr); | ||
112 | if (!sta) { | ||
113 | rcu_read_unlock(); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | for (i = 0; i < STA_TID_NUM; i++) | ||
118 | if (ba_rx_bitmap & BIT(i)) | ||
119 | set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested); | ||
120 | |||
121 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); | ||
122 | rcu_read_unlock(); | ||
123 | } | ||
124 | EXPORT_SYMBOL(ieee80211_stop_rx_ba_session); | ||
125 | |||
103 | /* | 126 | /* |
104 | * After accepting the AddBA Request we activated a timer, | 127 | * After accepting the AddBA Request we activated a timer, |
105 | * resetting it after each frame that arrives from the originator. | 128 | * resetting it after each frame that arrives from the originator. |
@@ -247,7 +270,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
247 | "%pM on tid %u\n", | 270 | "%pM on tid %u\n", |
248 | mgmt->sa, tid); | 271 | mgmt->sa, tid); |
249 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 272 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
250 | goto end; | 273 | |
274 | /* delete existing Rx BA session on the same tid */ | ||
275 | ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, | ||
276 | WLAN_STATUS_UNSPECIFIED_QOS, | ||
277 | false); | ||
251 | } | 278 | } |
252 | 279 | ||
253 | /* prepare A-MPDU MLME for Rx aggregation */ | 280 | /* prepare A-MPDU MLME for Rx aggregation */ |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index c8be8eff70d..b7f4f5c1f69 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -162,6 +162,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
162 | return -ENOENT; | 162 | return -ENOENT; |
163 | } | 163 | } |
164 | 164 | ||
165 | /* if we're already stopping ignore any new requests to stop */ | ||
166 | if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | ||
167 | spin_unlock_bh(&sta->lock); | ||
168 | return -EALREADY; | ||
169 | } | ||
170 | |||
165 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | 171 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { |
166 | /* not even started yet! */ | 172 | /* not even started yet! */ |
167 | ieee80211_assign_tid_tx(sta, tid, NULL); | 173 | ieee80211_assign_tid_tx(sta, tid, NULL); |
@@ -170,6 +176,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
170 | return 0; | 176 | return 0; |
171 | } | 177 | } |
172 | 178 | ||
179 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); | ||
180 | |||
173 | spin_unlock_bh(&sta->lock); | 181 | spin_unlock_bh(&sta->lock); |
174 | 182 | ||
175 | #ifdef CONFIG_MAC80211_HT_DEBUG | 183 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -177,8 +185,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
177 | sta->sta.addr, tid); | 185 | sta->sta.addr, tid); |
178 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 186 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
179 | 187 | ||
180 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); | ||
181 | |||
182 | del_timer_sync(&tid_tx->addba_resp_timer); | 188 | del_timer_sync(&tid_tx->addba_resp_timer); |
183 | 189 | ||
184 | /* | 190 | /* |
@@ -188,6 +194,20 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
188 | */ | 194 | */ |
189 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); | 195 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); |
190 | 196 | ||
197 | /* | ||
198 | * There might be a few packets being processed right now (on | ||
199 | * another CPU) that have already gotten past the aggregation | ||
200 | * check when it was still OPERATIONAL and consequently have | ||
201 | * IEEE80211_TX_CTL_AMPDU set. In that case, this code might | ||
202 | * call into the driver at the same time or even before the | ||
203 | * TX paths calls into it, which could confuse the driver. | ||
204 | * | ||
205 | * Wait for all currently running TX paths to finish before | ||
206 | * telling the driver. New packets will not go through since | ||
207 | * the aggregation session is no longer OPERATIONAL. | ||
208 | */ | ||
209 | synchronize_net(); | ||
210 | |||
191 | tid_tx->stop_initiator = initiator; | 211 | tid_tx->stop_initiator = initiator; |
192 | tid_tx->tx_stop = tx; | 212 | tid_tx->tx_stop = tx; |
193 | 213 | ||
@@ -284,6 +304,38 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | |||
284 | __release(agg_queue); | 304 | __release(agg_queue); |
285 | } | 305 | } |
286 | 306 | ||
307 | /* | ||
308 | * splice packets from the STA's pending to the local pending, | ||
309 | * requires a call to ieee80211_agg_splice_finish later | ||
310 | */ | ||
311 | static void __acquires(agg_queue) | ||
312 | ieee80211_agg_splice_packets(struct ieee80211_local *local, | ||
313 | struct tid_ampdu_tx *tid_tx, u16 tid) | ||
314 | { | ||
315 | int queue = ieee80211_ac_from_tid(tid); | ||
316 | unsigned long flags; | ||
317 | |||
318 | ieee80211_stop_queue_agg(local, tid); | ||
319 | |||
320 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" | ||
321 | " from the pending queue\n", tid)) | ||
322 | return; | ||
323 | |||
324 | if (!skb_queue_empty(&tid_tx->pending)) { | ||
325 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
326 | /* copy over remaining packets */ | ||
327 | skb_queue_splice_tail_init(&tid_tx->pending, | ||
328 | &local->pending[queue]); | ||
329 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static void __releases(agg_queue) | ||
334 | ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | ||
335 | { | ||
336 | ieee80211_wake_queue_agg(local, tid); | ||
337 | } | ||
338 | |||
287 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | 339 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
288 | { | 340 | { |
289 | struct tid_ampdu_tx *tid_tx; | 341 | struct tid_ampdu_tx *tid_tx; |
@@ -295,19 +347,17 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
295 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 347 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
296 | 348 | ||
297 | /* | 349 | /* |
298 | * While we're asking the driver about the aggregation, | 350 | * Start queuing up packets for this aggregation session. |
299 | * stop the AC queue so that we don't have to worry | 351 | * We're going to release them once the driver is OK with |
300 | * about frames that came in while we were doing that, | 352 | * that. |
301 | * which would require us to put them to the AC pending | ||
302 | * afterwards which just makes the code more complex. | ||
303 | */ | 353 | */ |
304 | ieee80211_stop_queue_agg(local, tid); | ||
305 | |||
306 | clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); | 354 | clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); |
307 | 355 | ||
308 | /* | 356 | /* |
309 | * make sure no packets are being processed to get | 357 | * Make sure no packets are being processed. This ensures that |
310 | * valid starting sequence number | 358 | * we have a valid starting sequence number and that in-flight |
359 | * packets have been flushed out and no packets for this TID | ||
360 | * will go into the driver during the ampdu_action call. | ||
311 | */ | 361 | */ |
312 | synchronize_net(); | 362 | synchronize_net(); |
313 | 363 | ||
@@ -321,17 +371,15 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
321 | " tid %d\n", tid); | 371 | " tid %d\n", tid); |
322 | #endif | 372 | #endif |
323 | spin_lock_bh(&sta->lock); | 373 | spin_lock_bh(&sta->lock); |
374 | ieee80211_agg_splice_packets(local, tid_tx, tid); | ||
324 | ieee80211_assign_tid_tx(sta, tid, NULL); | 375 | ieee80211_assign_tid_tx(sta, tid, NULL); |
376 | ieee80211_agg_splice_finish(local, tid); | ||
325 | spin_unlock_bh(&sta->lock); | 377 | spin_unlock_bh(&sta->lock); |
326 | 378 | ||
327 | ieee80211_wake_queue_agg(local, tid); | ||
328 | kfree_rcu(tid_tx, rcu_head); | 379 | kfree_rcu(tid_tx, rcu_head); |
329 | return; | 380 | return; |
330 | } | 381 | } |
331 | 382 | ||
332 | /* we can take packets again now */ | ||
333 | ieee80211_wake_queue_agg(local, tid); | ||
334 | |||
335 | /* activate the timer for the recipient's addBA response */ | 383 | /* activate the timer for the recipient's addBA response */ |
336 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); | 384 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); |
337 | #ifdef CONFIG_MAC80211_HT_DEBUG | 385 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -451,38 +499,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
451 | } | 499 | } |
452 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | 500 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); |
453 | 501 | ||
454 | /* | ||
455 | * splice packets from the STA's pending to the local pending, | ||
456 | * requires a call to ieee80211_agg_splice_finish later | ||
457 | */ | ||
458 | static void __acquires(agg_queue) | ||
459 | ieee80211_agg_splice_packets(struct ieee80211_local *local, | ||
460 | struct tid_ampdu_tx *tid_tx, u16 tid) | ||
461 | { | ||
462 | int queue = ieee80211_ac_from_tid(tid); | ||
463 | unsigned long flags; | ||
464 | |||
465 | ieee80211_stop_queue_agg(local, tid); | ||
466 | |||
467 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" | ||
468 | " from the pending queue\n", tid)) | ||
469 | return; | ||
470 | |||
471 | if (!skb_queue_empty(&tid_tx->pending)) { | ||
472 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
473 | /* copy over remaining packets */ | ||
474 | skb_queue_splice_tail_init(&tid_tx->pending, | ||
475 | &local->pending[queue]); | ||
476 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | static void __releases(agg_queue) | ||
481 | ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | ||
482 | { | ||
483 | ieee80211_wake_queue_agg(local, tid); | ||
484 | } | ||
485 | |||
486 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | 502 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, |
487 | struct sta_info *sta, u16 tid) | 503 | struct sta_info *sta, u16 tid) |
488 | { | 504 | { |
@@ -772,12 +788,27 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
772 | goto out; | 788 | goto out; |
773 | } | 789 | } |
774 | 790 | ||
775 | del_timer(&tid_tx->addba_resp_timer); | 791 | del_timer_sync(&tid_tx->addba_resp_timer); |
776 | 792 | ||
777 | #ifdef CONFIG_MAC80211_HT_DEBUG | 793 | #ifdef CONFIG_MAC80211_HT_DEBUG |
778 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); | 794 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); |
779 | #endif | 795 | #endif |
780 | 796 | ||
797 | /* | ||
798 | * addba_resp_timer may have fired before we got here, and | ||
799 | * caused WANT_STOP to be set. If the stop then was already | ||
800 | * processed further, STOPPING might be set. | ||
801 | */ | ||
802 | if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || | ||
803 | test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | ||
804 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
805 | printk(KERN_DEBUG | ||
806 | "got addBA resp for tid %d but we already gave up\n", | ||
807 | tid); | ||
808 | #endif | ||
809 | goto out; | ||
810 | } | ||
811 | |||
781 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 812 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
782 | == WLAN_STATUS_SUCCESS) { | 813 | == WLAN_STATUS_SUCCESS) { |
783 | /* | 814 | /* |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index be70c70d3f5..10c95be3b30 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -209,6 +209,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
209 | u8 seq[6] = {0}; | 209 | u8 seq[6] = {0}; |
210 | struct key_params params; | 210 | struct key_params params; |
211 | struct ieee80211_key *key = NULL; | 211 | struct ieee80211_key *key = NULL; |
212 | u64 pn64; | ||
212 | u32 iv32; | 213 | u32 iv32; |
213 | u16 iv16; | 214 | u16 iv16; |
214 | int err = -ENOENT; | 215 | int err = -ENOENT; |
@@ -256,22 +257,24 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
256 | params.seq_len = 6; | 257 | params.seq_len = 6; |
257 | break; | 258 | break; |
258 | case WLAN_CIPHER_SUITE_CCMP: | 259 | case WLAN_CIPHER_SUITE_CCMP: |
259 | seq[0] = key->u.ccmp.tx_pn[5]; | 260 | pn64 = atomic64_read(&key->u.ccmp.tx_pn); |
260 | seq[1] = key->u.ccmp.tx_pn[4]; | 261 | seq[0] = pn64; |
261 | seq[2] = key->u.ccmp.tx_pn[3]; | 262 | seq[1] = pn64 >> 8; |
262 | seq[3] = key->u.ccmp.tx_pn[2]; | 263 | seq[2] = pn64 >> 16; |
263 | seq[4] = key->u.ccmp.tx_pn[1]; | 264 | seq[3] = pn64 >> 24; |
264 | seq[5] = key->u.ccmp.tx_pn[0]; | 265 | seq[4] = pn64 >> 32; |
266 | seq[5] = pn64 >> 40; | ||
265 | params.seq = seq; | 267 | params.seq = seq; |
266 | params.seq_len = 6; | 268 | params.seq_len = 6; |
267 | break; | 269 | break; |
268 | case WLAN_CIPHER_SUITE_AES_CMAC: | 270 | case WLAN_CIPHER_SUITE_AES_CMAC: |
269 | seq[0] = key->u.aes_cmac.tx_pn[5]; | 271 | pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); |
270 | seq[1] = key->u.aes_cmac.tx_pn[4]; | 272 | seq[0] = pn64; |
271 | seq[2] = key->u.aes_cmac.tx_pn[3]; | 273 | seq[1] = pn64 >> 8; |
272 | seq[3] = key->u.aes_cmac.tx_pn[2]; | 274 | seq[2] = pn64 >> 16; |
273 | seq[4] = key->u.aes_cmac.tx_pn[1]; | 275 | seq[3] = pn64 >> 24; |
274 | seq[5] = key->u.aes_cmac.tx_pn[0]; | 276 | seq[4] = pn64 >> 32; |
277 | seq[5] = pn64 >> 40; | ||
275 | params.seq = seq; | 278 | params.seq = seq; |
276 | params.seq_len = 6; | 279 | params.seq_len = 6; |
277 | break; | 280 | break; |
@@ -674,8 +677,11 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
674 | 677 | ||
675 | if (mask & BIT(NL80211_STA_FLAG_WME)) { | 678 | if (mask & BIT(NL80211_STA_FLAG_WME)) { |
676 | sta->flags &= ~WLAN_STA_WME; | 679 | sta->flags &= ~WLAN_STA_WME; |
677 | if (set & BIT(NL80211_STA_FLAG_WME)) | 680 | sta->sta.wme = false; |
681 | if (set & BIT(NL80211_STA_FLAG_WME)) { | ||
678 | sta->flags |= WLAN_STA_WME; | 682 | sta->flags |= WLAN_STA_WME; |
683 | sta->sta.wme = true; | ||
684 | } | ||
679 | } | 685 | } |
680 | 686 | ||
681 | if (mask & BIT(NL80211_STA_FLAG_MFP)) { | 687 | if (mask & BIT(NL80211_STA_FLAG_MFP)) { |
@@ -1249,6 +1255,10 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1249 | */ | 1255 | */ |
1250 | p.uapsd = false; | 1256 | p.uapsd = false; |
1251 | 1257 | ||
1258 | if (params->queue >= local->hw.queues) | ||
1259 | return -EINVAL; | ||
1260 | |||
1261 | local->tx_conf[params->queue] = p; | ||
1252 | if (drv_conf_tx(local, params->queue, &p)) { | 1262 | if (drv_conf_tx(local, params->queue, &p)) { |
1253 | wiphy_debug(local->hw.wiphy, | 1263 | wiphy_debug(local->hw.wiphy, |
1254 | "failed to set TX queue parameters for queue %d\n", | 1264 | "failed to set TX queue parameters for queue %d\n", |
@@ -1554,6 +1564,19 @@ static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) | |||
1554 | 1564 | ||
1555 | return local->ops->testmode_cmd(&local->hw, data, len); | 1565 | return local->ops->testmode_cmd(&local->hw, data, len); |
1556 | } | 1566 | } |
1567 | |||
1568 | static int ieee80211_testmode_dump(struct wiphy *wiphy, | ||
1569 | struct sk_buff *skb, | ||
1570 | struct netlink_callback *cb, | ||
1571 | void *data, int len) | ||
1572 | { | ||
1573 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1574 | |||
1575 | if (!local->ops->testmode_dump) | ||
1576 | return -EOPNOTSUPP; | ||
1577 | |||
1578 | return local->ops->testmode_dump(&local->hw, skb, cb, data, len); | ||
1579 | } | ||
1557 | #endif | 1580 | #endif |
1558 | 1581 | ||
1559 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | 1582 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, |
@@ -1798,7 +1821,7 @@ ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) | |||
1798 | * so in that case userspace will have to deal with it. | 1821 | * so in that case userspace will have to deal with it. |
1799 | */ | 1822 | */ |
1800 | 1823 | ||
1801 | if (wk->offchan_tx.wait && wk->offchan_tx.frame) | 1824 | if (wk->offchan_tx.wait && !wk->offchan_tx.status) |
1802 | cfg80211_mgmt_tx_status(wk->sdata->dev, | 1825 | cfg80211_mgmt_tx_status(wk->sdata->dev, |
1803 | (unsigned long) wk->offchan_tx.frame, | 1826 | (unsigned long) wk->offchan_tx.frame, |
1804 | wk->ie, wk->ie_len, false, GFP_KERNEL); | 1827 | wk->ie, wk->ie_len, false, GFP_KERNEL); |
@@ -2085,6 +2108,21 @@ static void ieee80211_get_ringparam(struct wiphy *wiphy, | |||
2085 | drv_get_ringparam(local, tx, tx_max, rx, rx_max); | 2108 | drv_get_ringparam(local, tx, tx_max, rx, rx_max); |
2086 | } | 2109 | } |
2087 | 2110 | ||
2111 | static int ieee80211_set_rekey_data(struct wiphy *wiphy, | ||
2112 | struct net_device *dev, | ||
2113 | struct cfg80211_gtk_rekey_data *data) | ||
2114 | { | ||
2115 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
2116 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2117 | |||
2118 | if (!local->ops->set_rekey_data) | ||
2119 | return -EOPNOTSUPP; | ||
2120 | |||
2121 | drv_set_rekey_data(local, sdata, data); | ||
2122 | |||
2123 | return 0; | ||
2124 | } | ||
2125 | |||
2088 | struct cfg80211_ops mac80211_config_ops = { | 2126 | struct cfg80211_ops mac80211_config_ops = { |
2089 | .add_virtual_intf = ieee80211_add_iface, | 2127 | .add_virtual_intf = ieee80211_add_iface, |
2090 | .del_virtual_intf = ieee80211_del_iface, | 2128 | .del_virtual_intf = ieee80211_del_iface, |
@@ -2134,6 +2172,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2134 | .set_wds_peer = ieee80211_set_wds_peer, | 2172 | .set_wds_peer = ieee80211_set_wds_peer, |
2135 | .rfkill_poll = ieee80211_rfkill_poll, | 2173 | .rfkill_poll = ieee80211_rfkill_poll, |
2136 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) | 2174 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) |
2175 | CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump) | ||
2137 | .set_power_mgmt = ieee80211_set_power_mgmt, | 2176 | .set_power_mgmt = ieee80211_set_power_mgmt, |
2138 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 2177 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
2139 | .remain_on_channel = ieee80211_remain_on_channel, | 2178 | .remain_on_channel = ieee80211_remain_on_channel, |
@@ -2146,4 +2185,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2146 | .get_antenna = ieee80211_get_antenna, | 2185 | .get_antenna = ieee80211_get_antenna, |
2147 | .set_ringparam = ieee80211_set_ringparam, | 2186 | .set_ringparam = ieee80211_set_ringparam, |
2148 | .get_ringparam = ieee80211_get_ringparam, | 2187 | .get_ringparam = ieee80211_get_ringparam, |
2188 | .set_rekey_data = ieee80211_set_rekey_data, | ||
2149 | }; | 2189 | }; |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 33c58b85c91..38e6101190d 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -78,7 +78,7 @@ KEY_OPS(algorithm); | |||
78 | static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | 78 | static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, |
79 | size_t count, loff_t *ppos) | 79 | size_t count, loff_t *ppos) |
80 | { | 80 | { |
81 | const u8 *tpn; | 81 | u64 pn; |
82 | char buf[20]; | 82 | char buf[20]; |
83 | int len; | 83 | int len; |
84 | struct ieee80211_key *key = file->private_data; | 84 | struct ieee80211_key *key = file->private_data; |
@@ -94,15 +94,16 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | |||
94 | key->u.tkip.tx.iv16); | 94 | key->u.tkip.tx.iv16); |
95 | break; | 95 | break; |
96 | case WLAN_CIPHER_SUITE_CCMP: | 96 | case WLAN_CIPHER_SUITE_CCMP: |
97 | tpn = key->u.ccmp.tx_pn; | 97 | pn = atomic64_read(&key->u.ccmp.tx_pn); |
98 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 98 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
99 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); | 99 | (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), |
100 | (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); | ||
100 | break; | 101 | break; |
101 | case WLAN_CIPHER_SUITE_AES_CMAC: | 102 | case WLAN_CIPHER_SUITE_AES_CMAC: |
102 | tpn = key->u.aes_cmac.tx_pn; | 103 | pn = atomic64_read(&key->u.aes_cmac.tx_pn); |
103 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 104 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
104 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], | 105 | (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), |
105 | tpn[5]); | 106 | (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); |
106 | break; | 107 | break; |
107 | default: | 108 | default: |
108 | return 0; | 109 | return 0; |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index eebf7a67daf..1425380983f 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -130,6 +130,37 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
130 | trace_drv_return_void(local); | 130 | trace_drv_return_void(local); |
131 | } | 131 | } |
132 | 132 | ||
133 | static inline int drv_tx_sync(struct ieee80211_local *local, | ||
134 | struct ieee80211_sub_if_data *sdata, | ||
135 | const u8 *bssid, | ||
136 | enum ieee80211_tx_sync_type type) | ||
137 | { | ||
138 | int ret = 0; | ||
139 | |||
140 | might_sleep(); | ||
141 | |||
142 | trace_drv_tx_sync(local, sdata, bssid, type); | ||
143 | if (local->ops->tx_sync) | ||
144 | ret = local->ops->tx_sync(&local->hw, &sdata->vif, | ||
145 | bssid, type); | ||
146 | trace_drv_return_int(local, ret); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static inline void drv_finish_tx_sync(struct ieee80211_local *local, | ||
151 | struct ieee80211_sub_if_data *sdata, | ||
152 | const u8 *bssid, | ||
153 | enum ieee80211_tx_sync_type type) | ||
154 | { | ||
155 | might_sleep(); | ||
156 | |||
157 | trace_drv_finish_tx_sync(local, sdata, bssid, type); | ||
158 | if (local->ops->finish_tx_sync) | ||
159 | local->ops->finish_tx_sync(&local->hw, &sdata->vif, | ||
160 | bssid, type); | ||
161 | trace_drv_return_void(local); | ||
162 | } | ||
163 | |||
133 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | 164 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, |
134 | struct netdev_hw_addr_list *mc_list) | 165 | struct netdev_hw_addr_list *mc_list) |
135 | { | 166 | { |
@@ -218,6 +249,16 @@ static inline int drv_hw_scan(struct ieee80211_local *local, | |||
218 | return ret; | 249 | return ret; |
219 | } | 250 | } |
220 | 251 | ||
252 | static inline void drv_cancel_hw_scan(struct ieee80211_local *local, | ||
253 | struct ieee80211_sub_if_data *sdata) | ||
254 | { | ||
255 | might_sleep(); | ||
256 | |||
257 | trace_drv_cancel_hw_scan(local, sdata); | ||
258 | local->ops->cancel_hw_scan(&local->hw, &sdata->vif); | ||
259 | trace_drv_return_void(local); | ||
260 | } | ||
261 | |||
221 | static inline int | 262 | static inline int |
222 | drv_sched_scan_start(struct ieee80211_local *local, | 263 | drv_sched_scan_start(struct ieee80211_local *local, |
223 | struct ieee80211_sub_if_data *sdata, | 264 | struct ieee80211_sub_if_data *sdata, |
@@ -637,4 +678,22 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local, | |||
637 | return ret; | 678 | return ret; |
638 | } | 679 | } |
639 | 680 | ||
681 | static inline void drv_set_rekey_data(struct ieee80211_local *local, | ||
682 | struct ieee80211_sub_if_data *sdata, | ||
683 | struct cfg80211_gtk_rekey_data *data) | ||
684 | { | ||
685 | trace_drv_set_rekey_data(local, sdata, data); | ||
686 | if (local->ops->set_rekey_data) | ||
687 | local->ops->set_rekey_data(&local->hw, &sdata->vif, data); | ||
688 | trace_drv_return_void(local); | ||
689 | } | ||
690 | |||
691 | static inline void drv_rssi_callback(struct ieee80211_local *local, | ||
692 | const enum ieee80211_rssi_event event) | ||
693 | { | ||
694 | trace_drv_rssi_callback(local, event); | ||
695 | if (local->ops->rssi_callback) | ||
696 | local->ops->rssi_callback(&local->hw, event); | ||
697 | trace_drv_return_void(local); | ||
698 | } | ||
640 | #endif /* __MAC80211_DRIVER_OPS */ | 699 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index ed9edcbd9aa..f47b00dc7af 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -319,6 +319,49 @@ TRACE_EVENT(drv_bss_info_changed, | |||
319 | ) | 319 | ) |
320 | ); | 320 | ); |
321 | 321 | ||
322 | DECLARE_EVENT_CLASS(tx_sync_evt, | ||
323 | TP_PROTO(struct ieee80211_local *local, | ||
324 | struct ieee80211_sub_if_data *sdata, | ||
325 | const u8 *bssid, | ||
326 | enum ieee80211_tx_sync_type type), | ||
327 | TP_ARGS(local, sdata, bssid, type), | ||
328 | |||
329 | TP_STRUCT__entry( | ||
330 | LOCAL_ENTRY | ||
331 | VIF_ENTRY | ||
332 | __array(char, bssid, ETH_ALEN) | ||
333 | __field(u32, sync_type) | ||
334 | ), | ||
335 | |||
336 | TP_fast_assign( | ||
337 | LOCAL_ASSIGN; | ||
338 | VIF_ASSIGN; | ||
339 | memcpy(__entry->bssid, bssid, ETH_ALEN); | ||
340 | __entry->sync_type = type; | ||
341 | ), | ||
342 | |||
343 | TP_printk( | ||
344 | LOCAL_PR_FMT VIF_PR_FMT " bssid:%pM type:%d", | ||
345 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->bssid, __entry->sync_type | ||
346 | ) | ||
347 | ); | ||
348 | |||
349 | DEFINE_EVENT(tx_sync_evt, drv_tx_sync, | ||
350 | TP_PROTO(struct ieee80211_local *local, | ||
351 | struct ieee80211_sub_if_data *sdata, | ||
352 | const u8 *bssid, | ||
353 | enum ieee80211_tx_sync_type type), | ||
354 | TP_ARGS(local, sdata, bssid, type) | ||
355 | ); | ||
356 | |||
357 | DEFINE_EVENT(tx_sync_evt, drv_finish_tx_sync, | ||
358 | TP_PROTO(struct ieee80211_local *local, | ||
359 | struct ieee80211_sub_if_data *sdata, | ||
360 | const u8 *bssid, | ||
361 | enum ieee80211_tx_sync_type type), | ||
362 | TP_ARGS(local, sdata, bssid, type) | ||
363 | ); | ||
364 | |||
322 | TRACE_EVENT(drv_prepare_multicast, | 365 | TRACE_EVENT(drv_prepare_multicast, |
323 | TP_PROTO(struct ieee80211_local *local, int mc_count), | 366 | TP_PROTO(struct ieee80211_local *local, int mc_count), |
324 | 367 | ||
@@ -460,6 +503,12 @@ DEFINE_EVENT(local_sdata_evt, drv_hw_scan, | |||
460 | TP_ARGS(local, sdata) | 503 | TP_ARGS(local, sdata) |
461 | ); | 504 | ); |
462 | 505 | ||
506 | DEFINE_EVENT(local_sdata_evt, drv_cancel_hw_scan, | ||
507 | TP_PROTO(struct ieee80211_local *local, | ||
508 | struct ieee80211_sub_if_data *sdata), | ||
509 | TP_ARGS(local, sdata) | ||
510 | ); | ||
511 | |||
463 | DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start, | 512 | DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start, |
464 | TP_PROTO(struct ieee80211_local *local, | 513 | TP_PROTO(struct ieee80211_local *local, |
465 | struct ieee80211_sub_if_data *sdata), | 514 | struct ieee80211_sub_if_data *sdata), |
@@ -1018,6 +1067,56 @@ TRACE_EVENT(drv_set_bitrate_mask, | |||
1018 | ) | 1067 | ) |
1019 | ); | 1068 | ); |
1020 | 1069 | ||
1070 | TRACE_EVENT(drv_set_rekey_data, | ||
1071 | TP_PROTO(struct ieee80211_local *local, | ||
1072 | struct ieee80211_sub_if_data *sdata, | ||
1073 | struct cfg80211_gtk_rekey_data *data), | ||
1074 | |||
1075 | TP_ARGS(local, sdata, data), | ||
1076 | |||
1077 | TP_STRUCT__entry( | ||
1078 | LOCAL_ENTRY | ||
1079 | VIF_ENTRY | ||
1080 | __array(u8, kek, NL80211_KEK_LEN) | ||
1081 | __array(u8, kck, NL80211_KCK_LEN) | ||
1082 | __array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN) | ||
1083 | ), | ||
1084 | |||
1085 | TP_fast_assign( | ||
1086 | LOCAL_ASSIGN; | ||
1087 | VIF_ASSIGN; | ||
1088 | memcpy(__entry->kek, data->kek, NL80211_KEK_LEN); | ||
1089 | memcpy(__entry->kck, data->kck, NL80211_KCK_LEN); | ||
1090 | memcpy(__entry->replay_ctr, data->replay_ctr, | ||
1091 | NL80211_REPLAY_CTR_LEN); | ||
1092 | ), | ||
1093 | |||
1094 | TP_printk(LOCAL_PR_FMT VIF_PR_FMT, | ||
1095 | LOCAL_PR_ARG, VIF_PR_ARG) | ||
1096 | ); | ||
1097 | |||
1098 | TRACE_EVENT(drv_rssi_callback, | ||
1099 | TP_PROTO(struct ieee80211_local *local, | ||
1100 | enum ieee80211_rssi_event rssi_event), | ||
1101 | |||
1102 | TP_ARGS(local, rssi_event), | ||
1103 | |||
1104 | TP_STRUCT__entry( | ||
1105 | LOCAL_ENTRY | ||
1106 | __field(u32, rssi_event) | ||
1107 | ), | ||
1108 | |||
1109 | TP_fast_assign( | ||
1110 | LOCAL_ASSIGN; | ||
1111 | __entry->rssi_event = rssi_event; | ||
1112 | ), | ||
1113 | |||
1114 | TP_printk( | ||
1115 | LOCAL_PR_FMT " rssi_event:%d", | ||
1116 | LOCAL_PR_ARG, __entry->rssi_event | ||
1117 | ) | ||
1118 | ); | ||
1119 | |||
1021 | /* | 1120 | /* |
1022 | * Tracing for API calls that drivers call. | 1121 | * Tracing for API calls that drivers call. |
1023 | */ | 1122 | */ |
@@ -1287,6 +1386,51 @@ DEFINE_EVENT(local_only_evt, api_remain_on_channel_expired, | |||
1287 | TP_ARGS(local) | 1386 | TP_ARGS(local) |
1288 | ); | 1387 | ); |
1289 | 1388 | ||
1389 | TRACE_EVENT(api_gtk_rekey_notify, | ||
1390 | TP_PROTO(struct ieee80211_sub_if_data *sdata, | ||
1391 | const u8 *bssid, const u8 *replay_ctr), | ||
1392 | |||
1393 | TP_ARGS(sdata, bssid, replay_ctr), | ||
1394 | |||
1395 | TP_STRUCT__entry( | ||
1396 | VIF_ENTRY | ||
1397 | __array(u8, bssid, ETH_ALEN) | ||
1398 | __array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN) | ||
1399 | ), | ||
1400 | |||
1401 | TP_fast_assign( | ||
1402 | VIF_ASSIGN; | ||
1403 | memcpy(__entry->bssid, bssid, ETH_ALEN); | ||
1404 | memcpy(__entry->replay_ctr, replay_ctr, NL80211_REPLAY_CTR_LEN); | ||
1405 | ), | ||
1406 | |||
1407 | TP_printk(VIF_PR_FMT, VIF_PR_ARG) | ||
1408 | ); | ||
1409 | |||
1410 | TRACE_EVENT(api_enable_rssi_reports, | ||
1411 | TP_PROTO(struct ieee80211_sub_if_data *sdata, | ||
1412 | int rssi_min_thold, int rssi_max_thold), | ||
1413 | |||
1414 | TP_ARGS(sdata, rssi_min_thold, rssi_max_thold), | ||
1415 | |||
1416 | TP_STRUCT__entry( | ||
1417 | VIF_ENTRY | ||
1418 | __field(int, rssi_min_thold) | ||
1419 | __field(int, rssi_max_thold) | ||
1420 | ), | ||
1421 | |||
1422 | TP_fast_assign( | ||
1423 | VIF_ASSIGN; | ||
1424 | __entry->rssi_min_thold = rssi_min_thold; | ||
1425 | __entry->rssi_max_thold = rssi_max_thold; | ||
1426 | ), | ||
1427 | |||
1428 | TP_printk( | ||
1429 | VIF_PR_FMT " rssi_min_thold =%d, rssi_max_thold = %d", | ||
1430 | VIF_PR_ARG, __entry->rssi_min_thold, __entry->rssi_max_thold | ||
1431 | ) | ||
1432 | ); | ||
1433 | |||
1290 | /* | 1434 | /* |
1291 | * Tracing for internal functions | 1435 | * Tracing for internal functions |
1292 | * (which may also be called in response to driver calls) | 1436 | * (which may also be called in response to driver calls) |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 591add22bcc..7cfc286946c 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -140,6 +140,12 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
140 | sta, tid, WLAN_BACK_RECIPIENT, | 140 | sta, tid, WLAN_BACK_RECIPIENT, |
141 | WLAN_REASON_QSTA_TIMEOUT, true); | 141 | WLAN_REASON_QSTA_TIMEOUT, true); |
142 | 142 | ||
143 | if (test_and_clear_bit(tid, | ||
144 | sta->ampdu_mlme.tid_rx_stop_requested)) | ||
145 | ___ieee80211_stop_rx_ba_session( | ||
146 | sta, tid, WLAN_BACK_RECIPIENT, | ||
147 | WLAN_REASON_UNSPECIFIED, true); | ||
148 | |||
143 | tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; | 149 | tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; |
144 | if (tid_tx) { | 150 | if (tid_tx) { |
145 | /* | 151 | /* |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 090b0ec1e05..9fab144cc9f 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -202,7 +202,22 @@ struct ieee80211_rx_data { | |||
202 | struct ieee80211_key *key; | 202 | struct ieee80211_key *key; |
203 | 203 | ||
204 | unsigned int flags; | 204 | unsigned int flags; |
205 | int queue; | 205 | |
206 | /* | ||
207 | * Index into sequence numbers array, 0..16 | ||
208 | * since the last (16) is used for non-QoS, | ||
209 | * will be 16 on non-QoS frames. | ||
210 | */ | ||
211 | int seqno_idx; | ||
212 | |||
213 | /* | ||
214 | * Index into the security IV/PN arrays, 0..16 | ||
215 | * since the last (16) is used for CCMP-encrypted | ||
216 | * management frames, will be set to 16 on mgmt | ||
217 | * frames and 0 on non-QoS frames. | ||
218 | */ | ||
219 | int security_idx; | ||
220 | |||
206 | u32 tkip_iv32; | 221 | u32 tkip_iv32; |
207 | u16 tkip_iv16; | 222 | u16 tkip_iv16; |
208 | }; | 223 | }; |
@@ -308,6 +323,7 @@ struct ieee80211_work { | |||
308 | u8 key[WLAN_KEY_LEN_WEP104]; | 323 | u8 key[WLAN_KEY_LEN_WEP104]; |
309 | u8 key_len, key_idx; | 324 | u8 key_len, key_idx; |
310 | bool privacy; | 325 | bool privacy; |
326 | bool synced; | ||
311 | } probe_auth; | 327 | } probe_auth; |
312 | struct { | 328 | struct { |
313 | struct cfg80211_bss *bss; | 329 | struct cfg80211_bss *bss; |
@@ -321,6 +337,7 @@ struct ieee80211_work { | |||
321 | u8 ssid_len; | 337 | u8 ssid_len; |
322 | u8 supp_rates_len; | 338 | u8 supp_rates_len; |
323 | bool wmm_used, use_11n, uapsd_used; | 339 | bool wmm_used, use_11n, uapsd_used; |
340 | bool synced; | ||
324 | } assoc; | 341 | } assoc; |
325 | struct { | 342 | struct { |
326 | u32 duration; | 343 | u32 duration; |
@@ -328,6 +345,7 @@ struct ieee80211_work { | |||
328 | struct { | 345 | struct { |
329 | struct sk_buff *frame; | 346 | struct sk_buff *frame; |
330 | u32 wait; | 347 | u32 wait; |
348 | bool status; | ||
331 | } offchan_tx; | 349 | } offchan_tx; |
332 | }; | 350 | }; |
333 | 351 | ||
@@ -372,6 +390,7 @@ struct ieee80211_if_managed { | |||
372 | 390 | ||
373 | unsigned long timers_running; /* used for quiesce/restart */ | 391 | unsigned long timers_running; /* used for quiesce/restart */ |
374 | bool powersave; /* powersave requested for this iface */ | 392 | bool powersave; /* powersave requested for this iface */ |
393 | bool broken_ap; /* AP is broken -- turn off powersave */ | ||
375 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | 394 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ |
376 | ap_smps, /* smps mode AP thinks we're in */ | 395 | ap_smps, /* smps mode AP thinks we're in */ |
377 | driver_smps_mode; /* smps mode request */ | 396 | driver_smps_mode; /* smps mode request */ |
@@ -417,6 +436,14 @@ struct ieee80211_if_managed { | |||
417 | * generated for the current association. | 436 | * generated for the current association. |
418 | */ | 437 | */ |
419 | int last_cqm_event_signal; | 438 | int last_cqm_event_signal; |
439 | |||
440 | /* | ||
441 | * State variables for keeping track of RSSI of the AP currently | ||
442 | * connected to and informing driver when RSSI has gone | ||
443 | * below/above a certain threshold. | ||
444 | */ | ||
445 | int rssi_min_thold, rssi_max_thold; | ||
446 | int last_ave_beacon_signal; | ||
420 | }; | 447 | }; |
421 | 448 | ||
422 | struct ieee80211_if_ibss { | 449 | struct ieee80211_if_ibss { |
@@ -515,12 +542,14 @@ struct ieee80211_if_mesh { | |||
515 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between | 542 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between |
516 | * associated stations and deliver multicast frames both | 543 | * associated stations and deliver multicast frames both |
517 | * back to wireless media and to the local net stack. | 544 | * back to wireless media and to the local net stack. |
545 | * @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume. | ||
518 | */ | 546 | */ |
519 | enum ieee80211_sub_if_data_flags { | 547 | enum ieee80211_sub_if_data_flags { |
520 | IEEE80211_SDATA_ALLMULTI = BIT(0), | 548 | IEEE80211_SDATA_ALLMULTI = BIT(0), |
521 | IEEE80211_SDATA_PROMISC = BIT(1), | 549 | IEEE80211_SDATA_PROMISC = BIT(1), |
522 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), | 550 | IEEE80211_SDATA_OPERATING_GMODE = BIT(2), |
523 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), | 551 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), |
552 | IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4), | ||
524 | }; | 553 | }; |
525 | 554 | ||
526 | /** | 555 | /** |
@@ -544,6 +573,9 @@ struct ieee80211_sub_if_data { | |||
544 | /* keys */ | 573 | /* keys */ |
545 | struct list_head key_list; | 574 | struct list_head key_list; |
546 | 575 | ||
576 | /* count for keys needing tailroom space allocation */ | ||
577 | int crypto_tx_tailroom_needed_cnt; | ||
578 | |||
547 | struct net_device *dev; | 579 | struct net_device *dev; |
548 | struct ieee80211_local *local; | 580 | struct ieee80211_local *local; |
549 | 581 | ||
@@ -718,6 +750,7 @@ struct ieee80211_local { | |||
718 | struct workqueue_struct *workqueue; | 750 | struct workqueue_struct *workqueue; |
719 | 751 | ||
720 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; | 752 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; |
753 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; | ||
721 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ | 754 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ |
722 | spinlock_t queue_stop_reason_lock; | 755 | spinlock_t queue_stop_reason_lock; |
723 | 756 | ||
@@ -1348,12 +1381,14 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1348 | enum ieee80211_band band, u32 rate_mask, | 1381 | enum ieee80211_band band, u32 rate_mask, |
1349 | u8 channel); | 1382 | u8 channel); |
1350 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1383 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1351 | u8 *dst, | 1384 | u8 *dst, u32 ratemask, |
1352 | const u8 *ssid, size_t ssid_len, | 1385 | const u8 *ssid, size_t ssid_len, |
1353 | const u8 *ie, size_t ie_len); | 1386 | const u8 *ie, size_t ie_len, |
1387 | bool directed); | ||
1354 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1388 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1355 | const u8 *ssid, size_t ssid_len, | 1389 | const u8 *ssid, size_t ssid_len, |
1356 | const u8 *ie, size_t ie_len); | 1390 | const u8 *ie, size_t ie_len, |
1391 | u32 ratemask, bool directed); | ||
1357 | 1392 | ||
1358 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 1393 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
1359 | const size_t supp_rates_len, | 1394 | const size_t supp_rates_len, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index dee30aea9ab..556e7e6ddf0 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -363,8 +363,7 @@ static int ieee80211_open(struct net_device *dev) | |||
363 | int err; | 363 | int err; |
364 | 364 | ||
365 | /* fail early if user set an invalid address */ | 365 | /* fail early if user set an invalid address */ |
366 | if (!is_zero_ether_addr(dev->dev_addr) && | 366 | if (!is_valid_ether_addr(dev->dev_addr)) |
367 | !is_valid_ether_addr(dev->dev_addr)) | ||
368 | return -EADDRNOTAVAIL; | 367 | return -EADDRNOTAVAIL; |
369 | 368 | ||
370 | err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); | 369 | err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); |
@@ -699,6 +698,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = { | |||
699 | static void ieee80211_if_setup(struct net_device *dev) | 698 | static void ieee80211_if_setup(struct net_device *dev) |
700 | { | 699 | { |
701 | ether_setup(dev); | 700 | ether_setup(dev); |
701 | dev->priv_flags &= ~IFF_TX_SKB_SHARING; | ||
702 | dev->netdev_ops = &ieee80211_dataif_ops; | 702 | dev->netdev_ops = &ieee80211_dataif_ops; |
703 | dev->destructor = free_netdev; | 703 | dev->destructor = free_netdev; |
704 | } | 704 | } |
@@ -1130,8 +1130,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1130 | 1130 | ||
1131 | ASSERT_RTNL(); | 1131 | ASSERT_RTNL(); |
1132 | 1132 | ||
1133 | ndev = alloc_netdev_mq(sizeof(*sdata) + local->hw.vif_data_size, | 1133 | ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, |
1134 | name, ieee80211_if_setup, local->hw.queues); | 1134 | name, ieee80211_if_setup, local->hw.queues, 1); |
1135 | if (!ndev) | 1135 | if (!ndev) |
1136 | return -ENOMEM; | 1136 | return -ENOMEM; |
1137 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); | 1137 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index f825e2f0a57..5150c6d11b5 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -61,6 +61,36 @@ static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) | |||
61 | return NULL; | 61 | return NULL; |
62 | } | 62 | } |
63 | 63 | ||
64 | static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) | ||
65 | { | ||
66 | /* | ||
67 | * When this count is zero, SKB resizing for allocating tailroom | ||
68 | * for IV or MMIC is skipped. But, this check has created two race | ||
69 | * cases in xmit path while transiting from zero count to one: | ||
70 | * | ||
71 | * 1. SKB resize was skipped because no key was added but just before | ||
72 | * the xmit key is added and SW encryption kicks off. | ||
73 | * | ||
74 | * 2. SKB resize was skipped because all the keys were hw planted but | ||
75 | * just before xmit one of the key is deleted and SW encryption kicks | ||
76 | * off. | ||
77 | * | ||
78 | * In both the above case SW encryption will find not enough space for | ||
79 | * tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c) | ||
80 | * | ||
81 | * Solution has been explained at | ||
82 | * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net | ||
83 | */ | ||
84 | |||
85 | if (!sdata->crypto_tx_tailroom_needed_cnt++) { | ||
86 | /* | ||
87 | * Flush all XMIT packets currently using HW encryption or no | ||
88 | * encryption at all if the count transition is from 0 -> 1. | ||
89 | */ | ||
90 | synchronize_net(); | ||
91 | } | ||
92 | } | ||
93 | |||
64 | static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | 94 | static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) |
65 | { | 95 | { |
66 | struct ieee80211_sub_if_data *sdata; | 96 | struct ieee80211_sub_if_data *sdata; |
@@ -101,6 +131,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
101 | 131 | ||
102 | if (!ret) { | 132 | if (!ret) { |
103 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 133 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
134 | |||
135 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || | ||
136 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) | ||
137 | sdata->crypto_tx_tailroom_needed_cnt--; | ||
138 | |||
104 | return 0; | 139 | return 0; |
105 | } | 140 | } |
106 | 141 | ||
@@ -142,6 +177,10 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
142 | sta = get_sta_for_key(key); | 177 | sta = get_sta_for_key(key); |
143 | sdata = key->sdata; | 178 | sdata = key->sdata; |
144 | 179 | ||
180 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || | ||
181 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))) | ||
182 | increment_tailroom_need_count(sdata); | ||
183 | |||
145 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 184 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
146 | sdata = container_of(sdata->bss, | 185 | sdata = container_of(sdata->bss, |
147 | struct ieee80211_sub_if_data, | 186 | struct ieee80211_sub_if_data, |
@@ -239,7 +278,7 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
239 | bool defunikey, defmultikey, defmgmtkey; | 278 | bool defunikey, defmultikey, defmgmtkey; |
240 | 279 | ||
241 | if (new) | 280 | if (new) |
242 | list_add(&new->list, &sdata->key_list); | 281 | list_add_tail(&new->list, &sdata->key_list); |
243 | 282 | ||
244 | if (sta && pairwise) { | 283 | if (sta && pairwise) { |
245 | rcu_assign_pointer(sta->ptk, new); | 284 | rcu_assign_pointer(sta->ptk, new); |
@@ -330,6 +369,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
330 | get_unaligned_le16(seq); | 369 | get_unaligned_le16(seq); |
331 | } | 370 | } |
332 | } | 371 | } |
372 | spin_lock_init(&key->u.tkip.txlock); | ||
333 | break; | 373 | break; |
334 | case WLAN_CIPHER_SUITE_CCMP: | 374 | case WLAN_CIPHER_SUITE_CCMP: |
335 | key->conf.iv_len = CCMP_HDR_LEN; | 375 | key->conf.iv_len = CCMP_HDR_LEN; |
@@ -394,8 +434,10 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
394 | ieee80211_aes_key_free(key->u.ccmp.tfm); | 434 | ieee80211_aes_key_free(key->u.ccmp.tfm); |
395 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) | 435 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) |
396 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | 436 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); |
397 | if (key->local) | 437 | if (key->local) { |
398 | ieee80211_debugfs_key_remove(key); | 438 | ieee80211_debugfs_key_remove(key); |
439 | key->sdata->crypto_tx_tailroom_needed_cnt--; | ||
440 | } | ||
399 | 441 | ||
400 | kfree(key); | 442 | kfree(key); |
401 | } | 443 | } |
@@ -452,6 +494,8 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
452 | else | 494 | else |
453 | old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); | 495 | old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); |
454 | 496 | ||
497 | increment_tailroom_need_count(sdata); | ||
498 | |||
455 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); | 499 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); |
456 | __ieee80211_key_destroy(old_key); | 500 | __ieee80211_key_destroy(old_key); |
457 | 501 | ||
@@ -498,12 +542,49 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | |||
498 | 542 | ||
499 | mutex_lock(&sdata->local->key_mtx); | 543 | mutex_lock(&sdata->local->key_mtx); |
500 | 544 | ||
501 | list_for_each_entry(key, &sdata->key_list, list) | 545 | sdata->crypto_tx_tailroom_needed_cnt = 0; |
546 | |||
547 | list_for_each_entry(key, &sdata->key_list, list) { | ||
548 | increment_tailroom_need_count(sdata); | ||
502 | ieee80211_key_enable_hw_accel(key); | 549 | ieee80211_key_enable_hw_accel(key); |
550 | } | ||
503 | 551 | ||
504 | mutex_unlock(&sdata->local->key_mtx); | 552 | mutex_unlock(&sdata->local->key_mtx); |
505 | } | 553 | } |
506 | 554 | ||
555 | void ieee80211_iter_keys(struct ieee80211_hw *hw, | ||
556 | struct ieee80211_vif *vif, | ||
557 | void (*iter)(struct ieee80211_hw *hw, | ||
558 | struct ieee80211_vif *vif, | ||
559 | struct ieee80211_sta *sta, | ||
560 | struct ieee80211_key_conf *key, | ||
561 | void *data), | ||
562 | void *iter_data) | ||
563 | { | ||
564 | struct ieee80211_local *local = hw_to_local(hw); | ||
565 | struct ieee80211_key *key; | ||
566 | struct ieee80211_sub_if_data *sdata; | ||
567 | |||
568 | ASSERT_RTNL(); | ||
569 | |||
570 | mutex_lock(&local->key_mtx); | ||
571 | if (vif) { | ||
572 | sdata = vif_to_sdata(vif); | ||
573 | list_for_each_entry(key, &sdata->key_list, list) | ||
574 | iter(hw, &sdata->vif, | ||
575 | key->sta ? &key->sta->sta : NULL, | ||
576 | &key->conf, iter_data); | ||
577 | } else { | ||
578 | list_for_each_entry(sdata, &local->interfaces, list) | ||
579 | list_for_each_entry(key, &sdata->key_list, list) | ||
580 | iter(hw, &sdata->vif, | ||
581 | key->sta ? &key->sta->sta : NULL, | ||
582 | &key->conf, iter_data); | ||
583 | } | ||
584 | mutex_unlock(&local->key_mtx); | ||
585 | } | ||
586 | EXPORT_SYMBOL(ieee80211_iter_keys); | ||
587 | |||
507 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) | 588 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) |
508 | { | 589 | { |
509 | struct ieee80211_key *key; | 590 | struct ieee80211_key *key; |
@@ -533,3 +614,89 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | |||
533 | 614 | ||
534 | mutex_unlock(&sdata->local->key_mtx); | 615 | mutex_unlock(&sdata->local->key_mtx); |
535 | } | 616 | } |
617 | |||
618 | |||
619 | void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid, | ||
620 | const u8 *replay_ctr, gfp_t gfp) | ||
621 | { | ||
622 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
623 | |||
624 | trace_api_gtk_rekey_notify(sdata, bssid, replay_ctr); | ||
625 | |||
626 | cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp); | ||
627 | } | ||
628 | EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify); | ||
629 | |||
630 | void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf, | ||
631 | struct ieee80211_key_seq *seq) | ||
632 | { | ||
633 | struct ieee80211_key *key; | ||
634 | u64 pn64; | ||
635 | |||
636 | if (WARN_ON(!(keyconf->flags & IEEE80211_KEY_FLAG_GENERATE_IV))) | ||
637 | return; | ||
638 | |||
639 | key = container_of(keyconf, struct ieee80211_key, conf); | ||
640 | |||
641 | switch (key->conf.cipher) { | ||
642 | case WLAN_CIPHER_SUITE_TKIP: | ||
643 | seq->tkip.iv32 = key->u.tkip.tx.iv32; | ||
644 | seq->tkip.iv16 = key->u.tkip.tx.iv16; | ||
645 | break; | ||
646 | case WLAN_CIPHER_SUITE_CCMP: | ||
647 | pn64 = atomic64_read(&key->u.ccmp.tx_pn); | ||
648 | seq->ccmp.pn[5] = pn64; | ||
649 | seq->ccmp.pn[4] = pn64 >> 8; | ||
650 | seq->ccmp.pn[3] = pn64 >> 16; | ||
651 | seq->ccmp.pn[2] = pn64 >> 24; | ||
652 | seq->ccmp.pn[1] = pn64 >> 32; | ||
653 | seq->ccmp.pn[0] = pn64 >> 40; | ||
654 | break; | ||
655 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
656 | pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); | ||
657 | seq->ccmp.pn[5] = pn64; | ||
658 | seq->ccmp.pn[4] = pn64 >> 8; | ||
659 | seq->ccmp.pn[3] = pn64 >> 16; | ||
660 | seq->ccmp.pn[2] = pn64 >> 24; | ||
661 | seq->ccmp.pn[1] = pn64 >> 32; | ||
662 | seq->ccmp.pn[0] = pn64 >> 40; | ||
663 | break; | ||
664 | default: | ||
665 | WARN_ON(1); | ||
666 | } | ||
667 | } | ||
668 | EXPORT_SYMBOL(ieee80211_get_key_tx_seq); | ||
669 | |||
670 | void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf, | ||
671 | int tid, struct ieee80211_key_seq *seq) | ||
672 | { | ||
673 | struct ieee80211_key *key; | ||
674 | const u8 *pn; | ||
675 | |||
676 | key = container_of(keyconf, struct ieee80211_key, conf); | ||
677 | |||
678 | switch (key->conf.cipher) { | ||
679 | case WLAN_CIPHER_SUITE_TKIP: | ||
680 | if (WARN_ON(tid < 0 || tid >= NUM_RX_DATA_QUEUES)) | ||
681 | return; | ||
682 | seq->tkip.iv32 = key->u.tkip.rx[tid].iv32; | ||
683 | seq->tkip.iv16 = key->u.tkip.rx[tid].iv16; | ||
684 | break; | ||
685 | case WLAN_CIPHER_SUITE_CCMP: | ||
686 | if (WARN_ON(tid < -1 || tid >= NUM_RX_DATA_QUEUES)) | ||
687 | return; | ||
688 | if (tid < 0) | ||
689 | pn = key->u.ccmp.rx_pn[NUM_RX_DATA_QUEUES]; | ||
690 | else | ||
691 | pn = key->u.ccmp.rx_pn[tid]; | ||
692 | memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN); | ||
693 | break; | ||
694 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
695 | if (WARN_ON(tid != 0)) | ||
696 | return; | ||
697 | pn = key->u.aes_cmac.rx_pn; | ||
698 | memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN); | ||
699 | break; | ||
700 | } | ||
701 | } | ||
702 | EXPORT_SYMBOL(ieee80211_get_key_rx_seq); | ||
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index d801d535133..7d4e31f037d 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -28,8 +28,9 @@ | |||
28 | #define CCMP_PN_LEN 6 | 28 | #define CCMP_PN_LEN 6 |
29 | #define TKIP_IV_LEN 8 | 29 | #define TKIP_IV_LEN 8 |
30 | #define TKIP_ICV_LEN 4 | 30 | #define TKIP_ICV_LEN 4 |
31 | #define CMAC_PN_LEN 6 | ||
31 | 32 | ||
32 | #define NUM_RX_DATA_QUEUES 17 | 33 | #define NUM_RX_DATA_QUEUES 16 |
33 | 34 | ||
34 | struct ieee80211_local; | 35 | struct ieee80211_local; |
35 | struct ieee80211_sub_if_data; | 36 | struct ieee80211_sub_if_data; |
@@ -40,9 +41,11 @@ struct sta_info; | |||
40 | * | 41 | * |
41 | * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present | 42 | * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present |
42 | * in the hardware for TX crypto hardware acceleration. | 43 | * in the hardware for TX crypto hardware acceleration. |
44 | * @KEY_FLAG_TAINTED: Key is tainted and packets should be dropped. | ||
43 | */ | 45 | */ |
44 | enum ieee80211_internal_key_flags { | 46 | enum ieee80211_internal_key_flags { |
45 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), | 47 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), |
48 | KEY_FLAG_TAINTED = BIT(1), | ||
46 | }; | 49 | }; |
47 | 50 | ||
48 | enum ieee80211_internal_tkip_state { | 51 | enum ieee80211_internal_tkip_state { |
@@ -52,9 +55,10 @@ enum ieee80211_internal_tkip_state { | |||
52 | }; | 55 | }; |
53 | 56 | ||
54 | struct tkip_ctx { | 57 | struct tkip_ctx { |
55 | u32 iv32; | 58 | u32 iv32; /* current iv32 */ |
56 | u16 iv16; | 59 | u16 iv16; /* current iv16 */ |
57 | u16 p1k[5]; | 60 | u16 p1k[5]; /* p1k cache */ |
61 | u32 p1k_iv32; /* iv32 for which p1k computed */ | ||
58 | enum ieee80211_internal_tkip_state state; | 62 | enum ieee80211_internal_tkip_state state; |
59 | }; | 63 | }; |
60 | 64 | ||
@@ -71,6 +75,9 @@ struct ieee80211_key { | |||
71 | 75 | ||
72 | union { | 76 | union { |
73 | struct { | 77 | struct { |
78 | /* protects tx context */ | ||
79 | spinlock_t txlock; | ||
80 | |||
74 | /* last used TSC */ | 81 | /* last used TSC */ |
75 | struct tkip_ctx tx; | 82 | struct tkip_ctx tx; |
76 | 83 | ||
@@ -78,32 +85,23 @@ struct ieee80211_key { | |||
78 | struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; | 85 | struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; |
79 | } tkip; | 86 | } tkip; |
80 | struct { | 87 | struct { |
81 | u8 tx_pn[6]; | 88 | atomic64_t tx_pn; |
82 | /* | 89 | /* |
83 | * Last received packet number. The first | 90 | * Last received packet number. The first |
84 | * NUM_RX_DATA_QUEUES counters are used with Data | 91 | * NUM_RX_DATA_QUEUES counters are used with Data |
85 | * frames and the last counter is used with Robust | 92 | * frames and the last counter is used with Robust |
86 | * Management frames. | 93 | * Management frames. |
87 | */ | 94 | */ |
88 | u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6]; | 95 | u8 rx_pn[NUM_RX_DATA_QUEUES + 1][CCMP_PN_LEN]; |
89 | struct crypto_cipher *tfm; | 96 | struct crypto_cipher *tfm; |
90 | u32 replays; /* dot11RSNAStatsCCMPReplays */ | 97 | u32 replays; /* dot11RSNAStatsCCMPReplays */ |
91 | /* scratch buffers for virt_to_page() (crypto API) */ | ||
92 | #ifndef AES_BLOCK_LEN | ||
93 | #define AES_BLOCK_LEN 16 | ||
94 | #endif | ||
95 | u8 tx_crypto_buf[6 * AES_BLOCK_LEN]; | ||
96 | u8 rx_crypto_buf[6 * AES_BLOCK_LEN]; | ||
97 | } ccmp; | 98 | } ccmp; |
98 | struct { | 99 | struct { |
99 | u8 tx_pn[6]; | 100 | atomic64_t tx_pn; |
100 | u8 rx_pn[6]; | 101 | u8 rx_pn[CMAC_PN_LEN]; |
101 | struct crypto_cipher *tfm; | 102 | struct crypto_cipher *tfm; |
102 | u32 replays; /* dot11RSNAStatsCMACReplays */ | 103 | u32 replays; /* dot11RSNAStatsCMACReplays */ |
103 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ | 104 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ |
104 | /* scratch buffers for virt_to_page() (crypto API) */ | ||
105 | u8 tx_crypto_buf[2 * AES_BLOCK_LEN]; | ||
106 | u8 rx_crypto_buf[2 * AES_BLOCK_LEN]; | ||
107 | } aes_cmac; | 105 | } aes_cmac; |
108 | } u; | 106 | } u; |
109 | 107 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 866f269183c..3d90dadb5d5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -742,6 +742,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
742 | if (!local->int_scan_req) | 742 | if (!local->int_scan_req) |
743 | return -ENOMEM; | 743 | return -ENOMEM; |
744 | 744 | ||
745 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
746 | if (!local->hw.wiphy->bands[band]) | ||
747 | continue; | ||
748 | local->int_scan_req->rates[band] = (u32) -1; | ||
749 | } | ||
750 | |||
745 | /* if low-level driver supports AP, we also support VLAN */ | 751 | /* if low-level driver supports AP, we also support VLAN */ |
746 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { | 752 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { |
747 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | 753 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); |
@@ -1012,7 +1018,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1012 | cancel_work_sync(&local->reconfig_filter); | 1018 | cancel_work_sync(&local->reconfig_filter); |
1013 | 1019 | ||
1014 | ieee80211_clear_tx_pending(local); | 1020 | ieee80211_clear_tx_pending(local); |
1015 | sta_info_stop(local); | ||
1016 | rate_control_deinitialize(local); | 1021 | rate_control_deinitialize(local); |
1017 | 1022 | ||
1018 | if (skb_queue_len(&local->skb_queue) || | 1023 | if (skb_queue_len(&local->skb_queue) || |
@@ -1024,6 +1029,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1024 | 1029 | ||
1025 | destroy_workqueue(local->workqueue); | 1030 | destroy_workqueue(local->workqueue); |
1026 | wiphy_unregister(local->hw.wiphy); | 1031 | wiphy_unregister(local->hw.wiphy); |
1032 | sta_info_stop(local); | ||
1027 | ieee80211_wep_free(local); | 1033 | ieee80211_wep_free(local); |
1028 | ieee80211_led_exit(local); | 1034 | ieee80211_led_exit(local); |
1029 | kfree(local->int_scan_req); | 1035 | kfree(local->int_scan_req); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 2b18053070c..3460108810d 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -57,29 +57,29 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae) | |||
57 | #define PREQ_IE_TTL(x) (*(x + 2)) | 57 | #define PREQ_IE_TTL(x) (*(x + 2)) |
58 | #define PREQ_IE_PREQ_ID(x) u32_field_get(x, 3, 0) | 58 | #define PREQ_IE_PREQ_ID(x) u32_field_get(x, 3, 0) |
59 | #define PREQ_IE_ORIG_ADDR(x) (x + 7) | 59 | #define PREQ_IE_ORIG_ADDR(x) (x + 7) |
60 | #define PREQ_IE_ORIG_SN(x) u32_field_get(x, 13, 0); | 60 | #define PREQ_IE_ORIG_SN(x) u32_field_get(x, 13, 0) |
61 | #define PREQ_IE_LIFETIME(x) u32_field_get(x, 17, AE_F_SET(x)); | 61 | #define PREQ_IE_LIFETIME(x) u32_field_get(x, 17, AE_F_SET(x)) |
62 | #define PREQ_IE_METRIC(x) u32_field_get(x, 21, AE_F_SET(x)); | 62 | #define PREQ_IE_METRIC(x) u32_field_get(x, 21, AE_F_SET(x)) |
63 | #define PREQ_IE_TARGET_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26)) | 63 | #define PREQ_IE_TARGET_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26)) |
64 | #define PREQ_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27) | 64 | #define PREQ_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27) |
65 | #define PREQ_IE_TARGET_SN(x) u32_field_get(x, 33, AE_F_SET(x)); | 65 | #define PREQ_IE_TARGET_SN(x) u32_field_get(x, 33, AE_F_SET(x)) |
66 | 66 | ||
67 | 67 | ||
68 | #define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) | 68 | #define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) |
69 | #define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) | 69 | #define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) |
70 | #define PREP_IE_TTL(x) PREQ_IE_TTL(x) | 70 | #define PREP_IE_TTL(x) PREQ_IE_TTL(x) |
71 | #define PREP_IE_ORIG_ADDR(x) (x + 3) | 71 | #define PREP_IE_ORIG_ADDR(x) (x + 3) |
72 | #define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0); | 72 | #define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0) |
73 | #define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)); | 73 | #define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)) |
74 | #define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)); | 74 | #define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)) |
75 | #define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) | 75 | #define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) |
76 | #define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x)); | 76 | #define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x)) |
77 | 77 | ||
78 | #define PERR_IE_TTL(x) (*(x)) | 78 | #define PERR_IE_TTL(x) (*(x)) |
79 | #define PERR_IE_TARGET_FLAGS(x) (*(x + 2)) | 79 | #define PERR_IE_TARGET_FLAGS(x) (*(x + 2)) |
80 | #define PERR_IE_TARGET_ADDR(x) (x + 3) | 80 | #define PERR_IE_TARGET_ADDR(x) (x + 3) |
81 | #define PERR_IE_TARGET_SN(x) u32_field_get(x, 9, 0); | 81 | #define PERR_IE_TARGET_SN(x) u32_field_get(x, 9, 0) |
82 | #define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0); | 82 | #define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0) |
83 | 83 | ||
84 | #define MSEC_TO_TU(x) (x*1000/1024) | 84 | #define MSEC_TO_TU(x) (x*1000/1024) |
85 | #define SN_GT(x, y) ((long) (y) - (long) (x) < 0) | 85 | #define SN_GT(x, y) ((long) (y) - (long) (x) < 0) |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0d2faacc3e8..068ee651825 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -647,12 +647,12 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) | |||
647 | mpath = node->mpath; | 647 | mpath = node->mpath; |
648 | if (mpath->sdata == sdata && | 648 | if (mpath->sdata == sdata && |
649 | memcmp(addr, mpath->dst, ETH_ALEN) == 0) { | 649 | memcmp(addr, mpath->dst, ETH_ALEN) == 0) { |
650 | spin_lock_bh(&mpath->state_lock); | 650 | spin_lock(&mpath->state_lock); |
651 | mpath->flags |= MESH_PATH_RESOLVING; | 651 | mpath->flags |= MESH_PATH_RESOLVING; |
652 | hlist_del_rcu(&node->list); | 652 | hlist_del_rcu(&node->list); |
653 | call_rcu(&node->rcu, mesh_path_node_reclaim); | 653 | call_rcu(&node->rcu, mesh_path_node_reclaim); |
654 | atomic_dec(&tbl->entries); | 654 | atomic_dec(&tbl->entries); |
655 | spin_unlock_bh(&mpath->state_lock); | 655 | spin_unlock(&mpath->state_lock); |
656 | goto enddel; | 656 | goto enddel; |
657 | } | 657 | } |
658 | } | 658 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d595265d6c2..0f48368c2e2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -613,6 +613,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) | |||
613 | if (!mgd->powersave) | 613 | if (!mgd->powersave) |
614 | return false; | 614 | return false; |
615 | 615 | ||
616 | if (mgd->broken_ap) | ||
617 | return false; | ||
618 | |||
616 | if (!mgd->associated) | 619 | if (!mgd->associated) |
617 | return false; | 620 | return false; |
618 | 621 | ||
@@ -749,7 +752,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
749 | container_of(work, struct ieee80211_local, | 752 | container_of(work, struct ieee80211_local, |
750 | dynamic_ps_enable_work); | 753 | dynamic_ps_enable_work); |
751 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; | 754 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; |
752 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 755 | struct ieee80211_if_managed *ifmgd; |
753 | unsigned long flags; | 756 | unsigned long flags; |
754 | int q; | 757 | int q; |
755 | 758 | ||
@@ -757,26 +760,39 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
757 | if (!sdata) | 760 | if (!sdata) |
758 | return; | 761 | return; |
759 | 762 | ||
763 | ifmgd = &sdata->u.mgd; | ||
764 | |||
760 | if (local->hw.conf.flags & IEEE80211_CONF_PS) | 765 | if (local->hw.conf.flags & IEEE80211_CONF_PS) |
761 | return; | 766 | return; |
762 | 767 | ||
763 | /* | 768 | if (!local->disable_dynamic_ps && |
764 | * transmission can be stopped by others which leads to | 769 | local->hw.conf.dynamic_ps_timeout > 0) { |
765 | * dynamic_ps_timer expiry. Postpond the ps timer if it | 770 | /* don't enter PS if TX frames are pending */ |
766 | * is not the actual idle state. | 771 | if (drv_tx_frames_pending(local)) { |
767 | */ | ||
768 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
769 | for (q = 0; q < local->hw.queues; q++) { | ||
770 | if (local->queue_stop_reasons[q]) { | ||
771 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
772 | flags); | ||
773 | mod_timer(&local->dynamic_ps_timer, jiffies + | 772 | mod_timer(&local->dynamic_ps_timer, jiffies + |
774 | msecs_to_jiffies( | 773 | msecs_to_jiffies( |
775 | local->hw.conf.dynamic_ps_timeout)); | 774 | local->hw.conf.dynamic_ps_timeout)); |
776 | return; | 775 | return; |
777 | } | 776 | } |
777 | |||
778 | /* | ||
779 | * transmission can be stopped by others which leads to | ||
780 | * dynamic_ps_timer expiry. Postpone the ps timer if it | ||
781 | * is not the actual idle state. | ||
782 | */ | ||
783 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
784 | for (q = 0; q < local->hw.queues; q++) { | ||
785 | if (local->queue_stop_reasons[q]) { | ||
786 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
787 | flags); | ||
788 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
789 | msecs_to_jiffies( | ||
790 | local->hw.conf.dynamic_ps_timeout)); | ||
791 | return; | ||
792 | } | ||
793 | } | ||
794 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
778 | } | 795 | } |
779 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
780 | 796 | ||
781 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 797 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
782 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { | 798 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { |
@@ -801,7 +817,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
801 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 817 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
802 | } | 818 | } |
803 | 819 | ||
804 | netif_tx_wake_all_queues(sdata->dev); | 820 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) |
821 | netif_tx_wake_all_queues(sdata->dev); | ||
805 | } | 822 | } |
806 | 823 | ||
807 | void ieee80211_dynamic_ps_timer(unsigned long data) | 824 | void ieee80211_dynamic_ps_timer(unsigned long data) |
@@ -903,6 +920,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
903 | params.aifs, params.cw_min, params.cw_max, | 920 | params.aifs, params.cw_min, params.cw_max, |
904 | params.txop, params.uapsd); | 921 | params.txop, params.uapsd); |
905 | #endif | 922 | #endif |
923 | local->tx_conf[queue] = params; | ||
906 | if (drv_conf_tx(local, queue, ¶ms)) | 924 | if (drv_conf_tx(local, queue, ¶ms)) |
907 | wiphy_debug(local->hw.wiphy, | 925 | wiphy_debug(local->hw.wiphy, |
908 | "failed to set TX queue parameters for queue %d\n", | 926 | "failed to set TX queue parameters for queue %d\n", |
@@ -1204,7 +1222,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1204 | ieee80211_send_nullfunc(sdata->local, sdata, 0); | 1222 | ieee80211_send_nullfunc(sdata->local, sdata, 0); |
1205 | } else { | 1223 | } else { |
1206 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1224 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1207 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); | 1225 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, |
1226 | (u32) -1, true); | ||
1208 | } | 1227 | } |
1209 | 1228 | ||
1210 | ifmgd->probe_send_count++; | 1229 | ifmgd->probe_send_count++; |
@@ -1289,7 +1308,8 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1289 | 1308 | ||
1290 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1309 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1291 | skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, | 1310 | skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, |
1292 | ssid + 2, ssid[1], NULL, 0); | 1311 | (u32) -1, ssid + 2, ssid[1], |
1312 | NULL, 0, true); | ||
1293 | 1313 | ||
1294 | return skb; | 1314 | return skb; |
1295 | } | 1315 | } |
@@ -1450,10 +1470,21 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1450 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | 1470 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); |
1451 | 1471 | ||
1452 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1472 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
1453 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " | 1473 | printk(KERN_DEBUG |
1454 | "set\n", sdata->name, aid); | 1474 | "%s: invalid AID value 0x%x; bits 15:14 not set\n", |
1475 | sdata->name, aid); | ||
1455 | aid &= ~(BIT(15) | BIT(14)); | 1476 | aid &= ~(BIT(15) | BIT(14)); |
1456 | 1477 | ||
1478 | ifmgd->broken_ap = false; | ||
1479 | |||
1480 | if (aid == 0 || aid > IEEE80211_MAX_AID) { | ||
1481 | printk(KERN_DEBUG | ||
1482 | "%s: invalid AID value %d (out of range), turn off PS\n", | ||
1483 | sdata->name, aid); | ||
1484 | aid = 0; | ||
1485 | ifmgd->broken_ap = true; | ||
1486 | } | ||
1487 | |||
1457 | pos = mgmt->u.assoc_resp.variable; | 1488 | pos = mgmt->u.assoc_resp.variable; |
1458 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | 1489 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
1459 | 1490 | ||
@@ -1748,6 +1779,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1748 | ifmgd->ave_beacon_signal = rx_status->signal * 16; | 1779 | ifmgd->ave_beacon_signal = rx_status->signal * 16; |
1749 | ifmgd->last_cqm_event_signal = 0; | 1780 | ifmgd->last_cqm_event_signal = 0; |
1750 | ifmgd->count_beacon_signal = 1; | 1781 | ifmgd->count_beacon_signal = 1; |
1782 | ifmgd->last_ave_beacon_signal = 0; | ||
1751 | } else { | 1783 | } else { |
1752 | ifmgd->ave_beacon_signal = | 1784 | ifmgd->ave_beacon_signal = |
1753 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + | 1785 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + |
@@ -1755,6 +1787,28 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1755 | ifmgd->ave_beacon_signal) / 16; | 1787 | ifmgd->ave_beacon_signal) / 16; |
1756 | ifmgd->count_beacon_signal++; | 1788 | ifmgd->count_beacon_signal++; |
1757 | } | 1789 | } |
1790 | |||
1791 | if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold && | ||
1792 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) { | ||
1793 | int sig = ifmgd->ave_beacon_signal; | ||
1794 | int last_sig = ifmgd->last_ave_beacon_signal; | ||
1795 | |||
1796 | /* | ||
1797 | * if signal crosses either of the boundaries, invoke callback | ||
1798 | * with appropriate parameters | ||
1799 | */ | ||
1800 | if (sig > ifmgd->rssi_max_thold && | ||
1801 | (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) { | ||
1802 | ifmgd->last_ave_beacon_signal = sig; | ||
1803 | drv_rssi_callback(local, RSSI_EVENT_HIGH); | ||
1804 | } else if (sig < ifmgd->rssi_min_thold && | ||
1805 | (last_sig >= ifmgd->rssi_max_thold || | ||
1806 | last_sig == 0)) { | ||
1807 | ifmgd->last_ave_beacon_signal = sig; | ||
1808 | drv_rssi_callback(local, RSSI_EVENT_LOW); | ||
1809 | } | ||
1810 | } | ||
1811 | |||
1758 | if (bss_conf->cqm_rssi_thold && | 1812 | if (bss_conf->cqm_rssi_thold && |
1759 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && | 1813 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && |
1760 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | 1814 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { |
@@ -2014,7 +2068,7 @@ static void ieee80211_sta_timer(unsigned long data) | |||
2014 | } | 2068 | } |
2015 | 2069 | ||
2016 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | 2070 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, |
2017 | u8 *bssid) | 2071 | u8 *bssid, u8 reason) |
2018 | { | 2072 | { |
2019 | struct ieee80211_local *local = sdata->local; | 2073 | struct ieee80211_local *local = sdata->local; |
2020 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2074 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -2032,8 +2086,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2032 | * but that's not a problem. | 2086 | * but that's not a problem. |
2033 | */ | 2087 | */ |
2034 | ieee80211_send_deauth_disassoc(sdata, bssid, | 2088 | ieee80211_send_deauth_disassoc(sdata, bssid, |
2035 | IEEE80211_STYPE_DEAUTH, | 2089 | IEEE80211_STYPE_DEAUTH, reason, |
2036 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
2037 | NULL, true); | 2090 | NULL, true); |
2038 | mutex_lock(&ifmgd->mtx); | 2091 | mutex_lock(&ifmgd->mtx); |
2039 | } | 2092 | } |
@@ -2079,7 +2132,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2079 | " AP %pM, disconnecting.\n", | 2132 | " AP %pM, disconnecting.\n", |
2080 | sdata->name, bssid); | 2133 | sdata->name, bssid); |
2081 | #endif | 2134 | #endif |
2082 | ieee80211_sta_connection_lost(sdata, bssid); | 2135 | ieee80211_sta_connection_lost(sdata, bssid, |
2136 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); | ||
2083 | } | 2137 | } |
2084 | } else if (time_is_after_jiffies(ifmgd->probe_timeout)) | 2138 | } else if (time_is_after_jiffies(ifmgd->probe_timeout)) |
2085 | run_again(ifmgd, ifmgd->probe_timeout); | 2139 | run_again(ifmgd, ifmgd->probe_timeout); |
@@ -2091,7 +2145,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2091 | sdata->name, | 2145 | sdata->name, |
2092 | bssid, probe_wait_ms); | 2146 | bssid, probe_wait_ms); |
2093 | #endif | 2147 | #endif |
2094 | ieee80211_sta_connection_lost(sdata, bssid); | 2148 | ieee80211_sta_connection_lost(sdata, bssid, |
2149 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); | ||
2095 | } else if (ifmgd->probe_send_count < max_tries) { | 2150 | } else if (ifmgd->probe_send_count < max_tries) { |
2096 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2151 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
2097 | wiphy_debug(local->hw.wiphy, | 2152 | wiphy_debug(local->hw.wiphy, |
@@ -2113,7 +2168,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2113 | sdata->name, | 2168 | sdata->name, |
2114 | bssid, probe_wait_ms); | 2169 | bssid, probe_wait_ms); |
2115 | 2170 | ||
2116 | ieee80211_sta_connection_lost(sdata, bssid); | 2171 | ieee80211_sta_connection_lost(sdata, bssid, |
2172 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); | ||
2117 | } | 2173 | } |
2118 | } | 2174 | } |
2119 | 2175 | ||
@@ -2200,12 +2256,34 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | |||
2200 | { | 2256 | { |
2201 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2257 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2202 | 2258 | ||
2259 | if (!ifmgd->associated) | ||
2260 | return; | ||
2261 | |||
2262 | if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { | ||
2263 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; | ||
2264 | mutex_lock(&ifmgd->mtx); | ||
2265 | if (ifmgd->associated) { | ||
2266 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
2267 | wiphy_debug(sdata->local->hw.wiphy, | ||
2268 | "%s: driver requested disconnect after resume.\n", | ||
2269 | sdata->name); | ||
2270 | #endif | ||
2271 | ieee80211_sta_connection_lost(sdata, | ||
2272 | ifmgd->associated->bssid, | ||
2273 | WLAN_REASON_UNSPECIFIED); | ||
2274 | mutex_unlock(&ifmgd->mtx); | ||
2275 | return; | ||
2276 | } | ||
2277 | mutex_unlock(&ifmgd->mtx); | ||
2278 | } | ||
2279 | |||
2203 | if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) | 2280 | if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) |
2204 | add_timer(&ifmgd->timer); | 2281 | add_timer(&ifmgd->timer); |
2205 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) | 2282 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) |
2206 | add_timer(&ifmgd->chswitch_timer); | 2283 | add_timer(&ifmgd->chswitch_timer); |
2207 | ieee80211_sta_reset_beacon_monitor(sdata); | 2284 | ieee80211_sta_reset_beacon_monitor(sdata); |
2208 | ieee80211_restart_sta_timer(sdata); | 2285 | ieee80211_restart_sta_timer(sdata); |
2286 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.monitor_work); | ||
2209 | } | 2287 | } |
2210 | #endif | 2288 | #endif |
2211 | 2289 | ||
@@ -2271,14 +2349,16 @@ static enum work_done_result | |||
2271 | ieee80211_probe_auth_done(struct ieee80211_work *wk, | 2349 | ieee80211_probe_auth_done(struct ieee80211_work *wk, |
2272 | struct sk_buff *skb) | 2350 | struct sk_buff *skb) |
2273 | { | 2351 | { |
2352 | struct ieee80211_local *local = wk->sdata->local; | ||
2353 | |||
2274 | if (!skb) { | 2354 | if (!skb) { |
2275 | cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); | 2355 | cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); |
2276 | return WORK_DONE_DESTROY; | 2356 | goto destroy; |
2277 | } | 2357 | } |
2278 | 2358 | ||
2279 | if (wk->type == IEEE80211_WORK_AUTH) { | 2359 | if (wk->type == IEEE80211_WORK_AUTH) { |
2280 | cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); | 2360 | cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); |
2281 | return WORK_DONE_DESTROY; | 2361 | goto destroy; |
2282 | } | 2362 | } |
2283 | 2363 | ||
2284 | mutex_lock(&wk->sdata->u.mgd.mtx); | 2364 | mutex_lock(&wk->sdata->u.mgd.mtx); |
@@ -2288,6 +2368,12 @@ ieee80211_probe_auth_done(struct ieee80211_work *wk, | |||
2288 | wk->type = IEEE80211_WORK_AUTH; | 2368 | wk->type = IEEE80211_WORK_AUTH; |
2289 | wk->probe_auth.tries = 0; | 2369 | wk->probe_auth.tries = 0; |
2290 | return WORK_DONE_REQUEUE; | 2370 | return WORK_DONE_REQUEUE; |
2371 | destroy: | ||
2372 | if (wk->probe_auth.synced) | ||
2373 | drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, | ||
2374 | IEEE80211_TX_SYNC_AUTH); | ||
2375 | |||
2376 | return WORK_DONE_DESTROY; | ||
2291 | } | 2377 | } |
2292 | 2378 | ||
2293 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 2379 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
@@ -2360,6 +2446,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2360 | static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, | 2446 | static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, |
2361 | struct sk_buff *skb) | 2447 | struct sk_buff *skb) |
2362 | { | 2448 | { |
2449 | struct ieee80211_local *local = wk->sdata->local; | ||
2363 | struct ieee80211_mgmt *mgmt; | 2450 | struct ieee80211_mgmt *mgmt; |
2364 | struct ieee80211_rx_status *rx_status; | 2451 | struct ieee80211_rx_status *rx_status; |
2365 | struct ieee802_11_elems elems; | 2452 | struct ieee802_11_elems elems; |
@@ -2367,7 +2454,7 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, | |||
2367 | 2454 | ||
2368 | if (!skb) { | 2455 | if (!skb) { |
2369 | cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); | 2456 | cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); |
2370 | return WORK_DONE_DESTROY; | 2457 | goto destroy; |
2371 | } | 2458 | } |
2372 | 2459 | ||
2373 | if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) { | 2460 | if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) { |
@@ -2387,6 +2474,10 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, | |||
2387 | status = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 2474 | status = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
2388 | 2475 | ||
2389 | if (status == WLAN_STATUS_SUCCESS) { | 2476 | if (status == WLAN_STATUS_SUCCESS) { |
2477 | if (wk->assoc.synced) | ||
2478 | drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, | ||
2479 | IEEE80211_TX_SYNC_ASSOC); | ||
2480 | |||
2390 | mutex_lock(&wk->sdata->u.mgd.mtx); | 2481 | mutex_lock(&wk->sdata->u.mgd.mtx); |
2391 | if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { | 2482 | if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { |
2392 | mutex_unlock(&wk->sdata->u.mgd.mtx); | 2483 | mutex_unlock(&wk->sdata->u.mgd.mtx); |
@@ -2400,6 +2491,11 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, | |||
2400 | } | 2491 | } |
2401 | 2492 | ||
2402 | cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); | 2493 | cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); |
2494 | destroy: | ||
2495 | if (wk->assoc.synced) | ||
2496 | drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, | ||
2497 | IEEE80211_TX_SYNC_ASSOC); | ||
2498 | |||
2403 | return WORK_DONE_DESTROY; | 2499 | return WORK_DONE_DESTROY; |
2404 | } | 2500 | } |
2405 | 2501 | ||
@@ -2652,3 +2748,10 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | |||
2652 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | 2748 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); |
2653 | } | 2749 | } |
2654 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | 2750 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); |
2751 | |||
2752 | unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif) | ||
2753 | { | ||
2754 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
2755 | return sdata->dev->operstate; | ||
2756 | } | ||
2757 | EXPORT_SYMBOL(ieee80211_get_operstate); | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 730778a2c90..6326d343986 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -6,12 +6,37 @@ | |||
6 | #include "driver-ops.h" | 6 | #include "driver-ops.h" |
7 | #include "led.h" | 7 | #include "led.h" |
8 | 8 | ||
9 | /* return value indicates whether the driver should be further notified */ | ||
10 | static bool ieee80211_quiesce(struct ieee80211_sub_if_data *sdata) | ||
11 | { | ||
12 | switch (sdata->vif.type) { | ||
13 | case NL80211_IFTYPE_STATION: | ||
14 | ieee80211_sta_quiesce(sdata); | ||
15 | return true; | ||
16 | case NL80211_IFTYPE_ADHOC: | ||
17 | ieee80211_ibss_quiesce(sdata); | ||
18 | return true; | ||
19 | case NL80211_IFTYPE_MESH_POINT: | ||
20 | ieee80211_mesh_quiesce(sdata); | ||
21 | return true; | ||
22 | case NL80211_IFTYPE_AP_VLAN: | ||
23 | case NL80211_IFTYPE_MONITOR: | ||
24 | /* don't tell driver about this */ | ||
25 | return false; | ||
26 | default: | ||
27 | return true; | ||
28 | } | ||
29 | } | ||
30 | |||
9 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | 31 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) |
10 | { | 32 | { |
11 | struct ieee80211_local *local = hw_to_local(hw); | 33 | struct ieee80211_local *local = hw_to_local(hw); |
12 | struct ieee80211_sub_if_data *sdata; | 34 | struct ieee80211_sub_if_data *sdata; |
13 | struct sta_info *sta; | 35 | struct sta_info *sta; |
14 | 36 | ||
37 | if (!local->open_count) | ||
38 | goto suspend; | ||
39 | |||
15 | ieee80211_scan_cancel(local); | 40 | ieee80211_scan_cancel(local); |
16 | 41 | ||
17 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 42 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
@@ -50,11 +75,19 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
50 | local->wowlan = wowlan && local->open_count; | 75 | local->wowlan = wowlan && local->open_count; |
51 | if (local->wowlan) { | 76 | if (local->wowlan) { |
52 | int err = drv_suspend(local, wowlan); | 77 | int err = drv_suspend(local, wowlan); |
53 | if (err) { | 78 | if (err < 0) { |
54 | local->quiescing = false; | 79 | local->quiescing = false; |
55 | return err; | 80 | return err; |
81 | } else if (err > 0) { | ||
82 | WARN_ON(err != 1); | ||
83 | local->wowlan = false; | ||
84 | } else { | ||
85 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
86 | cancel_work_sync(&sdata->work); | ||
87 | ieee80211_quiesce(sdata); | ||
88 | } | ||
89 | goto suspend; | ||
56 | } | 90 | } |
57 | goto suspend; | ||
58 | } | 91 | } |
59 | 92 | ||
60 | /* disable keys */ | 93 | /* disable keys */ |
@@ -82,23 +115,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
82 | list_for_each_entry(sdata, &local->interfaces, list) { | 115 | list_for_each_entry(sdata, &local->interfaces, list) { |
83 | cancel_work_sync(&sdata->work); | 116 | cancel_work_sync(&sdata->work); |
84 | 117 | ||
85 | switch(sdata->vif.type) { | 118 | if (!ieee80211_quiesce(sdata)) |
86 | case NL80211_IFTYPE_STATION: | ||
87 | ieee80211_sta_quiesce(sdata); | ||
88 | break; | ||
89 | case NL80211_IFTYPE_ADHOC: | ||
90 | ieee80211_ibss_quiesce(sdata); | ||
91 | break; | ||
92 | case NL80211_IFTYPE_MESH_POINT: | ||
93 | ieee80211_mesh_quiesce(sdata); | ||
94 | break; | ||
95 | case NL80211_IFTYPE_AP_VLAN: | ||
96 | case NL80211_IFTYPE_MONITOR: | ||
97 | /* don't tell driver about this */ | ||
98 | continue; | 119 | continue; |
99 | default: | ||
100 | break; | ||
101 | } | ||
102 | 120 | ||
103 | if (!ieee80211_sdata_running(sdata)) | 121 | if (!ieee80211_sdata_running(sdata)) |
104 | continue; | 122 | continue; |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 8adac67395f..58a89554b78 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -532,12 +532,21 @@ minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | |||
532 | mp->hw = hw; | 532 | mp->hw = hw; |
533 | mp->update_interval = 100; | 533 | mp->update_interval = 100; |
534 | 534 | ||
535 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
536 | mp->fixed_rate_idx = (u32) -1; | ||
537 | mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx", | ||
538 | S_IRUGO | S_IWUGO, debugfsdir, &mp->fixed_rate_idx); | ||
539 | #endif | ||
540 | |||
535 | return mp; | 541 | return mp; |
536 | } | 542 | } |
537 | 543 | ||
538 | static void | 544 | static void |
539 | minstrel_free(void *priv) | 545 | minstrel_free(void *priv) |
540 | { | 546 | { |
547 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
548 | debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate); | ||
549 | #endif | ||
541 | kfree(priv); | 550 | kfree(priv); |
542 | } | 551 | } |
543 | 552 | ||
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 0f5a83370aa..5d278eccaef 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -78,6 +78,18 @@ struct minstrel_priv { | |||
78 | unsigned int update_interval; | 78 | unsigned int update_interval; |
79 | unsigned int lookaround_rate; | 79 | unsigned int lookaround_rate; |
80 | unsigned int lookaround_rate_mrr; | 80 | unsigned int lookaround_rate_mrr; |
81 | |||
82 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
83 | /* | ||
84 | * enable fixed rate processing per RC | ||
85 | * - write static index to debugfs:ieee80211/phyX/rc/fixed_rate_idx | ||
86 | * - write -1 to enable RC processing again | ||
87 | * - setting will be applied on next update | ||
88 | */ | ||
89 | u32 fixed_rate_idx; | ||
90 | struct dentry *dbg_fixed_rate; | ||
91 | #endif | ||
92 | |||
81 | }; | 93 | }; |
82 | 94 | ||
83 | struct minstrel_debugfs_info { | 95 | struct minstrel_debugfs_info { |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 333b5118be6..66a1eeb279c 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -609,6 +609,13 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
609 | 609 | ||
610 | info->flags |= mi->tx_flags; | 610 | info->flags |= mi->tx_flags; |
611 | sample_idx = minstrel_get_sample_rate(mp, mi); | 611 | sample_idx = minstrel_get_sample_rate(mp, mi); |
612 | |||
613 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
614 | /* use fixed index if set */ | ||
615 | if (mp->fixed_rate_idx != -1) | ||
616 | sample_idx = mp->fixed_rate_idx; | ||
617 | #endif | ||
618 | |||
612 | if (sample_idx >= 0) { | 619 | if (sample_idx >= 0) { |
613 | sample = true; | 620 | sample = true; |
614 | minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, | 621 | minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7fa8c6be7bf..a961003ffa2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -140,8 +140,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
140 | pos++; | 140 | pos++; |
141 | 141 | ||
142 | /* IEEE80211_RADIOTAP_RATE */ | 142 | /* IEEE80211_RADIOTAP_RATE */ |
143 | if (status->flag & RX_FLAG_HT) { | 143 | if (!rate || status->flag & RX_FLAG_HT) { |
144 | /* | 144 | /* |
145 | * Without rate information don't add it. If we have, | ||
145 | * MCS information is a separate field in radiotap, | 146 | * MCS information is a separate field in radiotap, |
146 | * added below. The byte here is needed as padding | 147 | * added below. The byte here is needed as padding |
147 | * for the channel though, so initialise it to 0. | 148 | * for the channel though, so initialise it to 0. |
@@ -162,12 +163,14 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
162 | else if (status->flag & RX_FLAG_HT) | 163 | else if (status->flag & RX_FLAG_HT) |
163 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, | 164 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, |
164 | pos); | 165 | pos); |
165 | else if (rate->flags & IEEE80211_RATE_ERP_G) | 166 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
166 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, | 167 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, |
167 | pos); | 168 | pos); |
168 | else | 169 | else if (rate) |
169 | put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, | 170 | put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, |
170 | pos); | 171 | pos); |
172 | else | ||
173 | put_unaligned_le16(IEEE80211_CHAN_2GHZ, pos); | ||
171 | pos += 2; | 174 | pos += 2; |
172 | 175 | ||
173 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ | 176 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ |
@@ -331,15 +334,18 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
331 | { | 334 | { |
332 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 335 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
333 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | 336 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); |
334 | int tid; | 337 | int tid, seqno_idx, security_idx; |
335 | 338 | ||
336 | /* does the frame have a qos control field? */ | 339 | /* does the frame have a qos control field? */ |
337 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 340 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
338 | u8 *qc = ieee80211_get_qos_ctl(hdr); | 341 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
339 | /* frame has qos control */ | 342 | /* frame has qos control */ |
340 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 343 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
341 | if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | 344 | if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) |
342 | status->rx_flags |= IEEE80211_RX_AMSDU; | 345 | status->rx_flags |= IEEE80211_RX_AMSDU; |
346 | |||
347 | seqno_idx = tid; | ||
348 | security_idx = tid; | ||
343 | } else { | 349 | } else { |
344 | /* | 350 | /* |
345 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): | 351 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): |
@@ -352,10 +358,15 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
352 | * | 358 | * |
353 | * We also use that counter for non-QoS STAs. | 359 | * We also use that counter for non-QoS STAs. |
354 | */ | 360 | */ |
355 | tid = NUM_RX_DATA_QUEUES - 1; | 361 | seqno_idx = NUM_RX_DATA_QUEUES; |
362 | security_idx = 0; | ||
363 | if (ieee80211_is_mgmt(hdr->frame_control)) | ||
364 | security_idx = NUM_RX_DATA_QUEUES; | ||
365 | tid = 0; | ||
356 | } | 366 | } |
357 | 367 | ||
358 | rx->queue = tid; | 368 | rx->seqno_idx = seqno_idx; |
369 | rx->security_idx = security_idx; | ||
359 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. | 370 | /* Set skb->priority to 1d tag if highest order bit of TID is not set. |
360 | * For now, set skb->priority to 0 for other cases. */ | 371 | * For now, set skb->priority to 0 for other cases. */ |
361 | rx->skb->priority = (tid > 7) ? 0 : tid; | 372 | rx->skb->priority = (tid > 7) ? 0 : tid; |
@@ -810,7 +821,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
810 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ | 821 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ |
811 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { | 822 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { |
812 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && | 823 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && |
813 | rx->sta->last_seq_ctrl[rx->queue] == | 824 | rx->sta->last_seq_ctrl[rx->seqno_idx] == |
814 | hdr->seq_ctrl)) { | 825 | hdr->seq_ctrl)) { |
815 | if (status->rx_flags & IEEE80211_RX_RA_MATCH) { | 826 | if (status->rx_flags & IEEE80211_RX_RA_MATCH) { |
816 | rx->local->dot11FrameDuplicateCount++; | 827 | rx->local->dot11FrameDuplicateCount++; |
@@ -818,7 +829,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
818 | } | 829 | } |
819 | return RX_DROP_UNUSABLE; | 830 | return RX_DROP_UNUSABLE; |
820 | } else | 831 | } else |
821 | rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl; | 832 | rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; |
822 | } | 833 | } |
823 | 834 | ||
824 | if (unlikely(rx->skb->len < 16)) { | 835 | if (unlikely(rx->skb->len < 16)) { |
@@ -1011,6 +1022,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1011 | } | 1022 | } |
1012 | 1023 | ||
1013 | if (rx->key) { | 1024 | if (rx->key) { |
1025 | if (unlikely(rx->key->flags & KEY_FLAG_TAINTED)) | ||
1026 | return RX_DROP_MONITOR; | ||
1027 | |||
1014 | rx->key->tx_rx_count++; | 1028 | rx->key->tx_rx_count++; |
1015 | /* TODO: add threshold stuff again */ | 1029 | /* TODO: add threshold stuff again */ |
1016 | } else { | 1030 | } else { |
@@ -1374,11 +1388,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1374 | if (frag == 0) { | 1388 | if (frag == 0) { |
1375 | /* This is the first fragment of a new frame. */ | 1389 | /* This is the first fragment of a new frame. */ |
1376 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 1390 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
1377 | rx->queue, &(rx->skb)); | 1391 | rx->seqno_idx, &(rx->skb)); |
1378 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && | 1392 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && |
1379 | ieee80211_has_protected(fc)) { | 1393 | ieee80211_has_protected(fc)) { |
1380 | int queue = ieee80211_is_mgmt(fc) ? | 1394 | int queue = rx->security_idx; |
1381 | NUM_RX_DATA_QUEUES : rx->queue; | ||
1382 | /* Store CCMP PN so that we can verify that the next | 1395 | /* Store CCMP PN so that we can verify that the next |
1383 | * fragment has a sequential PN value. */ | 1396 | * fragment has a sequential PN value. */ |
1384 | entry->ccmp = 1; | 1397 | entry->ccmp = 1; |
@@ -1392,7 +1405,8 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1392 | /* This is a fragment for a frame that should already be pending in | 1405 | /* This is a fragment for a frame that should already be pending in |
1393 | * fragment cache. Add this fragment to the end of the pending entry. | 1406 | * fragment cache. Add this fragment to the end of the pending entry. |
1394 | */ | 1407 | */ |
1395 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr); | 1408 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, |
1409 | rx->seqno_idx, hdr); | ||
1396 | if (!entry) { | 1410 | if (!entry) { |
1397 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); | 1411 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); |
1398 | return RX_DROP_MONITOR; | 1412 | return RX_DROP_MONITOR; |
@@ -1412,8 +1426,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1412 | if (pn[i]) | 1426 | if (pn[i]) |
1413 | break; | 1427 | break; |
1414 | } | 1428 | } |
1415 | queue = ieee80211_is_mgmt(fc) ? | 1429 | queue = rx->security_idx; |
1416 | NUM_RX_DATA_QUEUES : rx->queue; | ||
1417 | rpn = rx->key->u.ccmp.rx_pn[queue]; | 1430 | rpn = rx->key->u.ccmp.rx_pn[queue]; |
1418 | if (memcmp(pn, rpn, CCMP_PN_LEN)) | 1431 | if (memcmp(pn, rpn, CCMP_PN_LEN)) |
1419 | return RX_DROP_UNUSABLE; | 1432 | return RX_DROP_UNUSABLE; |
@@ -2590,7 +2603,9 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
2590 | .sta = sta, | 2603 | .sta = sta, |
2591 | .sdata = sta->sdata, | 2604 | .sdata = sta->sdata, |
2592 | .local = sta->local, | 2605 | .local = sta->local, |
2593 | .queue = tid, | 2606 | /* This is OK -- must be QoS data frame */ |
2607 | .security_idx = tid, | ||
2608 | .seqno_idx = tid, | ||
2594 | .flags = 0, | 2609 | .flags = 0, |
2595 | }; | 2610 | }; |
2596 | struct tid_ampdu_rx *tid_agg_rx; | 2611 | struct tid_ampdu_rx *tid_agg_rx; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 669d2e32efb..6f09eca0111 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -251,8 +251,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
251 | local->hw_scan_req->n_channels = n_chans; | 251 | local->hw_scan_req->n_channels = n_chans; |
252 | 252 | ||
253 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, | 253 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, |
254 | req->ie, req->ie_len, band, (u32) -1, | 254 | req->ie, req->ie_len, band, |
255 | 0); | 255 | req->rates[band], 0); |
256 | local->hw_scan_req->ie_len = ielen; | 256 | local->hw_scan_req->ie_len = ielen; |
257 | 257 | ||
258 | return true; | 258 | return true; |
@@ -652,13 +652,15 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
652 | { | 652 | { |
653 | int i; | 653 | int i; |
654 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 654 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
655 | enum ieee80211_band band = local->hw.conf.channel->band; | ||
655 | 656 | ||
656 | for (i = 0; i < local->scan_req->n_ssids; i++) | 657 | for (i = 0; i < local->scan_req->n_ssids; i++) |
657 | ieee80211_send_probe_req( | 658 | ieee80211_send_probe_req( |
658 | sdata, NULL, | 659 | sdata, NULL, |
659 | local->scan_req->ssids[i].ssid, | 660 | local->scan_req->ssids[i].ssid, |
660 | local->scan_req->ssids[i].ssid_len, | 661 | local->scan_req->ssids[i].ssid_len, |
661 | local->scan_req->ie, local->scan_req->ie_len); | 662 | local->scan_req->ie, local->scan_req->ie_len, |
663 | local->scan_req->rates[band], false); | ||
662 | 664 | ||
663 | /* | 665 | /* |
664 | * After sending probe requests, wait for probe responses | 666 | * After sending probe requests, wait for probe responses |
@@ -821,10 +823,8 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
821 | */ | 823 | */ |
822 | void ieee80211_scan_cancel(struct ieee80211_local *local) | 824 | void ieee80211_scan_cancel(struct ieee80211_local *local) |
823 | { | 825 | { |
824 | bool abortscan; | ||
825 | |||
826 | /* | 826 | /* |
827 | * We are only canceling software scan, or deferred scan that was not | 827 | * We are canceling software scan, or deferred scan that was not |
828 | * yet really started (see __ieee80211_start_scan ). | 828 | * yet really started (see __ieee80211_start_scan ). |
829 | * | 829 | * |
830 | * Regarding hardware scan: | 830 | * Regarding hardware scan: |
@@ -836,23 +836,30 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
836 | * - we can not cancel scan_work since driver can schedule it | 836 | * - we can not cancel scan_work since driver can schedule it |
837 | * by ieee80211_scan_completed(..., true) to finish scan | 837 | * by ieee80211_scan_completed(..., true) to finish scan |
838 | * | 838 | * |
839 | * Hence low lever driver is responsible for canceling HW scan. | 839 | * Hence we only call the cancel_hw_scan() callback, but the low-level |
840 | * driver is still responsible for calling ieee80211_scan_completed() | ||
841 | * after the scan was completed/aborted. | ||
840 | */ | 842 | */ |
841 | 843 | ||
842 | mutex_lock(&local->mtx); | 844 | mutex_lock(&local->mtx); |
843 | abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning); | 845 | if (!local->scan_req) |
844 | if (abortscan) { | 846 | goto out; |
845 | /* | 847 | |
846 | * The scan is canceled, but stop work from being pending. | 848 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { |
847 | * | 849 | if (local->ops->cancel_hw_scan) |
848 | * If the work is currently running, it must be blocked on | 850 | drv_cancel_hw_scan(local, local->scan_sdata); |
849 | * the mutex, but we'll set scan_sdata = NULL and it'll | 851 | goto out; |
850 | * simply exit once it acquires the mutex. | ||
851 | */ | ||
852 | cancel_delayed_work(&local->scan_work); | ||
853 | /* and clean up */ | ||
854 | __ieee80211_scan_completed(&local->hw, true, false); | ||
855 | } | 852 | } |
853 | |||
854 | /* | ||
855 | * If the work is currently running, it must be blocked on | ||
856 | * the mutex, but we'll set scan_sdata = NULL and it'll | ||
857 | * simply exit once it acquires the mutex. | ||
858 | */ | ||
859 | cancel_delayed_work(&local->scan_work); | ||
860 | /* and clean up */ | ||
861 | __ieee80211_scan_completed(&local->hw, true, false); | ||
862 | out: | ||
856 | mutex_unlock(&local->mtx); | 863 | mutex_unlock(&local->mtx); |
857 | } | 864 | } |
858 | 865 | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index b83870bf60f..57cf5287384 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -97,7 +97,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
97 | struct sta_info *sta; | 97 | struct sta_info *sta; |
98 | 98 | ||
99 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 99 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
100 | rcu_read_lock_held() || | ||
101 | lockdep_is_held(&local->sta_lock) || | 100 | lockdep_is_held(&local->sta_lock) || |
102 | lockdep_is_held(&local->sta_mtx)); | 101 | lockdep_is_held(&local->sta_mtx)); |
103 | while (sta) { | 102 | while (sta) { |
@@ -105,7 +104,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
105 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
106 | break; | 105 | break; |
107 | sta = rcu_dereference_check(sta->hnext, | 106 | sta = rcu_dereference_check(sta->hnext, |
108 | rcu_read_lock_held() || | ||
109 | lockdep_is_held(&local->sta_lock) || | 107 | lockdep_is_held(&local->sta_lock) || |
110 | lockdep_is_held(&local->sta_mtx)); | 108 | lockdep_is_held(&local->sta_mtx)); |
111 | } | 109 | } |
@@ -123,7 +121,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
123 | struct sta_info *sta; | 121 | struct sta_info *sta; |
124 | 122 | ||
125 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 123 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
126 | rcu_read_lock_held() || | ||
127 | lockdep_is_held(&local->sta_lock) || | 124 | lockdep_is_held(&local->sta_lock) || |
128 | lockdep_is_held(&local->sta_mtx)); | 125 | lockdep_is_held(&local->sta_mtx)); |
129 | while (sta) { | 126 | while (sta) { |
@@ -132,7 +129,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
132 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
133 | break; | 130 | break; |
134 | sta = rcu_dereference_check(sta->hnext, | 131 | sta = rcu_dereference_check(sta->hnext, |
135 | rcu_read_lock_held() || | ||
136 | lockdep_is_held(&local->sta_lock) || | 132 | lockdep_is_held(&local->sta_lock) || |
137 | lockdep_is_held(&local->sta_mtx)); | 133 | lockdep_is_held(&local->sta_mtx)); |
138 | } | 134 | } |
@@ -334,6 +330,7 @@ static int sta_info_finish_insert(struct sta_info *sta, bool async) | |||
334 | ieee80211_sta_debugfs_add(sta); | 330 | ieee80211_sta_debugfs_add(sta); |
335 | rate_control_add_sta_debugfs(sta); | 331 | rate_control_add_sta_debugfs(sta); |
336 | 332 | ||
333 | memset(&sinfo, 0, sizeof(sinfo)); | ||
337 | sinfo.filled = 0; | 334 | sinfo.filled = 0; |
338 | sinfo.generation = local->sta_generation; | 335 | sinfo.generation = local->sta_generation; |
339 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | 336 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); |
@@ -669,7 +666,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
669 | BUG_ON(!sdata->bss); | 666 | BUG_ON(!sdata->bss); |
670 | 667 | ||
671 | atomic_dec(&sdata->bss->num_sta_ps); | 668 | atomic_dec(&sdata->bss->num_sta_ps); |
672 | __sta_info_clear_tim_bit(sdata->bss, sta); | 669 | sta_info_clear_tim_bit(sta); |
673 | } | 670 | } |
674 | 671 | ||
675 | local->num_sta--; | 672 | local->num_sta--; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index c6ae8718bd5..28beb78e601 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -158,6 +158,8 @@ struct tid_ampdu_rx { | |||
158 | * @work: work struct for starting/stopping aggregation | 158 | * @work: work struct for starting/stopping aggregation |
159 | * @tid_rx_timer_expired: bitmap indicating on which TIDs the | 159 | * @tid_rx_timer_expired: bitmap indicating on which TIDs the |
160 | * RX timer expired until the work for it runs | 160 | * RX timer expired until the work for it runs |
161 | * @tid_rx_stop_requested: bitmap indicating which BA sessions per TID the | ||
162 | * driver requested to close until the work for it runs | ||
161 | * @mtx: mutex to protect all TX data (except non-NULL assignments | 163 | * @mtx: mutex to protect all TX data (except non-NULL assignments |
162 | * to tid_tx[idx], which are protected by the sta spinlock) | 164 | * to tid_tx[idx], which are protected by the sta spinlock) |
163 | */ | 165 | */ |
@@ -166,6 +168,7 @@ struct sta_ampdu_mlme { | |||
166 | /* rx */ | 168 | /* rx */ |
167 | struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM]; | 169 | struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM]; |
168 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; | 170 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; |
171 | unsigned long tid_rx_stop_requested[BITS_TO_LONGS(STA_TID_NUM)]; | ||
169 | /* tx */ | 172 | /* tx */ |
170 | struct work_struct work; | 173 | struct work_struct work; |
171 | struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM]; | 174 | struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM]; |
@@ -284,7 +287,8 @@ struct sta_info { | |||
284 | unsigned long rx_dropped; | 287 | unsigned long rx_dropped; |
285 | int last_signal; | 288 | int last_signal; |
286 | struct ewma avg_signal; | 289 | struct ewma avg_signal; |
287 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 290 | /* Plus 1 for non-QoS frames */ |
291 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES + 1]; | ||
288 | 292 | ||
289 | /* Updated from TX status path only, no locking requirements */ | 293 | /* Updated from TX status path only, no locking requirements */ |
290 | unsigned long tx_filtered_count; | 294 | unsigned long tx_filtered_count; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 1658efaa2e8..04cdbaf160b 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -336,7 +336,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
336 | continue; | 336 | continue; |
337 | if (wk->offchan_tx.frame != skb) | 337 | if (wk->offchan_tx.frame != skb) |
338 | continue; | 338 | continue; |
339 | wk->offchan_tx.frame = NULL; | 339 | wk->offchan_tx.status = true; |
340 | break; | 340 | break; |
341 | } | 341 | } |
342 | rcu_read_unlock(); | 342 | rcu_read_unlock(); |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 757e4eb2baf..f49d00a4c7f 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -101,6 +101,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx, | |||
101 | p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; | 101 | p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; |
102 | } | 102 | } |
103 | ctx->state = TKIP_STATE_PHASE1_DONE; | 103 | ctx->state = TKIP_STATE_PHASE1_DONE; |
104 | ctx->p1k_iv32 = tsc_IV32; | ||
104 | } | 105 | } |
105 | 106 | ||
106 | static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, | 107 | static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, |
@@ -140,60 +141,80 @@ static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, | |||
140 | /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets | 141 | /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets |
141 | * of the IV. Returns pointer to the octet following IVs (i.e., beginning of | 142 | * of the IV. Returns pointer to the octet following IVs (i.e., beginning of |
142 | * the packet payload). */ | 143 | * the packet payload). */ |
143 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16) | 144 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key) |
144 | { | 145 | { |
145 | pos = write_tkip_iv(pos, iv16); | 146 | lockdep_assert_held(&key->u.tkip.txlock); |
147 | |||
148 | pos = write_tkip_iv(pos, key->u.tkip.tx.iv16); | ||
146 | *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */; | 149 | *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */; |
147 | put_unaligned_le32(key->u.tkip.tx.iv32, pos); | 150 | put_unaligned_le32(key->u.tkip.tx.iv32, pos); |
148 | return pos + 4; | 151 | return pos + 4; |
149 | } | 152 | } |
150 | 153 | ||
151 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | 154 | static void ieee80211_compute_tkip_p1k(struct ieee80211_key *key, u32 iv32) |
152 | struct sk_buff *skb, enum ieee80211_tkip_key_type type, | ||
153 | u8 *outkey) | ||
154 | { | 155 | { |
155 | struct ieee80211_key *key = (struct ieee80211_key *) | 156 | struct ieee80211_sub_if_data *sdata = key->sdata; |
156 | container_of(keyconf, struct ieee80211_key, conf); | 157 | struct tkip_ctx *ctx = &key->u.tkip.tx; |
157 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 158 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
158 | u8 *data; | ||
159 | const u8 *tk; | ||
160 | struct tkip_ctx *ctx; | ||
161 | u16 iv16; | ||
162 | u32 iv32; | ||
163 | 159 | ||
164 | data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control); | 160 | lockdep_assert_held(&key->u.tkip.txlock); |
165 | iv16 = data[2] | (data[0] << 8); | 161 | |
166 | iv32 = get_unaligned_le32(&data[4]); | 162 | /* |
163 | * Update the P1K when the IV32 is different from the value it | ||
164 | * had when we last computed it (or when not initialised yet). | ||
165 | * This might flip-flop back and forth if packets are processed | ||
166 | * out-of-order due to the different ACs, but then we have to | ||
167 | * just compute the P1K more often. | ||
168 | */ | ||
169 | if (ctx->p1k_iv32 != iv32 || ctx->state == TKIP_STATE_NOT_INIT) | ||
170 | tkip_mixing_phase1(tk, ctx, sdata->vif.addr, iv32); | ||
171 | } | ||
167 | 172 | ||
168 | tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; | 173 | void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf, |
169 | ctx = &key->u.tkip.tx; | 174 | u32 iv32, u16 *p1k) |
175 | { | ||
176 | struct ieee80211_key *key = (struct ieee80211_key *) | ||
177 | container_of(keyconf, struct ieee80211_key, conf); | ||
178 | struct tkip_ctx *ctx = &key->u.tkip.tx; | ||
179 | unsigned long flags; | ||
170 | 180 | ||
171 | #ifdef CONFIG_MAC80211_TKIP_DEBUG | 181 | spin_lock_irqsave(&key->u.tkip.txlock, flags); |
172 | printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", | 182 | ieee80211_compute_tkip_p1k(key, iv32); |
173 | iv16, iv32); | 183 | memcpy(p1k, ctx->p1k, sizeof(ctx->p1k)); |
174 | 184 | spin_unlock_irqrestore(&key->u.tkip.txlock, flags); | |
175 | if (iv32 != ctx->iv32) { | 185 | } |
176 | printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n", | 186 | EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv); |
177 | iv32, ctx->iv32); | ||
178 | printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " | ||
179 | "fragmented packet\n"); | ||
180 | } | ||
181 | #endif | ||
182 | 187 | ||
183 | /* Update the p1k only when the iv16 in the packet wraps around, this | 188 | void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf, |
184 | * might occur after the wrap around of iv16 in the key in case of | 189 | const u8 *ta, u32 iv32, u16 *p1k) |
185 | * fragmented packets. */ | 190 | { |
186 | if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) | 191 | const u8 *tk = &keyconf->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
187 | tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32); | 192 | struct tkip_ctx ctx; |
188 | 193 | ||
189 | if (type == IEEE80211_TKIP_P1_KEY) { | 194 | tkip_mixing_phase1(tk, &ctx, ta, iv32); |
190 | memcpy(outkey, ctx->p1k, sizeof(u16) * 5); | 195 | memcpy(p1k, ctx.p1k, sizeof(ctx.p1k)); |
191 | return; | 196 | } |
192 | } | 197 | EXPORT_SYMBOL(ieee80211_get_tkip_rx_p1k); |
193 | 198 | ||
194 | tkip_mixing_phase2(tk, ctx, iv16, outkey); | 199 | void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, |
200 | struct sk_buff *skb, u8 *p2k) | ||
201 | { | ||
202 | struct ieee80211_key *key = (struct ieee80211_key *) | ||
203 | container_of(keyconf, struct ieee80211_key, conf); | ||
204 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; | ||
205 | struct tkip_ctx *ctx = &key->u.tkip.tx; | ||
206 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
207 | const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control); | ||
208 | u32 iv32 = get_unaligned_le32(&data[4]); | ||
209 | u16 iv16 = data[2] | (data[0] << 8); | ||
210 | unsigned long flags; | ||
211 | |||
212 | spin_lock_irqsave(&key->u.tkip.txlock, flags); | ||
213 | ieee80211_compute_tkip_p1k(key, iv32); | ||
214 | tkip_mixing_phase2(tk, ctx, iv16, p2k); | ||
215 | spin_unlock_irqrestore(&key->u.tkip.txlock, flags); | ||
195 | } | 216 | } |
196 | EXPORT_SYMBOL(ieee80211_get_tkip_key); | 217 | EXPORT_SYMBOL(ieee80211_get_tkip_p2k); |
197 | 218 | ||
198 | /* | 219 | /* |
199 | * Encrypt packet payload with TKIP using @key. @pos is a pointer to the | 220 | * Encrypt packet payload with TKIP using @key. @pos is a pointer to the |
@@ -204,19 +225,15 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key); | |||
204 | */ | 225 | */ |
205 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, | 226 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, |
206 | struct ieee80211_key *key, | 227 | struct ieee80211_key *key, |
207 | u8 *pos, size_t payload_len, u8 *ta) | 228 | struct sk_buff *skb, |
229 | u8 *payload, size_t payload_len) | ||
208 | { | 230 | { |
209 | u8 rc4key[16]; | 231 | u8 rc4key[16]; |
210 | struct tkip_ctx *ctx = &key->u.tkip.tx; | ||
211 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; | ||
212 | |||
213 | /* Calculate per-packet key */ | ||
214 | if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) | ||
215 | tkip_mixing_phase1(tk, ctx, ta, ctx->iv32); | ||
216 | 232 | ||
217 | tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); | 233 | ieee80211_get_tkip_p2k(&key->conf, skb, rc4key); |
218 | 234 | ||
219 | return ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); | 235 | return ieee80211_wep_encrypt_data(tfm, rc4key, 16, |
236 | payload, payload_len); | ||
220 | } | 237 | } |
221 | 238 | ||
222 | /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the | 239 | /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the |
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h index 1cab9c86978..e3ecb659b90 100644 --- a/net/mac80211/tkip.h +++ b/net/mac80211/tkip.h | |||
@@ -13,11 +13,13 @@ | |||
13 | #include <linux/crypto.h> | 13 | #include <linux/crypto.h> |
14 | #include "key.h" | 14 | #include "key.h" |
15 | 15 | ||
16 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16); | 16 | u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key); |
17 | 17 | ||
18 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, | 18 | int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, |
19 | struct ieee80211_key *key, | 19 | struct ieee80211_key *key, |
20 | u8 *pos, size_t payload_len, u8 *ta); | 20 | struct sk_buff *skb, |
21 | u8 *payload, size_t payload_len); | ||
22 | |||
21 | enum { | 23 | enum { |
22 | TKIP_DECRYPT_OK = 0, | 24 | TKIP_DECRYPT_OK = 0, |
23 | TKIP_DECRYPT_NO_EXT_IV = -1, | 25 | TKIP_DECRYPT_NO_EXT_IV = -1, |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3104c844b54..8cb0d2d0ac6 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -589,6 +589,9 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
589 | break; | 589 | break; |
590 | } | 590 | } |
591 | 591 | ||
592 | if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED)) | ||
593 | return TX_DROP; | ||
594 | |||
592 | if (!skip_hw && tx->key && | 595 | if (!skip_hw && tx->key && |
593 | tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 596 | tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
594 | info->control.hw_key = &tx->key->conf; | 597 | info->control.hw_key = &tx->key->conf; |
@@ -1474,18 +1477,14 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1474 | 1477 | ||
1475 | /* device xmit handlers */ | 1478 | /* device xmit handlers */ |
1476 | 1479 | ||
1477 | static int ieee80211_skb_resize(struct ieee80211_local *local, | 1480 | static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, |
1478 | struct sk_buff *skb, | 1481 | struct sk_buff *skb, |
1479 | int head_need, bool may_encrypt) | 1482 | int head_need, bool may_encrypt) |
1480 | { | 1483 | { |
1484 | struct ieee80211_local *local = sdata->local; | ||
1481 | int tail_need = 0; | 1485 | int tail_need = 0; |
1482 | 1486 | ||
1483 | /* | 1487 | if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) { |
1484 | * This could be optimised, devices that do full hardware | ||
1485 | * crypto (including TKIP MMIC) need no tailroom... But we | ||
1486 | * have no drivers for such devices currently. | ||
1487 | */ | ||
1488 | if (may_encrypt) { | ||
1489 | tail_need = IEEE80211_ENCRYPT_TAILROOM; | 1488 | tail_need = IEEE80211_ENCRYPT_TAILROOM; |
1490 | tail_need -= skb_tailroom(skb); | 1489 | tail_need -= skb_tailroom(skb); |
1491 | tail_need = max_t(int, tail_need, 0); | 1490 | tail_need = max_t(int, tail_need, 0); |
@@ -1578,7 +1577,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1578 | headroom -= skb_headroom(skb); | 1577 | headroom -= skb_headroom(skb); |
1579 | headroom = max_t(int, 0, headroom); | 1578 | headroom = max_t(int, 0, headroom); |
1580 | 1579 | ||
1581 | if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) { | 1580 | if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { |
1582 | dev_kfree_skb(skb); | 1581 | dev_kfree_skb(skb); |
1583 | rcu_read_unlock(); | 1582 | rcu_read_unlock(); |
1584 | return; | 1583 | return; |
@@ -1945,7 +1944,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1945 | head_need += IEEE80211_ENCRYPT_HEADROOM; | 1944 | head_need += IEEE80211_ENCRYPT_HEADROOM; |
1946 | head_need += local->tx_headroom; | 1945 | head_need += local->tx_headroom; |
1947 | head_need = max_t(int, 0, head_need); | 1946 | head_need = max_t(int, 0, head_need); |
1948 | if (ieee80211_skb_resize(local, skb, head_need, true)) | 1947 | if (ieee80211_skb_resize(sdata, skb, head_need, true)) |
1949 | goto fail; | 1948 | goto fail; |
1950 | } | 1949 | } |
1951 | 1950 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d3fe2d23748..fd031e821f4 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -799,6 +799,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
799 | 799 | ||
800 | qparam.uapsd = false; | 800 | qparam.uapsd = false; |
801 | 801 | ||
802 | local->tx_conf[queue] = qparam; | ||
802 | drv_conf_tx(local, queue, &qparam); | 803 | drv_conf_tx(local, queue, &qparam); |
803 | } | 804 | } |
804 | 805 | ||
@@ -1016,9 +1017,10 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1016 | } | 1017 | } |
1017 | 1018 | ||
1018 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1019 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1019 | u8 *dst, | 1020 | u8 *dst, u32 ratemask, |
1020 | const u8 *ssid, size_t ssid_len, | 1021 | const u8 *ssid, size_t ssid_len, |
1021 | const u8 *ie, size_t ie_len) | 1022 | const u8 *ie, size_t ie_len, |
1023 | bool directed) | ||
1022 | { | 1024 | { |
1023 | struct ieee80211_local *local = sdata->local; | 1025 | struct ieee80211_local *local = sdata->local; |
1024 | struct sk_buff *skb; | 1026 | struct sk_buff *skb; |
@@ -1035,18 +1037,26 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1035 | return NULL; | 1037 | return NULL; |
1036 | } | 1038 | } |
1037 | 1039 | ||
1038 | chan = ieee80211_frequency_to_channel( | 1040 | /* |
1039 | local->hw.conf.channel->center_freq); | 1041 | * Do not send DS Channel parameter for directed probe requests |
1042 | * in order to maximize the chance that we get a response. Some | ||
1043 | * badly-behaved APs don't respond when this parameter is included. | ||
1044 | */ | ||
1045 | if (directed) | ||
1046 | chan = 0; | ||
1047 | else | ||
1048 | chan = ieee80211_frequency_to_channel( | ||
1049 | local->hw.conf.channel->center_freq); | ||
1040 | 1050 | ||
1041 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, | 1051 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, |
1042 | local->hw.conf.channel->band, | 1052 | local->hw.conf.channel->band, |
1043 | sdata->rc_rateidx_mask | 1053 | ratemask, chan); |
1044 | [local->hw.conf.channel->band], | ||
1045 | chan); | ||
1046 | 1054 | ||
1047 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 1055 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
1048 | ssid, ssid_len, | 1056 | ssid, ssid_len, |
1049 | buf, buf_len); | 1057 | buf, buf_len); |
1058 | if (!skb) | ||
1059 | goto out; | ||
1050 | 1060 | ||
1051 | if (dst) { | 1061 | if (dst) { |
1052 | mgmt = (struct ieee80211_mgmt *) skb->data; | 1062 | mgmt = (struct ieee80211_mgmt *) skb->data; |
@@ -1055,6 +1065,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1055 | } | 1065 | } |
1056 | 1066 | ||
1057 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1067 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
1068 | |||
1069 | out: | ||
1058 | kfree(buf); | 1070 | kfree(buf); |
1059 | 1071 | ||
1060 | return skb; | 1072 | return skb; |
@@ -1062,11 +1074,13 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1062 | 1074 | ||
1063 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1075 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1064 | const u8 *ssid, size_t ssid_len, | 1076 | const u8 *ssid, size_t ssid_len, |
1065 | const u8 *ie, size_t ie_len) | 1077 | const u8 *ie, size_t ie_len, |
1078 | u32 ratemask, bool directed) | ||
1066 | { | 1079 | { |
1067 | struct sk_buff *skb; | 1080 | struct sk_buff *skb; |
1068 | 1081 | ||
1069 | skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len); | 1082 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, |
1083 | ie, ie_len, directed); | ||
1070 | if (skb) | 1084 | if (skb) |
1071 | ieee80211_tx_skb(sdata, skb); | 1085 | ieee80211_tx_skb(sdata, skb); |
1072 | } | 1086 | } |
@@ -1123,7 +1137,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1123 | struct ieee80211_hw *hw = &local->hw; | 1137 | struct ieee80211_hw *hw = &local->hw; |
1124 | struct ieee80211_sub_if_data *sdata; | 1138 | struct ieee80211_sub_if_data *sdata; |
1125 | struct sta_info *sta; | 1139 | struct sta_info *sta; |
1126 | int res; | 1140 | int res, i; |
1127 | 1141 | ||
1128 | #ifdef CONFIG_PM | 1142 | #ifdef CONFIG_PM |
1129 | if (local->suspended) | 1143 | if (local->suspended) |
@@ -1146,27 +1160,37 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1146 | } | 1160 | } |
1147 | #endif | 1161 | #endif |
1148 | 1162 | ||
1149 | /* restart hardware */ | 1163 | /* setup fragmentation threshold */ |
1150 | if (local->open_count) { | 1164 | drv_set_frag_threshold(local, hw->wiphy->frag_threshold); |
1151 | /* | 1165 | |
1152 | * Upon resume hardware can sometimes be goofy due to | 1166 | /* setup RTS threshold */ |
1153 | * various platform / driver / bus issues, so restarting | 1167 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); |
1154 | * the device may at times not work immediately. Propagate | 1168 | |
1155 | * the error. | 1169 | /* reset coverage class */ |
1156 | */ | 1170 | drv_set_coverage_class(local, hw->wiphy->coverage_class); |
1157 | res = drv_start(local); | ||
1158 | if (res) { | ||
1159 | WARN(local->suspended, "Hardware became unavailable " | ||
1160 | "upon resume. This could be a software issue " | ||
1161 | "prior to suspend or a hardware issue.\n"); | ||
1162 | return res; | ||
1163 | } | ||
1164 | 1171 | ||
1165 | ieee80211_led_radio(local, true); | 1172 | /* everything else happens only if HW was up & running */ |
1166 | ieee80211_mod_tpt_led_trig(local, | 1173 | if (!local->open_count) |
1167 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | 1174 | goto wake_up; |
1175 | |||
1176 | /* | ||
1177 | * Upon resume hardware can sometimes be goofy due to | ||
1178 | * various platform / driver / bus issues, so restarting | ||
1179 | * the device may at times not work immediately. Propagate | ||
1180 | * the error. | ||
1181 | */ | ||
1182 | res = drv_start(local); | ||
1183 | if (res) { | ||
1184 | WARN(local->suspended, "Hardware became unavailable " | ||
1185 | "upon resume. This could be a software issue " | ||
1186 | "prior to suspend or a hardware issue.\n"); | ||
1187 | return res; | ||
1168 | } | 1188 | } |
1169 | 1189 | ||
1190 | ieee80211_led_radio(local, true); | ||
1191 | ieee80211_mod_tpt_led_trig(local, | ||
1192 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | ||
1193 | |||
1170 | /* add interfaces */ | 1194 | /* add interfaces */ |
1171 | list_for_each_entry(sdata, &local->interfaces, list) { | 1195 | list_for_each_entry(sdata, &local->interfaces, list) { |
1172 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1196 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
@@ -1190,11 +1214,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1190 | } | 1214 | } |
1191 | mutex_unlock(&local->sta_mtx); | 1215 | mutex_unlock(&local->sta_mtx); |
1192 | 1216 | ||
1193 | /* setup fragmentation threshold */ | 1217 | /* reconfigure tx conf */ |
1194 | drv_set_frag_threshold(local, hw->wiphy->frag_threshold); | 1218 | for (i = 0; i < hw->queues; i++) |
1195 | 1219 | drv_conf_tx(local, i, &local->tx_conf[i]); | |
1196 | /* setup RTS threshold */ | ||
1197 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); | ||
1198 | 1220 | ||
1199 | /* reconfigure hardware */ | 1221 | /* reconfigure hardware */ |
1200 | ieee80211_hw_config(local, ~0); | 1222 | ieee80211_hw_config(local, ~0); |
@@ -1321,6 +1343,33 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1321 | return 0; | 1343 | return 0; |
1322 | } | 1344 | } |
1323 | 1345 | ||
1346 | void ieee80211_resume_disconnect(struct ieee80211_vif *vif) | ||
1347 | { | ||
1348 | struct ieee80211_sub_if_data *sdata; | ||
1349 | struct ieee80211_local *local; | ||
1350 | struct ieee80211_key *key; | ||
1351 | |||
1352 | if (WARN_ON(!vif)) | ||
1353 | return; | ||
1354 | |||
1355 | sdata = vif_to_sdata(vif); | ||
1356 | local = sdata->local; | ||
1357 | |||
1358 | if (WARN_ON(!local->resuming)) | ||
1359 | return; | ||
1360 | |||
1361 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | ||
1362 | return; | ||
1363 | |||
1364 | sdata->flags |= IEEE80211_SDATA_DISCONNECT_RESUME; | ||
1365 | |||
1366 | mutex_lock(&local->key_mtx); | ||
1367 | list_for_each_entry(key, &sdata->key_list, list) | ||
1368 | key->flags |= KEY_FLAG_TAINTED; | ||
1369 | mutex_unlock(&local->key_mtx); | ||
1370 | } | ||
1371 | EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect); | ||
1372 | |||
1324 | static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, | 1373 | static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, |
1325 | enum ieee80211_smps_mode *smps_mode) | 1374 | enum ieee80211_smps_mode *smps_mode) |
1326 | { | 1375 | { |
@@ -1437,3 +1486,43 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) | |||
1437 | 1486 | ||
1438 | return pos; | 1487 | return pos; |
1439 | } | 1488 | } |
1489 | |||
1490 | static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata, | ||
1491 | int rssi_min_thold, | ||
1492 | int rssi_max_thold) | ||
1493 | { | ||
1494 | trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold); | ||
1495 | |||
1496 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) | ||
1497 | return; | ||
1498 | |||
1499 | /* | ||
1500 | * Scale up threshold values before storing it, as the RSSI averaging | ||
1501 | * algorithm uses a scaled up value as well. Change this scaling | ||
1502 | * factor if the RSSI averaging algorithm changes. | ||
1503 | */ | ||
1504 | sdata->u.mgd.rssi_min_thold = rssi_min_thold*16; | ||
1505 | sdata->u.mgd.rssi_max_thold = rssi_max_thold*16; | ||
1506 | } | ||
1507 | |||
1508 | void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, | ||
1509 | int rssi_min_thold, | ||
1510 | int rssi_max_thold) | ||
1511 | { | ||
1512 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1513 | |||
1514 | WARN_ON(rssi_min_thold == rssi_max_thold || | ||
1515 | rssi_min_thold > rssi_max_thold); | ||
1516 | |||
1517 | _ieee80211_enable_rssi_reports(sdata, rssi_min_thold, | ||
1518 | rssi_max_thold); | ||
1519 | } | ||
1520 | EXPORT_SYMBOL(ieee80211_enable_rssi_reports); | ||
1521 | |||
1522 | void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) | ||
1523 | { | ||
1524 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1525 | |||
1526 | _ieee80211_enable_rssi_reports(sdata, 0, 0); | ||
1527 | } | ||
1528 | EXPORT_SYMBOL(ieee80211_disable_rssi_reports); | ||
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 28bc084dbfb..7a49532f14c 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -151,8 +151,7 @@ void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb) | |||
151 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | 151 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
152 | 152 | ||
153 | if (unlikely(local->wifi_wme_noack_test)) | 153 | if (unlikely(local->wifi_wme_noack_test)) |
154 | ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK << | 154 | ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; |
155 | QOS_CONTROL_ACK_POLICY_SHIFT; | ||
156 | /* qos header is 2 bytes, second reserved */ | 155 | /* qos header is 2 bytes, second reserved */ |
157 | *p++ = ack_policy | tid; | 156 | *p++ = ack_policy | tid; |
158 | *p = 0; | 157 | *p = 0; |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 6053b1c9fee..faead6d0202 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -13,11 +13,6 @@ | |||
13 | #include <linux/netdevice.h> | 13 | #include <linux/netdevice.h> |
14 | #include "ieee80211_i.h" | 14 | #include "ieee80211_i.h" |
15 | 15 | ||
16 | #define QOS_CONTROL_ACK_POLICY_NORMAL 0 | ||
17 | #define QOS_CONTROL_ACK_POLICY_NOACK 1 | ||
18 | |||
19 | #define QOS_CONTROL_ACK_POLICY_SHIFT 5 | ||
20 | |||
21 | extern const int ieee802_1d_to_ac[8]; | 16 | extern const int ieee802_1d_to_ac[8]; |
22 | 17 | ||
23 | u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | 18 | u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index d2e7f0e8667..7737f204d3f 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include "ieee80211_i.h" | 26 | #include "ieee80211_i.h" |
27 | #include "rate.h" | 27 | #include "rate.h" |
28 | #include "driver-ops.h" | ||
28 | 29 | ||
29 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | 30 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) |
30 | #define IEEE80211_AUTH_MAX_TRIES 3 | 31 | #define IEEE80211_AUTH_MAX_TRIES 3 |
@@ -427,6 +428,14 @@ ieee80211_direct_probe(struct ieee80211_work *wk) | |||
427 | struct ieee80211_sub_if_data *sdata = wk->sdata; | 428 | struct ieee80211_sub_if_data *sdata = wk->sdata; |
428 | struct ieee80211_local *local = sdata->local; | 429 | struct ieee80211_local *local = sdata->local; |
429 | 430 | ||
431 | if (!wk->probe_auth.synced) { | ||
432 | int ret = drv_tx_sync(local, sdata, wk->filter_ta, | ||
433 | IEEE80211_TX_SYNC_AUTH); | ||
434 | if (ret) | ||
435 | return WORK_ACT_TIMEOUT; | ||
436 | } | ||
437 | wk->probe_auth.synced = true; | ||
438 | |||
430 | wk->probe_auth.tries++; | 439 | wk->probe_auth.tries++; |
431 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { | 440 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { |
432 | printk(KERN_DEBUG "%s: direct probe to %pM timed out\n", | 441 | printk(KERN_DEBUG "%s: direct probe to %pM timed out\n", |
@@ -450,7 +459,8 @@ ieee80211_direct_probe(struct ieee80211_work *wk) | |||
450 | * will not answer to direct packet in unassociated state. | 459 | * will not answer to direct packet in unassociated state. |
451 | */ | 460 | */ |
452 | ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, | 461 | ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, |
453 | wk->probe_auth.ssid_len, NULL, 0); | 462 | wk->probe_auth.ssid_len, NULL, 0, |
463 | (u32) -1, true); | ||
454 | 464 | ||
455 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 465 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
456 | run_again(local, wk->timeout); | 466 | run_again(local, wk->timeout); |
@@ -465,6 +475,14 @@ ieee80211_authenticate(struct ieee80211_work *wk) | |||
465 | struct ieee80211_sub_if_data *sdata = wk->sdata; | 475 | struct ieee80211_sub_if_data *sdata = wk->sdata; |
466 | struct ieee80211_local *local = sdata->local; | 476 | struct ieee80211_local *local = sdata->local; |
467 | 477 | ||
478 | if (!wk->probe_auth.synced) { | ||
479 | int ret = drv_tx_sync(local, sdata, wk->filter_ta, | ||
480 | IEEE80211_TX_SYNC_AUTH); | ||
481 | if (ret) | ||
482 | return WORK_ACT_TIMEOUT; | ||
483 | } | ||
484 | wk->probe_auth.synced = true; | ||
485 | |||
468 | wk->probe_auth.tries++; | 486 | wk->probe_auth.tries++; |
469 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { | 487 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { |
470 | printk(KERN_DEBUG "%s: authentication with %pM" | 488 | printk(KERN_DEBUG "%s: authentication with %pM" |
@@ -498,6 +516,14 @@ ieee80211_associate(struct ieee80211_work *wk) | |||
498 | struct ieee80211_sub_if_data *sdata = wk->sdata; | 516 | struct ieee80211_sub_if_data *sdata = wk->sdata; |
499 | struct ieee80211_local *local = sdata->local; | 517 | struct ieee80211_local *local = sdata->local; |
500 | 518 | ||
519 | if (!wk->assoc.synced) { | ||
520 | int ret = drv_tx_sync(local, sdata, wk->filter_ta, | ||
521 | IEEE80211_TX_SYNC_ASSOC); | ||
522 | if (ret) | ||
523 | return WORK_ACT_TIMEOUT; | ||
524 | } | ||
525 | wk->assoc.synced = true; | ||
526 | |||
501 | wk->assoc.tries++; | 527 | wk->assoc.tries++; |
502 | if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { | 528 | if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { |
503 | printk(KERN_DEBUG "%s: association with %pM" | 529 | printk(KERN_DEBUG "%s: association with %pM" |
@@ -553,7 +579,7 @@ ieee80211_offchannel_tx(struct ieee80211_work *wk) | |||
553 | /* | 579 | /* |
554 | * After this, offchan_tx.frame remains but now is no | 580 | * After this, offchan_tx.frame remains but now is no |
555 | * longer a valid pointer -- we still need it as the | 581 | * longer a valid pointer -- we still need it as the |
556 | * cookie for canceling this work. | 582 | * cookie for canceling this work/status matching. |
557 | */ | 583 | */ |
558 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); | 584 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); |
559 | 585 | ||
@@ -1060,14 +1086,13 @@ static void ieee80211_work_work(struct work_struct *work) | |||
1060 | continue; | 1086 | continue; |
1061 | if (wk->chan != local->tmp_channel) | 1087 | if (wk->chan != local->tmp_channel) |
1062 | continue; | 1088 | continue; |
1063 | if (ieee80211_work_ct_coexists(wk->chan_type, | 1089 | if (!ieee80211_work_ct_coexists(wk->chan_type, |
1064 | local->tmp_channel_type)) | 1090 | local->tmp_channel_type)) |
1065 | continue; | 1091 | continue; |
1066 | remain_off_channel = true; | 1092 | remain_off_channel = true; |
1067 | } | 1093 | } |
1068 | 1094 | ||
1069 | if (!remain_off_channel && local->tmp_channel) { | 1095 | if (!remain_off_channel && local->tmp_channel) { |
1070 | bool on_oper_chan = ieee80211_cfg_on_oper_channel(local); | ||
1071 | local->tmp_channel = NULL; | 1096 | local->tmp_channel = NULL; |
1072 | /* If tmp_channel wasn't operating channel, then | 1097 | /* If tmp_channel wasn't operating channel, then |
1073 | * we need to go back on-channel. | 1098 | * we need to go back on-channel. |
@@ -1077,7 +1102,7 @@ static void ieee80211_work_work(struct work_struct *work) | |||
1077 | * we still need to do a hardware config. Currently, | 1102 | * we still need to do a hardware config. Currently, |
1078 | * we cannot be here while scanning, however. | 1103 | * we cannot be here while scanning, however. |
1079 | */ | 1104 | */ |
1080 | if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan) | 1105 | if (!ieee80211_cfg_on_oper_channel(local)) |
1081 | ieee80211_hw_config(local, 0); | 1106 | ieee80211_hw_config(local, 0); |
1082 | 1107 | ||
1083 | /* At the least, we need to disable offchannel_ps, | 1108 | /* At the least, we need to disable offchannel_ps, |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 8f6a302d2ac..ea70837e9d8 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/gfp.h> | 15 | #include <linux/gfp.h> |
16 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | #include <crypto/aes.h> | ||
18 | 19 | ||
19 | #include "ieee80211_i.h" | 20 | #include "ieee80211_i.h" |
20 | #include "michael.h" | 21 | #include "michael.h" |
@@ -86,11 +87,6 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
86 | struct sk_buff *skb = rx->skb; | 87 | struct sk_buff *skb = rx->skb; |
87 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 88 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
88 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 89 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
89 | int queue = rx->queue; | ||
90 | |||
91 | /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */ | ||
92 | if (rx->queue == NUM_RX_DATA_QUEUES - 1) | ||
93 | queue = 0; | ||
94 | 90 | ||
95 | /* | 91 | /* |
96 | * it makes no sense to check for MIC errors on anything other | 92 | * it makes no sense to check for MIC errors on anything other |
@@ -109,7 +105,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
109 | if (status->flag & RX_FLAG_MMIC_ERROR) | 105 | if (status->flag & RX_FLAG_MMIC_ERROR) |
110 | goto mic_fail; | 106 | goto mic_fail; |
111 | 107 | ||
112 | if (!(status->flag & RX_FLAG_IV_STRIPPED)) | 108 | if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) |
113 | goto update_iv; | 109 | goto update_iv; |
114 | 110 | ||
115 | return RX_CONTINUE; | 111 | return RX_CONTINUE; |
@@ -153,8 +149,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
153 | 149 | ||
154 | update_iv: | 150 | update_iv: |
155 | /* update IV in key information to be able to detect replays */ | 151 | /* update IV in key information to be able to detect replays */ |
156 | rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32; | 152 | rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32; |
157 | rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16; | 153 | rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16; |
158 | 154 | ||
159 | return RX_CONTINUE; | 155 | return RX_CONTINUE; |
160 | 156 | ||
@@ -176,6 +172,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
176 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 172 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
177 | struct ieee80211_key *key = tx->key; | 173 | struct ieee80211_key *key = tx->key; |
178 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 174 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
175 | unsigned long flags; | ||
179 | unsigned int hdrlen; | 176 | unsigned int hdrlen; |
180 | int len, tail; | 177 | int len, tail; |
181 | u8 *pos; | 178 | u8 *pos; |
@@ -203,11 +200,12 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
203 | pos += hdrlen; | 200 | pos += hdrlen; |
204 | 201 | ||
205 | /* Increase IV for the frame */ | 202 | /* Increase IV for the frame */ |
203 | spin_lock_irqsave(&key->u.tkip.txlock, flags); | ||
206 | key->u.tkip.tx.iv16++; | 204 | key->u.tkip.tx.iv16++; |
207 | if (key->u.tkip.tx.iv16 == 0) | 205 | if (key->u.tkip.tx.iv16 == 0) |
208 | key->u.tkip.tx.iv32++; | 206 | key->u.tkip.tx.iv32++; |
209 | 207 | pos = ieee80211_tkip_add_iv(pos, key); | |
210 | pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); | 208 | spin_unlock_irqrestore(&key->u.tkip.txlock, flags); |
211 | 209 | ||
212 | /* hwaccel - with software IV */ | 210 | /* hwaccel - with software IV */ |
213 | if (info->control.hw_key) | 211 | if (info->control.hw_key) |
@@ -216,9 +214,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
216 | /* Add room for ICV */ | 214 | /* Add room for ICV */ |
217 | skb_put(skb, TKIP_ICV_LEN); | 215 | skb_put(skb, TKIP_ICV_LEN); |
218 | 216 | ||
219 | hdr = (struct ieee80211_hdr *) skb->data; | ||
220 | return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, | 217 | return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, |
221 | key, pos, len, hdr->addr2); | 218 | key, skb, pos, len); |
222 | } | 219 | } |
223 | 220 | ||
224 | 221 | ||
@@ -246,11 +243,6 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
246 | struct ieee80211_key *key = rx->key; | 243 | struct ieee80211_key *key = rx->key; |
247 | struct sk_buff *skb = rx->skb; | 244 | struct sk_buff *skb = rx->skb; |
248 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 245 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
249 | int queue = rx->queue; | ||
250 | |||
251 | /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */ | ||
252 | if (rx->queue == NUM_RX_DATA_QUEUES - 1) | ||
253 | queue = 0; | ||
254 | 246 | ||
255 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 247 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
256 | 248 | ||
@@ -271,7 +263,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
271 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, | 263 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, |
272 | key, skb->data + hdrlen, | 264 | key, skb->data + hdrlen, |
273 | skb->len - hdrlen, rx->sta->sta.addr, | 265 | skb->len - hdrlen, rx->sta->sta.addr, |
274 | hdr->addr1, hwaccel, queue, | 266 | hdr->addr1, hwaccel, rx->security_idx, |
275 | &rx->tkip_iv32, | 267 | &rx->tkip_iv32, |
276 | &rx->tkip_iv16); | 268 | &rx->tkip_iv16); |
277 | if (res != TKIP_DECRYPT_OK) | 269 | if (res != TKIP_DECRYPT_OK) |
@@ -299,8 +291,10 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, | |||
299 | unsigned int hdrlen; | 291 | unsigned int hdrlen; |
300 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 292 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
301 | 293 | ||
302 | b_0 = scratch + 3 * AES_BLOCK_LEN; | 294 | memset(scratch, 0, 6 * AES_BLOCK_SIZE); |
303 | aad = scratch + 4 * AES_BLOCK_LEN; | 295 | |
296 | b_0 = scratch + 3 * AES_BLOCK_SIZE; | ||
297 | aad = scratch + 4 * AES_BLOCK_SIZE; | ||
304 | 298 | ||
305 | /* | 299 | /* |
306 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) | 300 | * Mask FC: zero subtype b4 b5 b6 (if not mgmt) |
@@ -389,8 +383,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
389 | struct ieee80211_key *key = tx->key; | 383 | struct ieee80211_key *key = tx->key; |
390 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 384 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
391 | int hdrlen, len, tail; | 385 | int hdrlen, len, tail; |
392 | u8 *pos, *pn; | 386 | u8 *pos; |
393 | int i; | 387 | u8 pn[6]; |
388 | u64 pn64; | ||
389 | u8 scratch[6 * AES_BLOCK_SIZE]; | ||
394 | 390 | ||
395 | if (info->control.hw_key && | 391 | if (info->control.hw_key && |
396 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 392 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
@@ -418,14 +414,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
418 | hdr = (struct ieee80211_hdr *) pos; | 414 | hdr = (struct ieee80211_hdr *) pos; |
419 | pos += hdrlen; | 415 | pos += hdrlen; |
420 | 416 | ||
421 | /* PN = PN + 1 */ | 417 | pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn); |
422 | pn = key->u.ccmp.tx_pn; | ||
423 | 418 | ||
424 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { | 419 | pn[5] = pn64; |
425 | pn[i]++; | 420 | pn[4] = pn64 >> 8; |
426 | if (pn[i]) | 421 | pn[3] = pn64 >> 16; |
427 | break; | 422 | pn[2] = pn64 >> 24; |
428 | } | 423 | pn[1] = pn64 >> 32; |
424 | pn[0] = pn64 >> 40; | ||
429 | 425 | ||
430 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); | 426 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); |
431 | 427 | ||
@@ -434,8 +430,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
434 | return 0; | 430 | return 0; |
435 | 431 | ||
436 | pos += CCMP_HDR_LEN; | 432 | pos += CCMP_HDR_LEN; |
437 | ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); | 433 | ccmp_special_blocks(skb, pn, scratch, 0); |
438 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len, | 434 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, |
439 | pos, skb_put(skb, CCMP_MIC_LEN)); | 435 | pos, skb_put(skb, CCMP_MIC_LEN)); |
440 | 436 | ||
441 | return 0; | 437 | return 0; |
@@ -482,8 +478,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
482 | 478 | ||
483 | ccmp_hdr2pn(pn, skb->data + hdrlen); | 479 | ccmp_hdr2pn(pn, skb->data + hdrlen); |
484 | 480 | ||
485 | queue = ieee80211_is_mgmt(hdr->frame_control) ? | 481 | queue = rx->security_idx; |
486 | NUM_RX_DATA_QUEUES : rx->queue; | ||
487 | 482 | ||
488 | if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { | 483 | if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { |
489 | key->u.ccmp.replays++; | 484 | key->u.ccmp.replays++; |
@@ -491,11 +486,12 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
491 | } | 486 | } |
492 | 487 | ||
493 | if (!(status->flag & RX_FLAG_DECRYPTED)) { | 488 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
489 | u8 scratch[6 * AES_BLOCK_SIZE]; | ||
494 | /* hardware didn't decrypt/verify MIC */ | 490 | /* hardware didn't decrypt/verify MIC */ |
495 | ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1); | 491 | ccmp_special_blocks(skb, pn, scratch, 1); |
496 | 492 | ||
497 | if (ieee80211_aes_ccm_decrypt( | 493 | if (ieee80211_aes_ccm_decrypt( |
498 | key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf, | 494 | key->u.ccmp.tfm, scratch, |
499 | skb->data + hdrlen + CCMP_HDR_LEN, data_len, | 495 | skb->data + hdrlen + CCMP_HDR_LEN, data_len, |
500 | skb->data + skb->len - CCMP_MIC_LEN, | 496 | skb->data + skb->len - CCMP_MIC_LEN, |
501 | skb->data + hdrlen + CCMP_HDR_LEN)) | 497 | skb->data + hdrlen + CCMP_HDR_LEN)) |
@@ -526,6 +522,16 @@ static void bip_aad(struct sk_buff *skb, u8 *aad) | |||
526 | } | 522 | } |
527 | 523 | ||
528 | 524 | ||
525 | static inline void bip_ipn_set64(u8 *d, u64 pn) | ||
526 | { | ||
527 | *d++ = pn; | ||
528 | *d++ = pn >> 8; | ||
529 | *d++ = pn >> 16; | ||
530 | *d++ = pn >> 24; | ||
531 | *d++ = pn >> 32; | ||
532 | *d = pn >> 40; | ||
533 | } | ||
534 | |||
529 | static inline void bip_ipn_swap(u8 *d, const u8 *s) | 535 | static inline void bip_ipn_swap(u8 *d, const u8 *s) |
530 | { | 536 | { |
531 | *d++ = s[5]; | 537 | *d++ = s[5]; |
@@ -544,8 +550,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) | |||
544 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 550 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
545 | struct ieee80211_key *key = tx->key; | 551 | struct ieee80211_key *key = tx->key; |
546 | struct ieee80211_mmie *mmie; | 552 | struct ieee80211_mmie *mmie; |
547 | u8 *pn, aad[20]; | 553 | u8 aad[20]; |
548 | int i; | 554 | u64 pn64; |
549 | 555 | ||
550 | if (info->control.hw_key) | 556 | if (info->control.hw_key) |
551 | return 0; | 557 | return 0; |
@@ -559,22 +565,17 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) | |||
559 | mmie->key_id = cpu_to_le16(key->conf.keyidx); | 565 | mmie->key_id = cpu_to_le16(key->conf.keyidx); |
560 | 566 | ||
561 | /* PN = PN + 1 */ | 567 | /* PN = PN + 1 */ |
562 | pn = key->u.aes_cmac.tx_pn; | 568 | pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn); |
563 | 569 | ||
564 | for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) { | 570 | bip_ipn_set64(mmie->sequence_number, pn64); |
565 | pn[i]++; | ||
566 | if (pn[i]) | ||
567 | break; | ||
568 | } | ||
569 | bip_ipn_swap(mmie->sequence_number, pn); | ||
570 | 571 | ||
571 | bip_aad(skb, aad); | 572 | bip_aad(skb, aad); |
572 | 573 | ||
573 | /* | 574 | /* |
574 | * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) | 575 | * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) |
575 | */ | 576 | */ |
576 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf, | 577 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, |
577 | aad, skb->data + 24, skb->len - 24, mmie->mic); | 578 | skb->data + 24, skb->len - 24, mmie->mic); |
578 | 579 | ||
579 | return TX_CONTINUE; | 580 | return TX_CONTINUE; |
580 | } | 581 | } |
@@ -612,8 +613,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | |||
612 | if (!(status->flag & RX_FLAG_DECRYPTED)) { | 613 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
613 | /* hardware didn't decrypt/verify MIC */ | 614 | /* hardware didn't decrypt/verify MIC */ |
614 | bip_aad(skb, aad); | 615 | bip_aad(skb, aad); |
615 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, | 616 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, |
616 | key->u.aes_cmac.rx_crypto_buf, aad, | ||
617 | skb->data + 24, skb->len - 24, mic); | 617 | skb->data + 24, skb->len - 24, mic); |
618 | if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { | 618 | if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { |
619 | key->u.aes_cmac.icverrors++; | 619 | key->u.aes_cmac.icverrors++; |