|
@@ -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;
|
|
}
|
|
}
|