ath9k: move ath9k_rx_accept to common.c
we can reuse it on ath9k_htc Signed-off-by: Oleksij Rempel <linux@rempel-privat.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
1274603646
commit
6438696efa
|
@ -27,6 +27,94 @@ MODULE_AUTHOR("Atheros Communications");
|
||||||
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
|
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
|
|
||||||
|
/* Assumes you've already done the endian to CPU conversion */
|
||||||
|
bool ath9k_cmn_rx_accept(struct ath_common *common,
|
||||||
|
struct ieee80211_hdr *hdr,
|
||||||
|
struct ieee80211_rx_status *rxs,
|
||||||
|
struct ath_rx_status *rx_stats,
|
||||||
|
bool *decrypt_error,
|
||||||
|
unsigned int rxfilter)
|
||||||
|
{
|
||||||
|
struct ath_hw *ah = common->ah;
|
||||||
|
bool is_mc, is_valid_tkip, strip_mic, mic_error;
|
||||||
|
__le16 fc;
|
||||||
|
|
||||||
|
fc = hdr->frame_control;
|
||||||
|
|
||||||
|
is_mc = !!is_multicast_ether_addr(hdr->addr1);
|
||||||
|
is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
|
||||||
|
test_bit(rx_stats->rs_keyix, common->tkip_keymap);
|
||||||
|
strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
|
||||||
|
ieee80211_has_protected(fc) &&
|
||||||
|
!(rx_stats->rs_status &
|
||||||
|
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
|
||||||
|
ATH9K_RXERR_KEYMISS));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Key miss events are only relevant for pairwise keys where the
|
||||||
|
* descriptor does contain a valid key index. This has been observed
|
||||||
|
* mostly with CCMP encryption.
|
||||||
|
*/
|
||||||
|
if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
|
||||||
|
!test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
|
||||||
|
rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
|
||||||
|
|
||||||
|
mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
|
||||||
|
!ieee80211_has_morefrags(fc) &&
|
||||||
|
!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
|
||||||
|
(rx_stats->rs_status & ATH9K_RXERR_MIC);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The rx_stats->rs_status will not be set until the end of the
|
||||||
|
* chained descriptors so it can be ignored if rs_more is set. The
|
||||||
|
* rs_more will be false at the last element of the chained
|
||||||
|
* 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_DECRYPT) ||
|
||||||
|
(!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
|
||||||
|
*decrypt_error = true;
|
||||||
|
mic_error = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reject error frames with the exception of
|
||||||
|
* decryption and MIC failures. For monitor mode,
|
||||||
|
* we also ignore the CRC error.
|
||||||
|
*/
|
||||||
|
status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||||
|
ATH9K_RXERR_KEYMISS;
|
||||||
|
|
||||||
|
if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL))
|
||||||
|
status_mask |= ATH9K_RXERR_CRC;
|
||||||
|
|
||||||
|
if (rx_stats->rs_status & ~status_mask)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For unicast frames the MIC error bit can have false positives,
|
||||||
|
* so all MIC error reports need to be validated in software.
|
||||||
|
* False negatives are not common, so skip software verification
|
||||||
|
* if the hardware considers the MIC valid.
|
||||||
|
*/
|
||||||
|
if (strip_mic)
|
||||||
|
rxs->flag |= RX_FLAG_MMIC_STRIPPED;
|
||||||
|
else if (is_mc && mic_error)
|
||||||
|
rxs->flag |= RX_FLAG_MMIC_ERROR;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ath9k_cmn_rx_accept);
|
||||||
|
|
||||||
int ath9k_cmn_process_rate(struct ath_common *common,
|
int ath9k_cmn_process_rate(struct ath_common *common,
|
||||||
struct ieee80211_hw *hw,
|
struct ieee80211_hw *hw,
|
||||||
struct ath_rx_status *rx_stats,
|
struct ath_rx_status *rx_stats,
|
||||||
|
|
|
@ -42,6 +42,12 @@
|
||||||
#define ATH_EP_RND(x, mul) \
|
#define ATH_EP_RND(x, mul) \
|
||||||
(((x) + ((mul)/2)) / (mul))
|
(((x) + ((mul)/2)) / (mul))
|
||||||
|
|
||||||
|
bool ath9k_cmn_rx_accept(struct ath_common *common,
|
||||||
|
struct ieee80211_hdr *hdr,
|
||||||
|
struct ieee80211_rx_status *rxs,
|
||||||
|
struct ath_rx_status *rx_stats,
|
||||||
|
bool *decrypt_error,
|
||||||
|
unsigned int rxfilter);
|
||||||
int ath9k_cmn_process_rate(struct ath_common *common,
|
int ath9k_cmn_process_rate(struct ath_common *common,
|
||||||
struct ieee80211_hw *hw,
|
struct ieee80211_hw *hw,
|
||||||
struct ath_rx_status *rx_stats,
|
struct ath_rx_status *rx_stats,
|
||||||
|
|
|
@ -755,92 +755,6 @@ static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
|
||||||
return bf;
|
return bf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assumes you've already done the endian to CPU conversion */
|
|
||||||
static bool ath9k_rx_accept(struct ath_common *common,
|
|
||||||
struct ieee80211_hdr *hdr,
|
|
||||||
struct ieee80211_rx_status *rxs,
|
|
||||||
struct ath_rx_status *rx_stats,
|
|
||||||
bool *decrypt_error)
|
|
||||||
{
|
|
||||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
|
||||||
bool is_mc, is_valid_tkip, strip_mic, mic_error;
|
|
||||||
struct ath_hw *ah = common->ah;
|
|
||||||
__le16 fc;
|
|
||||||
|
|
||||||
fc = hdr->frame_control;
|
|
||||||
|
|
||||||
is_mc = !!is_multicast_ether_addr(hdr->addr1);
|
|
||||||
is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
|
|
||||||
test_bit(rx_stats->rs_keyix, common->tkip_keymap);
|
|
||||||
strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
|
|
||||||
ieee80211_has_protected(fc) &&
|
|
||||||
!(rx_stats->rs_status &
|
|
||||||
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
|
|
||||||
ATH9K_RXERR_KEYMISS));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Key miss events are only relevant for pairwise keys where the
|
|
||||||
* descriptor does contain a valid key index. This has been observed
|
|
||||||
* mostly with CCMP encryption.
|
|
||||||
*/
|
|
||||||
if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
|
|
||||||
!test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
|
|
||||||
rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
|
|
||||||
|
|
||||||
mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
|
|
||||||
!ieee80211_has_morefrags(fc) &&
|
|
||||||
!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
|
|
||||||
(rx_stats->rs_status & ATH9K_RXERR_MIC);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The rx_stats->rs_status will not be set until the end of the
|
|
||||||
* chained descriptors so it can be ignored if rs_more is set. The
|
|
||||||
* rs_more will be false at the last element of the chained
|
|
||||||
* 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_DECRYPT) ||
|
|
||||||
(!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
|
|
||||||
*decrypt_error = true;
|
|
||||||
mic_error = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reject error frames with the exception of
|
|
||||||
* decryption and MIC failures. For monitor mode,
|
|
||||||
* we also ignore the CRC error.
|
|
||||||
*/
|
|
||||||
status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
|
||||||
ATH9K_RXERR_KEYMISS;
|
|
||||||
|
|
||||||
if (ah->is_monitoring && (sc->rx.rxfilter & FIF_FCSFAIL))
|
|
||||||
status_mask |= ATH9K_RXERR_CRC;
|
|
||||||
|
|
||||||
if (rx_stats->rs_status & ~status_mask)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For unicast frames the MIC error bit can have false positives,
|
|
||||||
* so all MIC error reports need to be validated in software.
|
|
||||||
* False negatives are not common, so skip software verification
|
|
||||||
* if the hardware considers the MIC valid.
|
|
||||||
*/
|
|
||||||
if (strip_mic)
|
|
||||||
rxs->flag |= RX_FLAG_MMIC_STRIPPED;
|
|
||||||
else if (is_mc && mic_error)
|
|
||||||
rxs->flag |= RX_FLAG_MMIC_ERROR;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ath9k_process_tsf(struct ath_rx_status *rs,
|
static void ath9k_process_tsf(struct ath_rx_status *rs,
|
||||||
struct ieee80211_rx_status *rxs,
|
struct ieee80211_rx_status *rxs,
|
||||||
u64 tsf)
|
u64 tsf)
|
||||||
|
@ -939,7 +853,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
||||||
* everything but the rate is checked here, the rate check is done
|
* everything but the rate is checked here, the rate check is done
|
||||||
* separately to avoid doing two lookups for a rate for each frame.
|
* separately to avoid doing two lookups for a rate for each frame.
|
||||||
*/
|
*/
|
||||||
if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
|
if (!ath9k_cmn_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error, sc->rx.rxfilter)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue