--- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -119,6 +119,7 @@ struct ath_common { u32 keymax; DECLARE_BITMAP(keymap, ATH_KEYMAX); + DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX); u8 splitmic; struct ath_regulatory regulatory; --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -366,9 +366,13 @@ int ath9k_cmn_key_config(struct ath_comm set_bit(idx, common->keymap); if (key->alg == ALG_TKIP) { set_bit(idx + 64, common->keymap); + set_bit(idx, common->tkip_keymap); + set_bit(idx + 64, common->tkip_keymap); if (common->splitmic) { set_bit(idx + 32, common->keymap); set_bit(idx + 64 + 32, common->keymap); + set_bit(idx + 32, common->tkip_keymap); + set_bit(idx + 64 + 32, common->tkip_keymap); } } @@ -393,10 +397,17 @@ void ath9k_cmn_key_delete(struct ath_com return; clear_bit(key->hw_key_idx + 64, common->keymap); + + clear_bit(key->hw_key_idx, common->tkip_keymap); + clear_bit(key->hw_key_idx + 64, common->tkip_keymap); + if (common->splitmic) { ath9k_hw_keyreset(ah, key->hw_key_idx + 32); clear_bit(key->hw_key_idx + 32, common->keymap); clear_bit(key->hw_key_idx + 64 + 32, common->keymap); + + clear_bit(key->hw_key_idx + 32, common->tkip_keymap); + clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap); } } EXPORT_SYMBOL(ath9k_cmn_key_delete); --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -870,15 +870,19 @@ static bool ath9k_rx_accept(struct ath_c if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { *decrypt_error = true; } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { - if (ieee80211_is_ctl(fc)) - /* - * Sometimes, we get invalid - * MIC failures on valid control frames. - * Remove these mic errors. - */ - rx_stats->rs_status &= ~ATH9K_RXERR_MIC; - else + /* + * The MIC error bit is only valid if the frame + * is not a control frame, and it was decrypted using + * a TKIP key. + */ + if (!ieee80211_is_ctl(fc) && + rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && + test_bit(rx_stats->rs_keyix, common->tkip_keymap)) { rxs->flag |= RX_FLAG_MMIC_ERROR; + } else { + rx_stats->rs_status &= ~ATH9K_RXERR_MIC; + *decrypt_error = true; + } } /* * Reject error frames with the exception of