ath9k: fix spurious MIC failure reports
PATCH 1/1 ath9k: fix spurious MIC failure reports
According to the hardware documentation, the MIC failure bit is only valid if the frame was decrypted using a valid TKIP key and is not a fragment.
In some setups I've seen hardware-reported MIC failures on an AP that was configured for CCMP only, so it's clear that additional checks are necessary.
Signed-off-by Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath.h +1 -0
@@ -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;
drivers/net/wireless/ath/ath9k/common.c +11 -0
@@ -366,9 +366,13 @@ int ath9k_cmn_key_config(struct ath_commset_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_comreturn ;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);
drivers/net/wireless/ath/ath9k/recv.c +11 -8
@@ -870,15 +870,18 @@ static bool ath9k_rx_accept(struct ath_cif (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 or fragment, and it was +* decrypted using a valid TKIP key. +*/ +if (!ieee80211_is_ctl (fc) && + !ieee80211_has_morefrags (fc) && + !(le16_to_cpu (hdr->seq_ctrl) &IEEE80211_SCTL_FRAG ) && +test_bit (rx_stats->rs_keyix, common->tkip_keymap)) rxs->flag |=RX_FLAG_MMIC_ERROR ; +else + rx_stats->rs_status &= ~ATH9K_RXERR_MIC ; }/* * Reject error frames with the exception of
drivers/net/wireless/ath/ath9k/mac.c +2 -1
@@ -711,7 +711,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a rs->rs_phyerr = phyerr; }else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) rs->rs_status |=ATH9K_RXERR_DECRYPT ; -else if (ads.ds_rxstatus8 & AR_MichaelErr) +else if ((ads.ds_rxstatus8 & AR_MichaelErr) && + rs->rs_keyix !=ATH9K_RXKEYIX_INVALID ) rs->rs_status |=ATH9K_RXERR_MIC ;else if (ads.ds_rxstatus8 & AR_KeyMiss) rs->rs_status |=ATH9K_RXERR_DECRYPT ;