diff options
author | Felix Fietkau <nbd@openwrt.org> | 2013-04-07 18:04:12 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-10 14:10:33 -0400 |
commit | 3747c3eef6df9bf936fc571ab64122e651db6137 (patch) | |
tree | 21a031787be78b7cc9e883355e96526e67bcd5dc | |
parent | 723e711356b5a8a95728a890e254e8b0d47b55cf (diff) |
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: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 2 |
3 files changed, 11 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 811007ec07a7..498fee04afa0 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -615,6 +615,14 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
615 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | 615 | rs->rs_status |= ATH9K_RXERR_DECRYPT; |
616 | else if (ads.ds_rxstatus8 & AR_MichaelErr) | 616 | else if (ads.ds_rxstatus8 & AR_MichaelErr) |
617 | rs->rs_status |= ATH9K_RXERR_MIC; | 617 | rs->rs_status |= ATH9K_RXERR_MIC; |
618 | } else { | ||
619 | if (ads.ds_rxstatus8 & | ||
620 | (AR_CRCErr | AR_PHYErr | AR_DecryptCRCErr | AR_MichaelErr)) | ||
621 | rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC; | ||
622 | |||
623 | /* Only up to MCS16 supported, everything above is invalid */ | ||
624 | if (rs->rs_rate >= 0x90) | ||
625 | rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC; | ||
618 | } | 626 | } |
619 | 627 | ||
620 | if (ads.ds_rxstatus8 & AR_KeyMiss) | 628 | if (ads.ds_rxstatus8 & AR_KeyMiss) |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 1ff817061ebc..5865f92998e1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -183,6 +183,7 @@ struct ath_htc_rx_status { | |||
183 | #define ATH9K_RXERR_DECRYPT 0x08 | 183 | #define ATH9K_RXERR_DECRYPT 0x08 |
184 | #define ATH9K_RXERR_MIC 0x10 | 184 | #define ATH9K_RXERR_MIC 0x10 |
185 | #define ATH9K_RXERR_KEYMISS 0x20 | 185 | #define ATH9K_RXERR_KEYMISS 0x20 |
186 | #define ATH9K_RXERR_CORRUPT_DESC 0x40 | ||
186 | 187 | ||
187 | #define ATH9K_RX_MORE 0x01 | 188 | #define ATH9K_RX_MORE 0x01 |
188 | #define ATH9K_RX_MORE_AGGR 0x02 | 189 | #define ATH9K_RX_MORE_AGGR 0x02 |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index c593a3e0cd95..ebb8d361b981 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -1319,6 +1319,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1319 | sc->rx.frag = skb; | 1319 | sc->rx.frag = skb; |
1320 | goto requeue; | 1320 | goto requeue; |
1321 | } | 1321 | } |
1322 | if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC) | ||
1323 | goto requeue_drop_frag; | ||
1322 | 1324 | ||
1323 | if (sc->rx.frag) { | 1325 | if (sc->rx.frag) { |
1324 | int space = skb->len - skb_tailroom(hdr_skb); | 1326 | int space = skb->len - skb_tailroom(hdr_skb); |