ath9k: fix a regression in handling of MAC key miss events (should improve connection...
authorFelix Fietkau <nbd@openwrt.org>
Sat, 17 Sep 2011 08:34:37 +0000 (08:34 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 17 Sep 2011 08:34:37 +0000 (08:34 +0000)
SVN-Revision: 28250

package/mac80211/patches/551-ath9k_fix_keymiss_handling.patch [new file with mode: 0644]

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 (file)
index 0000000..66ea9a7
--- /dev/null
@@ -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;
+       }
+       /*