aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2013-04-07 18:04:12 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-10 14:10:33 -0400
commit3747c3eef6df9bf936fc571ab64122e651db6137 (patch)
tree21a031787be78b7cc9e883355e96526e67bcd5dc
parent723e711356b5a8a95728a890e254e8b0d47b55cf (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.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c2
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);