Browse Source

ath9k: fix a regression in handling of MAC key miss events (should improve connection stability)

SVN-Revision: 28250
Felix Fietkau 14 years ago
parent
commit
0e9e83047d
1 changed files with 83 additions and 0 deletions
  1. 83 0
      package/mac80211/patches/551-ath9k_fix_keymiss_handling.patch

+ 83 - 0
package/mac80211/patches/551-ath9k_fix_keymiss_handling.patch

@@ -0,0 +1,83 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -525,8 +525,8 @@ int ath9k_hw_process_rxdesc_edma(struct 
+ 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
+ 		else if (rxsp->status11 & AR_MichaelErr)
+ 			rxs->rs_status |= ATH9K_RXERR_MIC;
+-		else if (rxsp->status11 & AR_KeyMiss)
+-			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
++		if (rxsp->status11 & AR_KeyMiss)
++			rxs->rs_status |= ATH9K_RXERR_KEYMISS;
+ 	}
+ 
+ 	return 0;
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -620,8 +620,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+ 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
+ 		else if (ads.ds_rxstatus8 & AR_MichaelErr)
+ 			rs->rs_status |= ATH9K_RXERR_MIC;
+-		else if (ads.ds_rxstatus8 & AR_KeyMiss)
+-			rs->rs_status |= ATH9K_RXERR_DECRYPT;
++		if (ads.ds_rxstatus8 & AR_KeyMiss)
++			rs->rs_status |= ATH9K_RXERR_KEYMISS;
+ 	}
+ 
+ 	return 0;
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -181,6 +181,7 @@ struct ath_htc_rx_status {
+ #define ATH9K_RXERR_FIFO          0x04
+ #define ATH9K_RXERR_DECRYPT       0x08
+ #define ATH9K_RXERR_MIC           0x10
++#define ATH9K_RXERR_KEYMISS       0x20
+ 
+ #define ATH9K_RX_MORE             0x01
+ #define ATH9K_RX_MORE_AGGR        0x02
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -854,6 +854,8 @@ static bool ath9k_rx_accept(struct ath_c
+ 	 * 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;
+@@ -861,7 +863,8 @@ static bool ath9k_rx_accept(struct ath_c
+ 		if (rx_stats->rs_status & ATH9K_RXERR_PHY)
+ 			return false;
+ 
+-		if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
++		if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
++		    (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
+ 			*decrypt_error = true;
+ 			mic_error = false;
+ 		}
+@@ -871,17 +874,14 @@ static bool ath9k_rx_accept(struct ath_c
+ 		 * decryption and MIC failures. For monitor mode,
+ 		 * we also ignore the CRC error.
+ 		 */
+-		if (ah->is_monitoring) {
+-			if (rx_stats->rs_status &
+-			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+-			      ATH9K_RXERR_CRC))
+-				return false;
+-		} else {
+-			if (rx_stats->rs_status &
+-			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
+-				return false;
+-			}
+-		}
++		status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
++			      ATH9K_RXERR_KEYMISS;
++
++		if (ah->is_monitoring)
++			status_mask |= ATH9K_RXERR_CRC;
++
++		if (rx_stats->rs_status & ~status_mask)
++			return false;
+ 	}
+ 
+ 	/*