mac80211: update to wireless-testing 2014-05-22
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
index ef81721529eee36aa5faa2a55a14cd6d887d177f..0a2e86b1d7bc2f539b84d4b4a23ec5a1eb413ec9 100644 (file)
-commit 230ab8c1880266c9cfceac962e2d48309dea79a7
+commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
 Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Mon May 19 21:48:56 2014 +0200
+Date:   Fri May 23 19:58:14 2014 +0200
 
-    ath9k: re-schedule rx processing after budget exceeded
+    mac80211: reduce packet loss notifications under load
     
-    Should improve rx stability under load
+    During strong signal fluctuations under high throughput, few consecutive
+    failed A-MPDU transmissions can easily trigger packet loss notification,
+    and thus (in AP mode) client disconnection.
     
-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 27647baeaee1b12bc3c57ccf1c7eba53bcd7fe53
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Mon May 19 21:20:49 2014 +0200
-
-    ath9k: avoid passing buffers to the hardware during flush
-    
-    The commit "ath9k: fix possible hang on flush" changed the receive code
-    to always link rx descriptors of processed frames, even when flushing.
-    In some cases, this leads to flushed rx buffers being passed to the
-    hardware while rx is already stopped.
+    Reduce the number of false positives by checking the A-MPDU status flag
+    and treating a failed A-MPDU as a single packet.
     
     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit 92e9dd662542683856e62a5e7e43fcf5b9da5c4a
