]>
Commit | Line | Data |
---|---|---|
c06f7f46 GKH |
1 | From 56363ddeeed3afc5277ca227209773bc1042cc7b Mon Sep 17 00:00:00 2001 |
2 | From: Felix Fietkau <nbd@openwrt.org> | |
3 | Date: Sat, 28 Aug 2010 18:21:21 +0200 | |
4 | Subject: ath9k: fix spurious MIC failure reports | |
5 | ||
6 | From: Felix Fietkau <nbd@openwrt.org> | |
7 | ||
8 | commit 56363ddeeed3afc5277ca227209773bc1042cc7b upstream. | |
9 | ||
10 | According to the hardware documentation, the MIC failure bit is only | |
11 | valid if the frame was decrypted using a valid TKIP key and is not a | |
12 | fragment. | |
13 | In some setups I've seen hardware-reported MIC failures on an AP that | |
14 | was configured for CCMP only, so it's clear that additional checks are | |
15 | necessary. | |
16 | ||
17 | Signed-off-by: Felix Fietkau <nbd@openwrt.org> | |
18 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | |
19 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
20 | ||
21 | --- | |
22 | drivers/net/wireless/ath/ath.h | 1 + | |
23 | drivers/net/wireless/ath/ath9k/common.c | 11 +++++++++++ | |
24 | drivers/net/wireless/ath/ath9k/mac.c | 3 ++- | |
25 | drivers/net/wireless/ath/ath9k/recv.c | 19 +++++++++++-------- | |
26 | 4 files changed, 25 insertions(+), 9 deletions(-) | |
27 | ||
28 | --- a/drivers/net/wireless/ath/ath.h | |
29 | +++ b/drivers/net/wireless/ath/ath.h | |
30 | @@ -119,6 +119,7 @@ struct ath_common { | |
31 | ||
32 | u32 keymax; | |
33 | DECLARE_BITMAP(keymap, ATH_KEYMAX); | |
34 | + DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX); | |
35 | u8 splitmic; | |
36 | ||
37 | struct ath_regulatory regulatory; | |
38 | --- a/drivers/net/wireless/ath/ath9k/common.c | |
39 | +++ b/drivers/net/wireless/ath/ath9k/common.c | |
40 | @@ -366,9 +366,13 @@ int ath9k_cmn_key_config(struct ath_comm | |
41 | set_bit(idx, common->keymap); | |
42 | if (key->alg == ALG_TKIP) { | |
43 | set_bit(idx + 64, common->keymap); | |
44 | + set_bit(idx, common->tkip_keymap); | |
45 | + set_bit(idx + 64, common->tkip_keymap); | |
46 | if (common->splitmic) { | |
47 | set_bit(idx + 32, common->keymap); | |
48 | set_bit(idx + 64 + 32, common->keymap); | |
49 | + set_bit(idx + 32, common->tkip_keymap); | |
50 | + set_bit(idx + 64 + 32, common->tkip_keymap); | |
51 | } | |
52 | } | |
53 | ||
54 | @@ -393,10 +397,17 @@ void ath9k_cmn_key_delete(struct ath_com | |
55 | return; | |
56 | ||
57 | clear_bit(key->hw_key_idx + 64, common->keymap); | |
58 | + | |
59 | + clear_bit(key->hw_key_idx, common->tkip_keymap); | |
60 | + clear_bit(key->hw_key_idx + 64, common->tkip_keymap); | |
61 | + | |
62 | if (common->splitmic) { | |
63 | ath9k_hw_keyreset(ah, key->hw_key_idx + 32); | |
64 | clear_bit(key->hw_key_idx + 32, common->keymap); | |
65 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); | |
66 | + | |
67 | + clear_bit(key->hw_key_idx + 32, common->tkip_keymap); | |
68 | + clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap); | |
69 | } | |
70 | } | |
71 | EXPORT_SYMBOL(ath9k_cmn_key_delete); | |
72 | --- a/drivers/net/wireless/ath/ath9k/mac.c | |
73 | +++ b/drivers/net/wireless/ath/ath9k/mac.c | |
74 | @@ -711,7 +711,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a | |
75 | rs->rs_phyerr = phyerr; | |
76 | } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) | |
77 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | |
78 | - else if (ads.ds_rxstatus8 & AR_MichaelErr) | |
79 | + else if ((ads.ds_rxstatus8 & AR_MichaelErr) && | |
80 | + rs->rs_keyix != ATH9K_RXKEYIX_INVALID) | |
81 | rs->rs_status |= ATH9K_RXERR_MIC; | |
82 | else if (ads.ds_rxstatus8 & AR_KeyMiss) | |
83 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | |
84 | --- a/drivers/net/wireless/ath/ath9k/recv.c | |
85 | +++ b/drivers/net/wireless/ath/ath9k/recv.c | |
86 | @@ -870,15 +870,18 @@ static bool ath9k_rx_accept(struct ath_c | |
87 | if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { | |
88 | *decrypt_error = true; | |
89 | } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { | |
90 | - if (ieee80211_is_ctl(fc)) | |
91 | - /* | |
92 | - * Sometimes, we get invalid | |
93 | - * MIC failures on valid control frames. | |
94 | - * Remove these mic errors. | |
95 | - */ | |
96 | - rx_stats->rs_status &= ~ATH9K_RXERR_MIC; | |
97 | - else | |
98 | + /* | |
99 | + * The MIC error bit is only valid if the frame | |
100 | + * is not a control frame or fragment, and it was | |
101 | + * decrypted using a valid TKIP key. | |
102 | + */ | |
103 | + if (!ieee80211_is_ctl(fc) && | |
104 | + !ieee80211_has_morefrags(fc) && | |
105 | + !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && | |
106 | + test_bit(rx_stats->rs_keyix, common->tkip_keymap)) | |
107 | rxs->flag |= RX_FLAG_MMIC_ERROR; | |
108 | + else | |
109 | + rx_stats->rs_status &= ~ATH9K_RXERR_MIC; | |
110 | } | |
111 | /* | |
112 | * Reject error frames with the exception of |