Commit 3747c3ee authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

ath9k: detect more kinds of invalid descriptors

If AR_CRCErr, AR_PHYErr, AR_DecryptCRCErr or AR_MichaelErr is indicated
in the rx status word, but AR_RxFrameOK is also set, the descriptor
contents are typically invalid. This can show up as a warning about
invalid MCS rates in a frame. Even with those checks in place, a
descriptor with invalid MCS rates can still sometimes make it through to
the driver (mostly on older hardware like AR91xx).

Detect such errors in the last descriptor of a frame and discard the
whole frame if present.
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 723e7113
...@@ -615,6 +615,14 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, ...@@ -615,6 +615,14 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_status |= ATH9K_RXERR_DECRYPT; rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr) else if (ads.ds_rxstatus8 & AR_MichaelErr)
rs->rs_status |= ATH9K_RXERR_MIC; rs->rs_status |= ATH9K_RXERR_MIC;
} else {
if (ads.ds_rxstatus8 &
(AR_CRCErr | AR_PHYErr | AR_DecryptCRCErr | AR_MichaelErr))
rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
/* Only up to MCS16 supported, everything above is invalid */
if (rs->rs_rate >= 0x90)
rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
} }
if (ads.ds_rxstatus8 & AR_KeyMiss) if (ads.ds_rxstatus8 & AR_KeyMiss)
......
...@@ -183,6 +183,7 @@ struct ath_htc_rx_status { ...@@ -183,6 +183,7 @@ struct ath_htc_rx_status {
#define ATH9K_RXERR_DECRYPT 0x08 #define ATH9K_RXERR_DECRYPT 0x08
#define ATH9K_RXERR_MIC 0x10 #define ATH9K_RXERR_MIC 0x10
#define ATH9K_RXERR_KEYMISS 0x20 #define ATH9K_RXERR_KEYMISS 0x20
#define ATH9K_RXERR_CORRUPT_DESC 0x40
#define ATH9K_RX_MORE 0x01 #define ATH9K_RX_MORE 0x01
#define ATH9K_RX_MORE_AGGR 0x02 #define ATH9K_RX_MORE_AGGR 0x02
......
...@@ -1319,6 +1319,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1319,6 +1319,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.frag = skb; sc->rx.frag = skb;
goto requeue; goto requeue;
} }
if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC)
goto requeue_drop_frag;
if (sc->rx.frag) { if (sc->rx.frag) {
int space = skb->len - skb_tailroom(hdr_skb); int space = skb->len - skb_tailroom(hdr_skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment