From 1abaf2bb2521dbbf7bfa351a4d1f92d831c5d79e Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Sat, 17 Sep 2011 08:34:37 +0000
Subject: ath9k: fix a regression in handling of MAC key miss events (should
 improve connection stability)

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@28250 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../patches/551-ath9k_fix_keymiss_handling.patch   | 83 ++++++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 package/mac80211/patches/551-ath9k_fix_keymiss_handling.patch

(limited to 'package/mac80211/patches')

diff --git a/package/mac80211/patches/551-ath9k_fix_keymiss_handling.patch b/package/mac80211/patches/551-ath9k_fix_keymiss_handling.patch
new file mode 100644
index 0000000000..66ea9a7c01
--- /dev/null
+++ b/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;
+ 	}
+ 
+ 	/*
-- 
cgit v1.2.3