aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2010-07-14 20:08:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-16 14:03:42 -0400
commit9171acc7e094b3ca88e624f39891a4f3bf9d083c (patch)
tree513857338301a5f04cc07ddae89d19ee9ae4b44a /drivers
parent15804e3e9de52f1baefad34233424488b5672853 (diff)
ath9k_hw: Fix AR9003 MPDU delimeter CRC check for middle subframes
An A-MPDU may contain several subframes each containing its own CRC for the data. Each subframe also has a respective CRC for the MPDU length and 4 reserved bits (aka delimeter CRC). AR9003 will ACK frames that have a valid data CRC but have failed to pass the CRC for the MPDU length, if and only if the subframe is not the last subframe in an A-MPDU and if an OFDM phy OFDM reset error has been caught. Discarding those subframes results in packet loss under heavy stress conditions, an example being UDP video. Since the frames are ACK'd by hardware we need to let these frames through and process them as valid frames. Cc: Tushit Jain <tushit.jain@atheros.com> Cc: Kyungwan Nam <kyungwan.nam@atheros.com> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 06ef71019c12..5b995bee70ae 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -579,12 +579,39 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
579 rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; 579 rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
580 580
581 if ((rxsp->status11 & AR_RxFrameOK) == 0) { 581 if ((rxsp->status11 & AR_RxFrameOK) == 0) {
582 /*
583 * AR_CRCErr will bet set to true if we're on the last
584 * subframe and the AR_PostDelimCRCErr is caught.
585 * In a way this also gives us a guarantee that when
586 * (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot
587 * possibly be reviewing the last subframe. AR_CRCErr
588 * is the CRC of the actual data.
589 */
582 if (rxsp->status11 & AR_CRCErr) { 590 if (rxsp->status11 & AR_CRCErr) {
583 rxs->rs_status |= ATH9K_RXERR_CRC; 591 rxs->rs_status |= ATH9K_RXERR_CRC;
584 } else if (rxsp->status11 & AR_PHYErr) { 592 } else if (rxsp->status11 & AR_PHYErr) {
585 rxs->rs_status |= ATH9K_RXERR_PHY;
586 phyerr = MS(rxsp->status11, AR_PHYErrCode); 593 phyerr = MS(rxsp->status11, AR_PHYErrCode);
587 rxs->rs_phyerr = phyerr; 594 /*
595 * If we reach a point here where AR_PostDelimCRCErr is
596 * true it implies we're *not* on the last subframe. In
597 * in that case that we know already that the CRC of
598 * the frame was OK, and MAC would send an ACK for that
599 * subframe, even if we did get a phy error of type
600 * ATH9K_PHYERR_OFDM_RESTART. This is only applicable
601 * to frame that are prior to the last subframe.
602 * The AR_PostDelimCRCErr is the CRC for the MPDU
603 * delimiter, which contains the 4 reserved bits,
604 * the MPDU length (12 bits), and follows the MPDU
605 * delimiter for an A-MPDU subframe (0x4E = 'N' ASCII).
606 */
607 if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) &&
608 (rxsp->status11 & AR_PostDelimCRCErr)) {
609 rxs->rs_phyerr = 0;
610 } else {
611 rxs->rs_status |= ATH9K_RXERR_PHY;
612 rxs->rs_phyerr = phyerr;
613 }
614
588 } else if (rxsp->status11 & AR_DecryptCRCErr) { 615 } else if (rxsp->status11 & AR_DecryptCRCErr) {
589 rxs->rs_status |= ATH9K_RXERR_DECRYPT; 616 rxs->rs_status |= ATH9K_RXERR_DECRYPT;
590 } else if (rxsp->status11 & AR_MichaelErr) { 617 } else if (rxsp->status11 & AR_MichaelErr) {