-Author: Henning Rogge <hrogge@gmail.com>
-Date:   Thu May 1 10:03:46 2014 +0200
-
-    mac80211: Fix mac80211 station info rx bitrate for IBSS mode
-    
-    Filter out incoming multicast packages before applying their bitrate
-    to the rx bitrate station info field to prevent them from setting the
-    rx bitrate to the basic multicast rate.
-    
-    Signed-off-by: Henning Rogge <hrogge@gmail.com>
-
-commit 4c8a3486cb577d40c1ef75f0a8dc9a04773eef83
-Author: Nickolay Ledovskikh <nledovskikh@gmail.com>
-Date:   Fri Apr 25 22:53:34 2014 +0400
-
-    ath5k: Fix AR5K_PHY_TXPOWER_RATE_MAX register value setting.
-    
-    I was reading ath5k power setting code and
-    noticed typing error in ath5k_hw_txpower function.
-    Invalid value was written to AR5K_PHY_TXPOWER_RATE_MAX
-    register.
-    
-    Signed-off-by: Nikolay Ledovskikh <nledovskikh@gmail.com>
-    Acked-by: Nick Kossifidis <mickflemm@gmail.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
-
-commit 4d76248013dbb1948429555208900a585b0f351d
-Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-Date:   Tue Apr 8 13:38:43 2014 +0200
-
-    ath9k: Enable DFS only when ATH9K_DFS_CERTIFIED
-    
-    Add DFS interface combination only when
-    CONFIG_ATH9K_DFS_CERTIFIED is set. In other case
-    user can run CAC/beaconing without proper handling
-    of pulse events (without radar detection activated).
-    
-    Reported-by: Cedric Voncken <cedric.voncken@acksys.fr>
-    Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
-
-commit c83a4e5156a4b4dd22137d33a5625440982d6d37
-Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-Date:   Mon Apr 28 21:17:08 2014 +0530
-
-    ath9k_hw: fix worse EVM for 11b rates
-    
-    Adjust FIR filter co-efficients to improve EVM for 11b rates.
-    
-    Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
-
-commit 8aab2c7a2f4a957e344db429dfb1190ae59ce8b5
-Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-Date:   Mon Apr 28 21:17:07 2014 +0530
-
-    ath9k_hw: update ar9300 initvals
-    
-     * rfsat gainchange hysteresis of rf_gain stuck with large
-       interference present.
-    
-    Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
-
-commit 8c7ae357cc5b6bd037ad2d666e9f3789cf882925
-Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-Date:   Wed Apr 23 15:07:57 2014 +0530
-
-    ath9k: fix race in setting ATH_OP_INVALID
-    
-    The commit "ath9k: move sc_flags to ath_common" moved setting
-    ATH_OP_INVALID flag below ieee80211_register_hw. This is causing
-    the flag never being cleared randomly as the drv_start is called
-    prior to setting flag. Fix this by setting the flag prior to
-    register_hw.
-    
-    Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
-
-commit c82552c5b0cb1735dbcbad78b1ffc6d3c212dc56
-Author: Tim Harvey <tharvey@gateworks.com>
-Date:   Mon Apr 21 16:14:57 2014 -0700
-
-    ath9k: add a recv budget
-    
-    Implement a recv budget so that in cases of high traffic we still allow other
-    taskets to get processed.
-    
-    Without this, we can encounter a host of issues during high wireless traffic
-    reception depending on system load including rcu stall's detected (ARM),
-    soft lockups, failure to service critical tasks such as watchdog resets,
-    and triggering of the tx stuck tasklet.
-    
-    The same thing was proposed previously by Ben:
-     http://www.spinics.net/lists/linux-wireless/msg112891.html
-    
-    The only difference here is that I make sure only processed packets are counted
-    in the budget by checking at the end of the rx loop.
-    
-    Signed-off-by: Tim Harvey <tharvey@gateworks.com>
-    Acked-by: Felix Fietkau <nbd@openwrt.org>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
-
-commit 3a758134e66ca74a9df792616b5288b2fa2cfd7f
-Author: Tim Harvey <tharvey@gateworks.com>
-Date:   Mon Apr 21 16:14:56 2014 -0700
-
-    ath9k: fix possible hang on flush
-    
-    If a flush is requested, make sure to clear the descriptor once we've
-    processed it.
-    
-    This resolves a hang that will occur if all RX descriptors are full when a
-    flush is requested.
-    
-    Signed-off-by: Tim Harvey <tharvey@gateworks.com>
-    Acked-by: Felix Fietkau <nbd@openwrt.org>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
-
-commit eefb1d6adc4c60d219182b8917e4567484ce07fc
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Mon Apr 28 18:27:41 2014 +0200
-
-    ath9k: remove tid->paused flag
-    
-    There are some corner cases where the driver could get stuck with a full
-    tid queue that is paused, leading to a software tx queue hang.
-    
-    Since the tx queueing rework, pausing per-tid queues on aggregation
-    session setup is no longer necessary. The driver will assign sequence
-    numbers to buffered frames when a new session is established, in order
-    to get the correct starting sequence number.
-    
-    mac80211 prevents new frames from entering the queue during setup.
-    
-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 98a713933d8495f4078f561c1e651b738dd5b531
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Sun Apr 27 14:49:03 2014 +0200
-
-    ath9k_hw: do not lower ANI setting below default on AR913x
-    
-    When the amount of noise fluctuates strongly, low immunity settings
-    can sometimes disrupt signal detection on AR913x chips. When that
-    happens, no OFDM/CCK errors are reported anymore, and ANI tunes the
-    radio to the lowest immunity settings.
-    Usually rx/tx fails as well in that case.
-    
-    To fix this, keep noise immunity settings at or above ANI default level,
-    which will keep radio parameters at or above INI values.
-    
-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 7cbb4c021bfd1e656f5b9953a947ab3c64e4e3b0
+commit 7b7843a36fbcc568834404c7430ff895d8502131
 Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Thu Apr 10 10:49:01 2014 +0200
+Date:   Fri May 23 19:26:32 2014 +0200
 
-    mac80211: exclude AP_VLAN interfaces from tx power calculation
-    
-    Their power value is initialized to zero. This patch fixes an issue
-    where the configured power drops to the minimum value when AP_VLAN
-    interfaces are created/removed.
+    mac80211: fix a memory leak on sta rate selection table
     
     Cc: stable@vger.kernel.org
+    Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit 0ca13e26341733bf9577287fb04a3bef0d2f5cc9
+commit 96892d6aa0a153423070addf3070bc79578b3897
 Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Wed Apr 9 00:07:01 2014 +0200
-
-    mac80211: suppress BSS info change notifications for AP_VLAN
-    
-    Fixes warnings on tx power changes
-    
-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit ec998e5991781ecdaad0911dc64f1c8d3749c308
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Tue Apr 8 23:42:17 2014 +0200
-
-    ath9k: fix a scheduling while atomic bug in CSA handling
-    
-    Commit "ath9k: prepare for multi-interface CSA support" added a call to
-    ieee80211_iterate_active_interfaces in atomic context (beacon tasklet),
-    which is crashing.
-    Use ieee80211_iterate_active_interfaces_atomic instead.
-    
-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Sun Apr 6 23:35:28 2014 +0200
+Date:   Mon May 19 21:20:49 2014 +0200
 
