Skip to content

Commit

Permalink
ath9k_hw: fix a regression in key miss handling
Browse files Browse the repository at this point in the history
The commit "ath9k_hw: Fix incorrect key_miss handling" changed the code
to only report key miss errors if a MIC error wasn't reported.
When checking the flags in that order in the MAC code, it might miss some
real events, because the value of the MIC error flag is undefined under
some conditions.

The primary issue addressed by the previous commit is making sure that
MIC errors are properly reported on the STA side. This can be fixed in
a better way by adding a separate rx status flag for key miss and
ignoring it for multicast frames.

This fix slightly improves stability in AP mode on some older hardware,
like AR9132.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: stable@kernel.org
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Felix Fietkau authored and John W. Linville committed Oct 11, 2011
1 parent 1b428a2 commit 846d936
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 17 deletions.
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/ath9k/ar9003_mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,8 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (rxsp->status11 & AR_MichaelErr)
rxs->rs_status |= ATH9K_RXERR_MIC;
else if (rxsp->status11 & AR_KeyMiss)
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
if (rxsp->status11 & AR_KeyMiss)
rxs->rs_status |= ATH9K_RXERR_KEYMISS;
}

return 0;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/ath9k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr)
rs->rs_status |= ATH9K_RXERR_MIC;
else if (ads.ds_rxstatus8 & AR_KeyMiss)
rs->rs_status |= ATH9K_RXERR_DECRYPT;
if (ads.ds_rxstatus8 & AR_KeyMiss)
rs->rs_status |= ATH9K_RXERR_KEYMISS;
}

return 0;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath9k/mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ struct ath_htc_rx_status {
#define ATH9K_RXERR_FIFO 0x04
#define ATH9K_RXERR_DECRYPT 0x08
#define ATH9K_RXERR_MIC 0x10
#define ATH9K_RXERR_KEYMISS 0x20

#define ATH9K_RX_MORE 0x01
#define ATH9K_RX_MORE_AGGR 0x02
Expand Down
27 changes: 14 additions & 13 deletions drivers/net/wireless/ath/ath9k/recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,8 @@ static bool ath9k_rx_accept(struct ath_common *common,
test_bit(rx_stats->rs_keyix, common->tkip_keymap);
strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
!(rx_stats->rs_status &
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
ATH9K_RXERR_KEYMISS));

if (!rx_stats->rs_datalen)
return false;
Expand Down Expand Up @@ -848,14 +849,17 @@ static bool ath9k_rx_accept(struct ath_common *common,
* descriptors.
*/
if (rx_stats->rs_status != 0) {
u8 status_mask;

if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
mic_error = false;
}
if (rx_stats->rs_status & ATH9K_RXERR_PHY)
return false;

if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
(!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
*decrypt_error = true;
mic_error = false;
}
Expand All @@ -865,17 +869,14 @@ static bool ath9k_rx_accept(struct ath_common *common,
* decryption and MIC failures. For monitor mode,
* we also ignore the CRC error.
*/
if (ah->is_monitoring) {
if (rx_stats->rs_status &
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
ATH9K_RXERR_CRC))
return false;
} else {
if (rx_stats->rs_status &
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
return false;
}
}
status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
ATH9K_RXERR_KEYMISS;

if (ah->is_monitoring)
status_mask |= ATH9K_RXERR_CRC;

if (rx_stats->rs_status & ~status_mask)
return false;
}

/*
Expand Down

0 comments on commit 846d936

Please sign in to comment.