-    ath9k_hw: reduce ANI firstep range for older chips
+    ath9k: avoid passing buffers to the hardware during flush
     
-    Use 0-8 instead of 0-16, which is closer to the old implementation.
-    Also drop the overwrite of the firstep_low parameter to improve
-    stability.
+    The commit "ath9k: fix possible hang on flush" changed the receive code
+    to always link rx descriptors of processed frames, even when flushing.
+    In some cases, this leads to flushed rx buffers being passed to the
+    hardware while rx is already stopped.
     
     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-
---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-@@ -1004,11 +1004,9 @@ static bool ar5008_hw_ani_control_new(st
-       case ATH9K_ANI_FIRSTEP_LEVEL:{
-               u32 level = param;
--              value = level * 2;
-+              value = level;
-               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
-                             AR_PHY_FIND_SIG_FIRSTEP, value);
--              REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
--                            AR_PHY_FIND_SIG_FIRSTEP_LOW, value);
-               if (level != aniState->firstepLevel) {
-                       ath_dbg(common, ANI,
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -312,10 +312,9 @@ static void ath9k_csa_update_vif(void *d
- void ath9k_csa_update(struct ath_softc *sc)
- {
--      ieee80211_iterate_active_interfaces(sc->hw,
--                                          IEEE80211_IFACE_ITER_NORMAL,
--                                          ath9k_csa_update_vif,
--                                          sc);
-+      ieee80211_iterate_active_interfaces_atomic(sc->hw,
-+                                                 IEEE80211_IFACE_ITER_NORMAL,
-+                                                 ath9k_csa_update_vif, sc);
- }
- void ath9k_beacon_tasklet(unsigned long data)
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -152,6 +152,8 @@ static u32 ieee80211_hw_conf_chan(struct
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-               if (!rcu_access_pointer(sdata->vif.chanctx_conf))
-                       continue;
-+              if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-+                      continue;
-               power = min(power, sdata->vif.bss_conf.txpower);
-       }
-       rcu_read_unlock();
-@@ -203,7 +205,7 @@ void ieee80211_bss_info_change_notify(st
- {
-       struct ieee80211_local *local = sdata->local;
--      if (!changed)
-+      if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-               return;
-       drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
---- a/drivers/net/wireless/ath/ath9k/ani.c
-+++ b/drivers/net/wireless/ath/ath9k/ani.c
-@@ -155,6 +155,9 @@ static void ath9k_hw_set_ofdm_nil(struct
-               ATH9K_ANI_RSSI_THR_LOW,
-               ATH9K_ANI_RSSI_THR_HIGH);
-+      if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL)
-+              immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
-+
-       if (!scan)
-               aniState->ofdmNoiseImmunityLevel = immunityLevel;
-@@ -235,6 +238,9 @@ static void ath9k_hw_set_cck_nil(struct 
-               BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
-               ATH9K_ANI_RSSI_THR_HIGH);
-+      if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL)
-+              immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
-+
-       if (ah->opmode == NL80211_IFTYPE_STATION &&
-           BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
-           immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -251,7 +251,6 @@ struct ath_atx_tid {
-       s8 bar_index;
-       bool sched;
--      bool paused;
-       bool active;
- };
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -107,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_
- {
-       struct ath_atx_ac *ac = tid->ac;
--      if (tid->paused)
--              return;
--
-       if (tid->sched)
-               return;
-@@ -1407,7 +1404,6 @@ int ath_tx_aggr_start(struct ath_softc *
-       ath_tx_tid_change_state(sc, txtid);
-       txtid->active = true;
--      txtid->paused = true;
-       *ssn = txtid->seq_start = txtid->seq_next;
-       txtid->bar_index = -1;
-@@ -1427,7 +1423,6 @@ void ath_tx_aggr_stop(struct ath_softc *
-       ath_txq_lock(sc, txq);
-       txtid->active = false;
--      txtid->paused = false;
-       ath_tx_flush_tid(sc, txtid);
-       ath_tx_tid_change_state(sc, txtid);
-       ath_txq_unlock_complete(sc, txq);
-@@ -1487,7 +1482,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
-               ath_txq_lock(sc, txq);
-               ac->clear_ps_filter = true;
--              if (!tid->paused && ath_tid_has_buffered(tid)) {
-+              if (ath_tid_has_buffered(tid)) {
-                       ath_tx_queue_tid(txq, tid);
-                       ath_txq_schedule(sc, txq);
-               }
-@@ -1510,7 +1505,6 @@ void ath_tx_aggr_resume(struct ath_softc
-       ath_txq_lock(sc, txq);
-       tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
--      tid->paused = false;
-       if (ath_tid_has_buffered(tid)) {
-               ath_tx_queue_tid(txq, tid);
-@@ -1544,8 +1538,6 @@ void ath9k_release_buffered_frames(struc
-                       continue;
-               tid = ATH_AN_2_TID(an, i);
--              if (tid->paused)
--                      continue;
-               ath_txq_lock(sc, tid->ac->txq);
-               while (nframes > 0) {
-@@ -1844,9 +1836,6 @@ void ath_txq_schedule(struct ath_softc *
-                       list_del(&tid->list);
-                       tid->sched = false;
--                      if (tid->paused)
--                              continue;
--
-                       if (ath_tx_sched_aggr(sc, txq, tid, &stop))
-                               sent = true;
-@@ -2698,7 +2687,6 @@ void ath_tx_node_init(struct ath_softc *
-               tid->baw_size  = WME_MAX_BA;
-               tid->baw_head  = tid->baw_tail = 0;
-               tid->sched     = false;
--              tid->paused    = false;
-               tid->active        = false;
-               __skb_queue_head_init(&tid->buf_q);
-               __skb_queue_head_init(&tid->retry_q);
 --- a/drivers/net/wireless/ath/ath9k/recv.c
 +++ b/drivers/net/wireless/ath/ath9k/recv.c
 @@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
@@ -417,35 +73,7 @@ Date:   Sun Apr 6 23:35:28 2014 +0200
  
        sc->rx.buf_hold = bf;
  }
-@@ -106,7 +108,7 @@ static void ath_opmode_init(struct ath_s
- }
- static bool ath_rx_edma_buf_link(struct ath_softc *sc,
--                               enum ath9k_rx_qtype qtype)
-+                               enum ath9k_rx_qtype qtype, bool flush)
- {
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_rx_edma *rx_edma;
-@@ -127,7 +129,8 @@ static bool ath_rx_edma_buf_link(struct 
-                               ah->caps.rx_status_len, DMA_TO_DEVICE);
-       SKB_CB_ATHBUF(skb) = bf;
--      ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype);
-+      if (!flush)
-+              ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype);
-       __skb_queue_tail(&rx_edma->rx_fifo, skb);
-       return true;
-@@ -145,7 +148,7 @@ static void ath_rx_addbuffer_edma(struct
-       }
-       list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list)
--              if (!ath_rx_edma_buf_link(sc, qtype))
-+              if (!ath_rx_edma_buf_link(sc, qtype, false))
-                       break;
- }
-@@ -442,7 +445,7 @@ int ath_startrecv(struct ath_softc *sc)
+@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
        sc->rx.buf_hold = NULL;
        sc->rx.rxlink = NULL;
        list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
@@ -454,282 +82,82 @@ Date:   Sun Apr 6 23:35:28 2014 +0200
        }
  
        /* We could have deleted elements so the list may be empty now */
-@@ -636,7 +639,7 @@ static bool ath_edma_get_buffers(struct 
-       if (ret == -EINVAL) {
-               /* corrupt descriptor, skip this one and the following one */
-               list_add_tail(&bf->list, &sc->rx.rxbuf);
--              ath_rx_edma_buf_link(sc, qtype);
-+              ath_rx_edma_buf_link(sc, qtype, false);
-               skb = skb_peek(&rx_edma->rx_fifo);
-               if (skb) {
-@@ -645,7 +648,7 @@ static bool ath_edma_get_buffers(struct 
-                       __skb_unlink(skb, &rx_edma->rx_fifo);
-                       list_add_tail(&bf->list, &sc->rx.rxbuf);
--                      ath_rx_edma_buf_link(sc, qtype);
-+                      ath_rx_edma_buf_link(sc, qtype, false);
-               }
-               bf = NULL;
-@@ -975,6 +978,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
-       u64 tsf = 0;
-       unsigned long flags;
-       dma_addr_t new_buf_addr;
-+      unsigned int budget = 512;
-       if (edma)
-               dma_type = DMA_BIDIRECTIONAL;
-@@ -1113,15 +1117,17 @@ requeue_drop_frag:
-               }
+@@ -1118,12 +1120,12 @@ requeue_drop_frag:
  requeue:
                list_add_tail(&bf->list, &sc->rx.rxbuf);
--              if (flush)
--                      continue;
  
-               if (edma) {
+-              if (edma) {
 -                      ath_rx_edma_buf_link(sc, qtype);
-+                      ath_rx_edma_buf_link(sc, qtype, flush);
-               } else {
+-              } else {
 -                      ath_rx_buf_relink(sc, bf);
--                      ath9k_hw_rxena(ah);
++              if (!edma) {
 +                      ath_rx_buf_relink(sc, bf, flush);
-+                      if (!flush)
-+                              ath9k_hw_rxena(ah);
+                       if (!flush)
+                               ath9k_hw_rxena(ah);
++              } else if (!flush) {
++                      ath_rx_edma_buf_link(sc, qtype);
                }
-+
-+              if (!budget--)
-+                      break;
-       } while (1);
-       if (!(ah->imask & ATH9K_INT_RXEOL)) {
-@@ -1129,5 +1135,5 @@ requeue:
-               ath9k_hw_set_interrupts(ah);
-       }
--      return 0;
-+      return !budget;
- }
---- a/drivers/net/wireless/ath/ath9k/ahb.c
-+++ b/drivers/net/wireless/ath/ath9k/ahb.c
-@@ -86,7 +86,6 @@ static int ath_ahb_probe(struct platform
-       int irq;
-       int ret = 0;
-       struct ath_hw *ah;
--      struct ath_common *common;
-       char hw_name[64];
-       if (!dev_get_platdata(&pdev->dev)) {
-@@ -146,9 +145,6 @@ static int ath_ahb_probe(struct platform
-       wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
-                  hw_name, (unsigned long)mem, irq);
--      common = ath9k_hw_common(sc->sc_ah);
--      /* Will be cleared in ath9k_start() */
--      set_bit(ATH_OP_INVALID, &common->op_flags);
-       return 0;
-  err_irq:
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -670,6 +670,7 @@ static const struct ieee80211_iface_comb
-               .num_different_channels = 1,
-               .beacon_int_infra_match = true,
-       },
-+#ifdef CONFIG_ATH9K_DFS_CERTIFIED
-       {
-               .limits = if_dfs_limits,
-               .n_limits = ARRAY_SIZE(if_dfs_limits),
-@@ -679,6 +680,7 @@ static const struct ieee80211_iface_comb
-               .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
-                                       BIT(NL80211_CHAN_WIDTH_20),
-       }
-+#endif
- };
  
- static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
-@@ -781,6 +783,9 @@ int ath9k_init_device(u16 devid, struct 
-       common = ath9k_hw_common(ah);
-       ath9k_set_hw_capab(sc, hw);
-+      /* Will be cleared in ath9k_start() */
-+      set_bit(ATH_OP_INVALID, &common->op_flags);
-+
-       /* Initialize regulatory */
-       error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
-                             ath9k_reg_notifier);
---- a/drivers/net/wireless/ath/ath9k/pci.c
-+++ b/drivers/net/wireless/ath/ath9k/pci.c
-@@ -784,7 +784,6 @@ static int ath_pci_probe(struct pci_dev 
+               if (!budget--)
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -227,6 +227,7 @@ struct sta_info *sta_info_get_by_idx(str
+  */
+ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
  {
-       struct ath_softc *sc;
-       struct ieee80211_hw *hw;
--      struct ath_common *common;
-       u8 csz;
-       u32 val;
-       int ret = 0;
-@@ -877,10 +876,6 @@ static int ath_pci_probe(struct pci_dev 
-       wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
-                  hw_name, (unsigned long)sc->mem, pdev->irq);
++      struct ieee80211_sta_rates *rates;
+       int i;
  
--      /* Will be cleared in ath9k_start() */
--      common = ath9k_hw_common(sc->sc_ah);
--      set_bit(ATH_OP_INVALID, &common->op_flags);
--
-       return 0;
- err_init:
---- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
-@@ -410,7 +410,7 @@ static const u32 ar9300_2p2_baseband_cor
-       {0x00009e30, 0x06336f77},
-       {0x00009e34, 0x6af6532f},
-       {0x00009e38, 0x0cc80c00},
--      {0x00009e40, 0x0d261820},
-+      {0x00009e40, 0x0d261800},
-       {0x00009e4c, 0x00001004},
-       {0x00009e50, 0x00ff03f1},
-       {0x00009e54, 0x00000000},
---- a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
-@@ -592,7 +592,7 @@ static const u32 ar9331_1p1_baseband_cor
-       {0x00009e30, 0x06336f77},
-       {0x00009e34, 0x6af6532f},
-       {0x00009e38, 0x0cc80c00},
--      {0x00009e40, 0x0d261820},
-+      {0x00009e40, 0x0d261800},
-       {0x00009e4c, 0x00001004},
-       {0x00009e50, 0x00ff03f1},
-       {0x00009fc0, 0x803e4788},
---- a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
-@@ -231,7 +231,7 @@ static const u32 ar9331_1p2_baseband_cor
-       {0x00009e30, 0x06336f77},
-       {0x00009e34, 0x6af6532f},
-       {0x00009e38, 0x0cc80c00},
--      {0x00009e40, 0x0d261820},
-+      {0x00009e40, 0x0d261800},
-       {0x00009e4c, 0x00001004},
-       {0x00009e50, 0x00ff03f1},
-       {0x00009fc0, 0x803e4788},
---- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
-@@ -318,7 +318,7 @@ static const u32 ar9340_1p0_baseband_cor
-       {0x00009e30, 0x06336f77},
-       {0x00009e34, 0x6af6532f},
-       {0x00009e38, 0x0cc80c00},
--      {0x00009e40, 0x0d261820},
-+      {0x00009e40, 0x0d261800},
-       {0x00009e4c, 0x00001004},
-       {0x00009e50, 0x00ff03f1},
-       {0x00009e54, 0x00000000},
-@@ -348,9 +348,9 @@ static const u32 ar9340_1p0_baseband_cor
-       {0x0000a370, 0x00000000},
-       {0x0000a390, 0x00000001},
-       {0x0000a394, 0x00000444},
--      {0x0000a398, 0x00000000},
--      {0x0000a39c, 0x210d0401},
--      {0x0000a3a0, 0xab9a7144},
-+      {0x0000a398, 0x001f0e0f},
-+      {0x0000a39c, 0x0075393f},
-+      {0x0000a3a0, 0xb79f6427},
-       {0x0000a3a4, 0x00000000},
-       {0x0000a3a8, 0xaaaaaaaa},
-       {0x0000a3ac, 0x3c466478},
---- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
-@@ -90,7 +90,7 @@ static const u32 ar9580_1p0_baseband_cor
-       {0x00009e30, 0x06336f77},
-       {0x00009e34, 0x6af6532f},
-       {0x00009e38, 0x0cc80c00},
--      {0x00009e40, 0x0d261820},
-+      {0x00009e40, 0x0d261800},
-       {0x00009e4c, 0x00001004},
-       {0x00009e50, 0x00ff03f1},
-       {0x00009e54, 0x00000000},
---- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
-+++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
-@@ -257,9 +257,9 @@ static const u32 qca953x_1p0_baseband_co
-       {0x0000a370, 0x00000000},
-       {0x0000a390, 0x00000001},
-       {0x0000a394, 0x00000444},
--      {0x0000a398, 0x1f020503},
--      {0x0000a39c, 0x29180c03},
--      {0x0000a3a0, 0x9a8b6844},
-+      {0x0000a398, 0x001f0e0f},
-+      {0x0000a39c, 0x0075393f},
-+      {0x0000a3a0, 0xb79f6427},
-       {0x0000a3a4, 0x000000ff},
-       {0x0000a3a8, 0x6a6a6a6a},
-       {0x0000a3ac, 0x6a6a6a6a},
---- a/drivers/net/wireless/ath/ath5k/phy.c
-+++ b/drivers/net/wireless/ath/ath5k/phy.c
-@@ -3709,8 +3709,8 @@ ath5k_hw_txpower(struct ath5k_hw *ah, st
-                       AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP),
-                       AR5K_TPC);
-       } else {
--              ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
--                      AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
-+              ath5k_hw_reg_write(ah, AR5K_TUNE_MAX_TXPOWER,
-+                      AR5K_PHY_TXPOWER_RATE_MAX);
+       if (sta->rate_ctrl)
+@@ -238,6 +239,10 @@ void sta_info_free(struct ieee80211_loca
+               kfree(sta->tx_lat);
        }
  
-       return 0;
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -1231,7 +1231,8 @@ ieee80211_rx_h_sta_process(struct ieee80
-               if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) &&
-                   test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
-                       sta->last_rx = jiffies;
--                      if (ieee80211_is_data(hdr->frame_control)) {
-+                      if (ieee80211_is_data(hdr->frame_control) &&
-+                          !is_multicast_ether_addr(hdr->addr1)) {
-                               sta->last_rx_rate_idx = status->rate_idx;
-                               sta->last_rx_rate_flag = status->flag;
-                               sta->last_rx_rate_vht_flag = status->vht_flag;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -442,6 +442,8 @@ void ath9k_tasklet(unsigned long data)
-       ath9k_ps_wakeup(sc);
-       spin_lock(&sc->sc_pcu_lock);
-+      sc->intrstatus = 0;
++      rates = rcu_dereference_protected(sta->sta.rates, true);
++      if (rates)
++              kfree(rates);
 +
-       if (status & ATH9K_INT_FATAL) {
-               type = RESET_TYPE_FATAL_INT;
-               ath9k_queue_reset(sc, type);
-@@ -510,10 +512,12 @@ void ath9k_tasklet(unsigned long data)
-       if (status & rxmask) {
-               /* Check for high priority Rx first */
-               if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
--                  (status & ATH9K_INT_RXHP))
--                      ath_rx_tasklet(sc, 0, true);
-+                  (status & ATH9K_INT_RXHP) &&
-+                  ath_rx_tasklet(sc, 0, true))
-+                      sc->intrstatus |= ATH9K_INT_RXHP;
+       sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
  
--              ath_rx_tasklet(sc, 0, false);
-+              if (ath_rx_tasklet(sc, 0, false))
-+                      sc->intrstatus |= ATH9K_INT_RXLP;
-       }
-       if (status & ATH9K_INT_TX) {
-@@ -541,6 +545,9 @@ void ath9k_tasklet(unsigned long data)
+       kfree(sta);
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
+  */
+ #define STA_LOST_PKT_THRESHOLD        50
  
-       /* re-enable hardware interrupt */
-       ath9k_hw_enable_interrupts(ah);
-+      if (sc->intrstatus)
-+              tasklet_schedule(&sc->intr_tq);
++static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
++{
++      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 +
- out:
-       spin_unlock(&sc->sc_pcu_lock);
-       ath9k_ps_restore(sc);
-@@ -607,7 +614,7 @@ irqreturn_t ath_isr(int irq, void *dev)
-               return IRQ_NONE;
-       /* Cache the status */
--      sc->intrstatus = status;
-+      sc->intrstatus |= status;
++      /* This packet was aggregated but doesn't carry status info */
++      if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
++          !(info->flags & IEEE80211_TX_STAT_AMPDU))
++              return;
++
++      if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
++              return;
++
++      cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
++                                  sta->lost_packets, GFP_ATOMIC);
++      sta->lost_packets = 0;
++}
++
+ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+ {
+       struct sk_buff *skb2;
+@@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021
+                       if (info->flags & IEEE80211_TX_STAT_ACK) {
+                               if (sta->lost_packets)
+                                       sta->lost_packets = 0;
+-                      } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
+-                              cfg80211_cqm_pktloss_notify(sta->sdata->dev,
+-                                                          sta->sta.addr,
+-                                                          sta->lost_packets,
+-                                                          GFP_ATOMIC);
+-                              sta->lost_packets = 0;
++                      } else {
++                              ieee80211_lost_packet(sta, skb);
+                       }
+               }
  
-       if (status & SCHED_INTR)
-               sched = true;