ath9k: add some rx path fixes
[openwrt/staging/lynxis.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
index 654d6aabe8797eaeff1c8010cb493452adaf76a1..ef81721529eee36aa5faa2a55a14cd6d887d177f 100644 (file)
---- a/net/mac80211/agg-rx.c
-+++ b/net/mac80211/agg-rx.c
-@@ -204,6 +204,8 @@ static void ieee80211_send_addba_resp(st
-               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-       else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-               memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
-+      else if (sdata->vif.type == NL80211_IFTYPE_WDS)
-+              memcpy(mgmt->bssid, da, ETH_ALEN);
-       mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-                                         IEEE80211_STYPE_ACTION);
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -81,7 +81,8 @@ static void ieee80211_send_addba_request
-       memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
-       if (sdata->vif.type == NL80211_IFTYPE_AP ||
-           sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
--          sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
-+          sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
-+          sdata->vif.type == NL80211_IFTYPE_WDS)
-               memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
-       else if (sdata->vif.type == NL80211_IFTYPE_STATION)
-               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-@@ -527,6 +528,7 @@ int ieee80211_start_tx_ba_session(struct
-           sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
-           sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
-           sdata->vif.type != NL80211_IFTYPE_AP &&
-+          sdata->vif.type != NL80211_IFTYPE_WDS &&
-           sdata->vif.type != NL80211_IFTYPE_ADHOC)
-               return -EINVAL;
---- a/net/mac80211/debugfs_sta.c
-+++ b/net/mac80211/debugfs_sta.c
-@@ -66,11 +66,11 @@ static ssize_t sta_flags_read(struct fil
-       test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
-       int res = scnprintf(buf, sizeof(buf),
--                          "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
-+                          "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
-                           TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
-                           TEST(PS_DRIVER), TEST(AUTHORIZED),
-                           TEST(SHORT_PREAMBLE),
--                          TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
-+                          TEST(WME), TEST(CLEAR_PS_FILT),
-                           TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
-                           TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
-                           TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -463,7 +463,6 @@ int ieee80211_do_open(struct wireless_de
-       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
-       struct net_device *dev = wdev->netdev;
-       struct ieee80211_local *local = sdata->local;
--      struct sta_info *sta;
-       u32 changed = 0;
-       int res;
-       u32 hw_reconf_flags = 0;
-@@ -629,30 +628,8 @@ int ieee80211_do_open(struct wireless_de
-       set_bit(SDATA_STATE_RUNNING, &sdata->state);
--      if (sdata->vif.type == NL80211_IFTYPE_WDS) {
--              /* Create STA entry for the WDS peer */
--              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
--                                   GFP_KERNEL);
--              if (!sta) {
--                      res = -ENOMEM;
--                      goto err_del_interface;
--              }
--
--              sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
--              sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
--              sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
--
--              res = sta_info_insert(sta);
--              if (res) {
--                      /* STA has been freed */
--                      goto err_del_interface;
--              }
--
--              rate_control_rate_init(sta);
--              netif_carrier_on(dev);
--      } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
-+      if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
-               rcu_assign_pointer(local->p2p_sdata, sdata);
--      }
-       /*
-        * set_multicast_list will be invoked by the networking core
-@@ -1116,6 +1093,74 @@ static void ieee80211_if_setup(struct ne
-       dev->destructor = free_netdev;
+commit 230ab8c1880266c9cfceac962e2d48309dea79a7
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Mon May 19 21:48:56 2014 +0200
+
+    ath9k: re-schedule rx processing after budget exceeded
+    
+    Should improve rx stability under load
+    
+    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.
+    
+    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
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Thu Apr 10 10:49:01 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.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 0ca13e26341733bf9577287fb04a3bef0d2f5cc9
+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
+
+    ath9k_hw: reduce ANI firstep range for older chips
+    
+    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.
+    
+    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);
  }
  
-+static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
-+                                       struct sk_buff *skb)
-+{
-+      struct ieee80211_local *local = sdata->local;
-+      struct ieee80211_rx_status *rx_status;
-+      struct ieee802_11_elems elems;
-+      struct ieee80211_mgmt *mgmt;
-+      struct sta_info *sta;
-+      size_t baselen;
-+      u32 rates = 0;
-+      u16 stype;
-+      bool new = false;
-+      enum ieee80211_band band;
-+      struct ieee80211_supported_band *sband;
-+
-+      rx_status = IEEE80211_SKB_RXCB(skb);
-+      band = rx_status->band;
-+      sband = local->hw.wiphy->bands[band];
-+      mgmt = (struct ieee80211_mgmt *) skb->data;
-+      stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
-+
-+      if (stype != IEEE80211_STYPE_BEACON)
-+              return;
-+
-+      baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
-+      if (baselen > skb->len)
-+              return;
-+
-+      ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
-+                             skb->len - baselen, false, &elems);
-+
-+      rates = ieee80211_sta_get_rates(local, &elems, band, NULL);
-+
-+      rcu_read_lock();
-+
-+      sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
-+
-+      if (!sta) {
-+              rcu_read_unlock();
-+              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
-+                                   GFP_KERNEL);
-+              if (!sta)
-+                      return;
-+
-+              new = true;
-+      }
-+
-+      sta->last_rx = jiffies;
-+      sta->sta.supp_rates[band] = rates;
-+
-+      if (elems.ht_cap_elem)
-+              ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
-+                              elems.ht_cap_elem, sta);
-+
-+      if (elems.wmm_param)
-+              set_sta_flag(sta, WLAN_STA_WME);
-+
-+      if (new) {
-+              sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
-+              sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
-+              sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
-+              rate_control_rate_init(sta);
-+              sta_info_insert_rcu(sta);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
- static void ieee80211_iface_work(struct work_struct *work)
+ 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_sub_if_data *sdata =
-@@ -1220,6 +1265,9 @@ static void ieee80211_iface_work(struct 
-                               break;
-                       ieee80211_mesh_rx_queued_mgmt(sdata, skb);
-                       break;
-+              case NL80211_IFTYPE_WDS:
-+                      ieee80211_wds_rx_queued_mgmt(sdata, skb);
-+                      break;
-               default:
-                       WARN(1, "frame for unexpected interface type");
-                       break;
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -804,10 +804,18 @@ minstrel_ht_get_rate(void *priv, struct 
+       struct ieee80211_local *local = sdata->local;
  
-       sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
-       info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-+      rate->count = 1;
-+
-+      if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
-+              int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
-+              rate->idx = mp->cck_rates[idx];
-+              rate->flags = 0;
-+              return;
-+      }
-+
-       rate->idx = sample_idx % MCS_GROUP_RATES +
-                   (sample_group->streams - 1) * MCS_GROUP_RATES;
-       rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
--      rate->count = 1;
- }
+-      if (!changed)
++      if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               return;
  
- static void
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2369,6 +2369,7 @@ ieee80211_rx_h_action(struct ieee80211_r
-                   sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
-                   sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
-                   sdata->vif.type != NL80211_IFTYPE_AP &&
-+                  sdata->vif.type != NL80211_IFTYPE_WDS &&
-                   sdata->vif.type != NL80211_IFTYPE_ADHOC)
-                       break;
+       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);
  
-@@ -2720,14 +2721,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
-       if (!ieee80211_vif_is_mesh(&sdata->vif) &&
-           sdata->vif.type != NL80211_IFTYPE_ADHOC &&
--          sdata->vif.type != NL80211_IFTYPE_STATION)
-+          sdata->vif.type != NL80211_IFTYPE_STATION &&
-+          sdata->vif.type != NL80211_IFTYPE_WDS)
-               return RX_DROP_MONITOR;
-       switch (stype) {
-       case cpu_to_le16(IEEE80211_STYPE_AUTH):
-       case cpu_to_le16(IEEE80211_STYPE_BEACON):
-       case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
--              /* process for all: mesh, mlme, ibss */
-+              /* process for all: mesh, mlme, ibss, wds */
-               break;
-       case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
-       case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
-@@ -3059,10 +3061,16 @@ static int prepare_for_handlers(struct i
-               }
-               break;
-       case NL80211_IFTYPE_WDS:
--              if (bssid || !ieee80211_is_data(hdr->frame_control))
--                      return 0;
-               if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2))
-                       return 0;
++      if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL)
++              immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
 +
-+              if (ieee80211_is_data(hdr->frame_control) ||
-+                  ieee80211_is_action(hdr->frame_control)) {
-+                      if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
-+                              return 0;
-+              } else if (!ieee80211_is_beacon(hdr->frame_control))
-+                      return 0;
+       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;
 +
-               break;
-       case NL80211_IFTYPE_P2P_DEVICE:
-               if (!ieee80211_is_public_action(hdr, skb->len) &&
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -32,7 +32,6 @@
-  * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
-  *    frames.
-  * @WLAN_STA_WME: Station is a QoS-STA.
-- * @WLAN_STA_WDS: Station is one of our WDS peers.
-  * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
-  *    IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
-  *    frame to this station is transmitted.
-@@ -66,7 +65,6 @@ enum ieee80211_sta_info_flags {
-       WLAN_STA_AUTHORIZED,
-       WLAN_STA_SHORT_PREAMBLE,
-       WLAN_STA_WME,
--      WLAN_STA_WDS,
-       WLAN_STA_CLEAR_PS_FILT,
-       WLAN_STA_MFP,
-       WLAN_STA_BLOCK_BA,
+       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
-@@ -146,6 +146,28 @@ static void ath_set_rates(struct ieee802
-                              ARRAY_SIZE(bf->rates));
- }
-+static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
-+                           struct sk_buff *skb)
-+{
-+      int q;
-+
-+      q = skb_get_queue_mapping(skb);
-+      if (txq == sc->tx.uapsdq)
-+              txq = sc->tx.txq_map[q];
-+
-+      if (txq != sc->tx.txq_map[q])
-+              return;
-+
-+      if (WARN_ON(--txq->pending_frames < 0))
-+              txq->pending_frames = 0;
-+
-+      if (txq->stopped &&
-+          txq->pending_frames < sc->tx.txq_max_pending[q]) {
-+              ieee80211_wake_queue(sc->hw, q);
-+              txq->stopped = false;
-+      }
-+}
-+
- static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+@@ -107,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_
  {
-       struct ath_txq *txq = tid->ac->txq;
-@@ -167,6 +189,7 @@ static void ath_tx_flush_tid(struct ath_
-               if (!bf) {
-                       bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-                       if (!bf) {
-+                              ath_txq_skb_done(sc, txq, skb);
-                               ieee80211_free_txskb(sc->hw, skb);
-                               continue;
-                       }
-@@ -811,6 +834,7 @@ ath_tx_get_tid_subframe(struct ath_softc
-               if (!bf) {
-                       __skb_unlink(skb, &tid->buf_q);
-+                      ath_txq_skb_done(sc, txq, skb);
-                       ieee80211_free_txskb(sc->hw, skb);
-                       continue;
-               }
-@@ -1824,6 +1848,7 @@ static void ath_tx_send_ampdu(struct ath
+       struct ath_atx_ac *ac = tid->ac;
  
-       bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-       if (!bf) {
-+              ath_txq_skb_done(sc, txq, skb);
-               ieee80211_free_txskb(sc->hw, skb);
+-      if (tid->paused)
+-              return;
+-
+       if (tid->sched)
                return;
-       }
-@@ -2090,6 +2115,7 @@ int ath_tx_start(struct ieee80211_hw *hw
-       bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-       if (!bf) {
-+              ath_txq_skb_done(sc, txq, skb);
-               if (txctl->paprd)
-                       dev_kfree_skb_any(skb);
-               else
-@@ -2189,7 +2215,7 @@ static void ath_tx_complete(struct ath_s
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
--      int q, padpos, padsize;
-+      int padpos, padsize;
-       unsigned long flags;
  
-       ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
-@@ -2225,21 +2251,7 @@ static void ath_tx_complete(struct ath_s
-       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+@@ -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);
  
-       __skb_queue_tail(&txq->complete_q, skb);
--
--      q = skb_get_queue_mapping(skb);
--      if (txq == sc->tx.uapsdq)
--              txq = sc->tx.txq_map[q];
--
--      if (txq == sc->tx.txq_map[q]) {
--              if (WARN_ON(--txq->pending_frames < 0))
--                      txq->pending_frames = 0;
--
--              if (txq->stopped &&
--                  txq->pending_frames < sc->tx.txq_max_pending[q]) {
--                      ieee80211_wake_queue(sc->hw, q);
--                      txq->stopped = false;
--              }
--      }
-+      ath_txq_skb_done(sc, txq, skb);
- }
+       tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
+-      tid->paused = false;
  
- static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -2094,7 +2094,7 @@ static void ath9k_wow_add_pattern(struct
- {
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath9k_wow_pattern *wow_pattern = NULL;
--      struct cfg80211_wowlan_trig_pkt_pattern *patterns = wowlan->patterns;
-+      struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
-       int mask_len;
-       s8 i = 0;
---- a/drivers/net/wireless/mwifiex/cfg80211.c
-+++ b/drivers/net/wireless/mwifiex/cfg80211.c
-@@ -2298,8 +2298,7 @@ EXPORT_SYMBOL_GPL(mwifiex_del_virtual_in
- #ifdef CONFIG_PM
- static bool
--mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat,
--                           s8 *byte_seq)
-+mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq)
- {
-       int j, k, valid_byte_cnt = 0;
-       bool dont_care_byte = false;
---- a/drivers/net/wireless/ti/wlcore/main.c
-+++ b/drivers/net/wireless/ti/wlcore/main.c
-@@ -1315,7 +1315,7 @@ static struct sk_buff *wl12xx_alloc_dumm
- #ifdef CONFIG_PM
- static int
--wl1271_validate_wowlan_pattern(struct cfg80211_wowlan_trig_pkt_pattern *p)
-+wl1271_validate_wowlan_pattern(struct cfg80211_pkt_pattern *p)
- {
-       int num_fields = 0, in_field = 0, fields_size = 0;
-       int i, pattern_len = 0;
-@@ -1458,9 +1458,9 @@ void wl1271_rx_filter_flatten_fields(str
-  * Allocates an RX filter returned through f
-  * which needs to be freed using rx_filter_free()
-  */
--static int wl1271_convert_wowlan_pattern_to_rx_filter(
--      struct cfg80211_wowlan_trig_pkt_pattern *p,
--      struct wl12xx_rx_filter **f)
-+static int
-+wl1271_convert_wowlan_pattern_to_rx_filter(struct cfg80211_pkt_pattern *p,
-+                                         struct wl12xx_rx_filter **f)
- {
-       int i, j, ret = 0;
-       struct wl12xx_rx_filter *filter;
-@@ -1562,7 +1562,7 @@ static int wl1271_configure_wowlan(struc
-       /* Translate WoWLAN patterns into filters */
-       for (i = 0; i < wow->n_patterns; i++) {
--              struct cfg80211_wowlan_trig_pkt_pattern *p;
-+              struct cfg80211_pkt_pattern *p;
-               struct wl12xx_rx_filter *filter = NULL;
-               p = &wow->patterns[i];
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -1698,7 +1698,7 @@ struct cfg80211_pmksa {
- };
+       if (ath_tid_has_buffered(tid)) {
+               ath_tx_queue_tid(txq, tid);
+@@ -1544,8 +1538,6 @@ void ath9k_release_buffered_frames(struc
+                       continue;
  
- /**
-- * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern
-+ * struct cfg80211_pkt_pattern - packet pattern
-  * @mask: bitmask where to match pattern and where to ignore bytes,
-  *    one bit per byte, in same format as nl80211
-  * @pattern: bytes to match where bitmask is 1
-@@ -1708,7 +1708,7 @@ struct cfg80211_pmksa {
-  * Internal note: @mask and @pattern are allocated in one chunk of
-  * memory, free @mask only!
-  */
--struct cfg80211_wowlan_trig_pkt_pattern {
-+struct cfg80211_pkt_pattern {
-       u8 *mask, *pattern;
-       int pattern_len;
-       int pkt_offset;
-@@ -1770,7 +1770,7 @@ struct cfg80211_wowlan {
-       bool any, disconnect, magic_pkt, gtk_rekey_failure,
-            eap_identity_req, four_way_handshake,
-            rfkill_release;
--      struct cfg80211_wowlan_trig_pkt_pattern *patterns;
-+      struct cfg80211_pkt_pattern *patterns;
-       struct cfg80211_wowlan_tcp *tcp;
-       int n_patterns;
- };
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -3060,11 +3060,11 @@ enum nl80211_tx_power_setting {
- };
+               tid = ATH_AN_2_TID(an, i);
+-              if (tid->paused)
+-                      continue;
  
- /**
-- * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute
-- * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute
-- * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has
-+ * enum nl80211_packet_pattern_attr - packet pattern attribute
-+ * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute
-+ * @NL80211_PKTPAT_PATTERN: the pattern, values where the mask has
-  *    a zero bit are ignored
-- * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have
-+ * @NL80211_PKTPAT_MASK: pattern mask, must be long enough to have
-  *    a bit for each byte in the pattern. The lowest-order bit corresponds
-  *    to the first byte of the pattern, but the bytes of the pattern are
-  *    in a little-endian-like format, i.e. the 9th byte of the pattern
-@@ -3075,23 +3075,23 @@ enum nl80211_tx_power_setting {
-  *    Note that the pattern matching is done as though frames were not
-  *    802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
-  *    first (including SNAP header unpacking) and then matched.
-- * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after
-+ * @NL80211_PKTPAT_OFFSET: packet offset, pattern is matched after
-  *    these fixed number of bytes of received packet
-- * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
-- * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
-+ * @NUM_NL80211_PKTPAT: number of attributes
-+ * @MAX_NL80211_PKTPAT: max attribute number
-  */
--enum nl80211_wowlan_packet_pattern_attr {
--      __NL80211_WOWLAN_PKTPAT_INVALID,
--      NL80211_WOWLAN_PKTPAT_MASK,
--      NL80211_WOWLAN_PKTPAT_PATTERN,
--      NL80211_WOWLAN_PKTPAT_OFFSET,
-+enum nl80211_packet_pattern_attr {
-+      __NL80211_PKTPAT_INVALID,
-+      NL80211_PKTPAT_MASK,
-+      NL80211_PKTPAT_PATTERN,
-+      NL80211_PKTPAT_OFFSET,
--      NUM_NL80211_WOWLAN_PKTPAT,
--      MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
-+      NUM_NL80211_PKTPAT,
-+      MAX_NL80211_PKTPAT = NUM_NL80211_PKTPAT - 1,
- };
+               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;
  
- /**
-- * struct nl80211_wowlan_pattern_support - pattern support information
-+ * struct nl80211_pattern_support - packet pattern support information
-  * @max_patterns: maximum number of patterns supported
-  * @min_pattern_len: minimum length of each pattern
-  * @max_pattern_len: maximum length of each pattern
-@@ -3101,13 +3101,22 @@ enum nl80211_wowlan_packet_pattern_attr 
-  * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
-  * capability information given by the kernel to userspace.
+-                      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
+  * buffer (or rx fifo). This can incorrectly acknowledge packets
+  * to a sender if last desc is self-linked.
   */
--struct nl80211_wowlan_pattern_support {
-+struct nl80211_pattern_support {
-       __u32 max_patterns;
-       __u32 min_pattern_len;
-       __u32 max_pattern_len;
-       __u32 max_pkt_offset;
- } __attribute__((packed));
-+/* only for backward compatibility */
-+#define __NL80211_WOWLAN_PKTPAT_INVALID __NL80211_PKTPAT_INVALID
-+#define NL80211_WOWLAN_PKTPAT_MASK NL80211_PKTPAT_MASK
-+#define NL80211_WOWLAN_PKTPAT_PATTERN NL80211_PKTPAT_PATTERN
-+#define NL80211_WOWLAN_PKTPAT_OFFSET NL80211_PKTPAT_OFFSET
-+#define NUM_NL80211_WOWLAN_PKTPAT NUM_NL80211_PKTPAT
-+#define MAX_NL80211_WOWLAN_PKTPAT MAX_NL80211_PKTPAT
-+#define nl80211_wowlan_pattern_support nl80211_pattern_support
-+
- /**
-  * enum nl80211_wowlan_triggers - WoWLAN trigger definitions
-  * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes
-@@ -3127,7 +3136,7 @@ struct nl80211_wowlan_pattern_support {
-  *    pattern matching is done after the packet is converted to the MSDU.
-  *
-  *    In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
-- *    carrying a &struct nl80211_wowlan_pattern_support.
-+ *    carrying a &struct nl80211_pattern_support.
-  *
-  *    When reporting wakeup. it is a u32 attribute containing the 0-based
-  *    index of the pattern that caused the wakeup, in the patterns passed
-@@ -3284,7 +3293,7 @@ struct nl80211_wowlan_tcp_data_token_fea
-  * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a
-  *    u32 attribute holding the maximum length
-  * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for
-- *    feature advertising. The mask works like @NL80211_WOWLAN_PKTPAT_MASK
-+ *    feature advertising. The mask works like @NL80211_PKTPAT_MASK
-  *    but on the TCP payload only.
-  * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes
-  * @MAX_NL80211_WOWLAN_TCP: highest attribute number
---- a/net/mac80211/mesh_ps.c
-+++ b/net/mac80211/mesh_ps.c
-@@ -229,6 +229,10 @@ void ieee80211_mps_sta_status_update(str
-       enum nl80211_mesh_power_mode pm;
-       bool do_buffer;
-+      /* For non-assoc STA, prevent buffering or frame transmission */
-+      if (sta->sta_state < IEEE80211_STA_ASSOC)
-+              return;
-+
-       /*
-        * use peer-specific power mode if peering is established and the
-        * peer's power mode is known
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -974,7 +974,7 @@ static int nl80211_send_wowlan(struct sk
-               return -ENOBUFS;
-       if (dev->wiphy.wowlan->n_patterns) {
--              struct nl80211_wowlan_pattern_support pat = {
-+              struct nl80211_pattern_support pat = {
-                       .max_patterns = dev->wiphy.wowlan->n_patterns,
-                       .min_pattern_len = dev->wiphy.wowlan->pattern_min_len,
-                       .max_pattern_len = dev->wiphy.wowlan->pattern_max_len,
-@@ -1568,8 +1568,10 @@ static int nl80211_dump_wiphy(struct sk_
-       rtnl_lock();
-       if (!state) {
-               state = kzalloc(sizeof(*state), GFP_KERNEL);
--              if (!state)
-+              if (!state) {
-+                      rtnl_unlock();
-                       return -ENOMEM;
-+              }
-               state->filter_wiphy = -1;
-               ret = nl80211_dump_wiphy_parse(skb, cb, state);
-               if (ret) {
-@@ -6615,12 +6617,14 @@ EXPORT_SYMBOL(cfg80211_testmode_alloc_ev
- void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
+-static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
++static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
++                          bool flush)
  {
-+      struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
-       void *hdr = ((void **)skb->cb)[1];
-       struct nlattr *data = ((void **)skb->cb)[2];
-       nla_nest_end(skb, data);
-       genlmsg_end(skb, hdr);
--      genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp);
-+      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0,
-+                              nl80211_testmode_mcgrp.id, gfp);
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
+                            common->rx_bufsize,
+                            0);
+-      if (sc->rx.rxlink == NULL)
+-              ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+-      else
++      if (sc->rx.rxlink)
+               *sc->rx.rxlink = bf->bf_daddr;
++      else if (!flush)
++              ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+       sc->rx.rxlink = &ds->ds_link;
  }
- EXPORT_SYMBOL(cfg80211_testmode_event);
- #endif
-@@ -7593,12 +7597,11 @@ static int nl80211_send_wowlan_patterns(
-               if (!nl_pat)
-                       return -ENOBUFS;
-               pat_len = wowlan->patterns[i].pattern_len;
--              if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
--                          DIV_ROUND_UP(pat_len, 8),
-+              if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
-                           wowlan->patterns[i].mask) ||
--                  nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
--                          pat_len, wowlan->patterns[i].pattern) ||
--                  nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
-+                  nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
-+                          wowlan->patterns[i].pattern) ||
-+                  nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
-                               wowlan->patterns[i].pkt_offset))
-                       return -ENOBUFS;
-               nla_nest_end(msg, nl_pat);
-@@ -7939,7 +7942,7 @@ static int nl80211_set_wowlan(struct sk_
-               struct nlattr *pat;
-               int n_patterns = 0;
-               int rem, pat_len, mask_len, pkt_offset;
--              struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
-+              struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
-               nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
-                                   rem)
-@@ -7958,26 +7961,25 @@ static int nl80211_set_wowlan(struct sk_
-               nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
-                                   rem) {
--                      nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT,
--                                nla_data(pat), nla_len(pat), NULL);
-+                      nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
-+                                nla_len(pat), NULL);
-                       err = -EINVAL;
--                      if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] ||
--                          !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN])
-+                      if (!pat_tb[NL80211_PKTPAT_MASK] ||
-+                          !pat_tb[NL80211_PKTPAT_PATTERN])
-                               goto error;
--                      pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]);
-+                      pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
-                       mask_len = DIV_ROUND_UP(pat_len, 8);
--                      if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) !=
--                          mask_len)
-+                      if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
-                               goto error;
-                       if (pat_len > wowlan->pattern_max_len ||
-                           pat_len < wowlan->pattern_min_len)
-                               goto error;
--                      if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
-+                      if (!pat_tb[NL80211_PKTPAT_OFFSET])
-                               pkt_offset = 0;
-                       else
-                               pkt_offset = nla_get_u32(
--                                      pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);
-+                                      pat_tb[NL80211_PKTPAT_OFFSET]);
-                       if (pkt_offset > wowlan->max_pkt_offset)
-                               goto error;
-                       new_triggers.patterns[i].pkt_offset = pkt_offset;
-@@ -7991,11 +7993,11 @@ static int nl80211_set_wowlan(struct sk_
-                       new_triggers.patterns[i].pattern =
-                               new_triggers.patterns[i].mask + mask_len;
-                       memcpy(new_triggers.patterns[i].mask,
--                             nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]),
-+                             nla_data(pat_tb[NL80211_PKTPAT_MASK]),
-                              mask_len);
-                       new_triggers.patterns[i].pattern_len = pat_len;
-                       memcpy(new_triggers.patterns[i].pattern,
--                             nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]),
-+                             nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
-                              pat_len);
-                       i++;
-               }
-@@ -10066,7 +10068,8 @@ void cfg80211_mgmt_tx_status(struct wire
-       genlmsg_end(msg, hdr);
--      genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
-+      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
-+                              nl80211_mlme_mcgrp.id, gfp);
-       return;
  
-  nla_put_failure:
---- a/net/wireless/reg.c
-+++ b/net/wireless/reg.c
-@@ -2279,7 +2279,9 @@ void wiphy_regulatory_deregister(struct 
- static void reg_timeout_work(struct work_struct *work)
+-static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
++static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
++                            bool flush)
  {
-       REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
-+      rtnl_lock();
-       restore_regulatory_settings(true);
-+      rtnl_unlock();
+       if (sc->rx.buf_hold)
+-              ath_rx_buf_link(sc, sc->rx.buf_hold);
++              ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
+       sc->rx.buf_hold = bf;
+ }
+@@ -106,7 +108,7 @@ static void ath_opmode_init(struct ath_s
  }
  
- int __init regulatory_init(void)
---- a/net/wireless/sme.c
-+++ b/net/wireless/sme.c
-@@ -34,8 +34,10 @@ struct cfg80211_conn {
-               CFG80211_CONN_SCAN_AGAIN,
-               CFG80211_CONN_AUTHENTICATE_NEXT,
-               CFG80211_CONN_AUTHENTICATING,
-+              CFG80211_CONN_AUTH_FAILED,
-               CFG80211_CONN_ASSOCIATE_NEXT,
-               CFG80211_CONN_ASSOCIATING,
-+              CFG80211_CONN_ASSOC_FAILED,
-               CFG80211_CONN_DEAUTH,
-               CFG80211_CONN_CONNECTED,
-       } state;
-@@ -164,6 +166,8 @@ static int cfg80211_conn_do_work(struct 
-                                         NULL, 0,
-                                         params->key, params->key_len,
-                                         params->key_idx, NULL, 0);
-+      case CFG80211_CONN_AUTH_FAILED:
-+              return -ENOTCONN;
-       case CFG80211_CONN_ASSOCIATE_NEXT:
-               BUG_ON(!rdev->ops->assoc);
-               wdev->conn->state = CFG80211_CONN_ASSOCIATING;
-@@ -188,10 +192,17 @@ static int cfg80211_conn_do_work(struct 
-                                            WLAN_REASON_DEAUTH_LEAVING,
-                                            false);
-               return err;
-+      case CFG80211_CONN_ASSOC_FAILED:
-+              cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
-+                                   NULL, 0,
-+                                   WLAN_REASON_DEAUTH_LEAVING, false);
-+              return -ENOTCONN;
-       case CFG80211_CONN_DEAUTH:
-               cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
-                                    NULL, 0,
-                                    WLAN_REASON_DEAUTH_LEAVING, false);
-+              /* free directly, disconnected event already sent */
-+              cfg80211_sme_free(wdev);
-               return 0;
-       default:
-               return 0;
-@@ -371,7 +382,7 @@ bool cfg80211_sme_rx_assoc_resp(struct w
-               return true;
+ 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
        }
  
--      wdev->conn->state = CFG80211_CONN_DEAUTH;
-+      wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
-       schedule_work(&rdev->conn_work);
-       return false;
+       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;
  }
-@@ -383,7 +394,13 @@ void cfg80211_sme_deauth(struct wireless
+@@ -442,7 +445,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) {
+-              ath_rx_buf_link(sc, bf);
++              ath_rx_buf_link(sc, bf, false);
+       }
  
- void cfg80211_sme_auth_timeout(struct wireless_dev *wdev)
- {
--      cfg80211_sme_free(wdev);
-+      struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
-+
-+      if (!wdev->conn)
-+              return;
+       /* 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:
+               }
+ requeue:
+               list_add_tail(&bf->list, &sc->rx.rxbuf);
+-              if (flush)
+-                      continue;
+               if (edma) {
+-                      ath_rx_edma_buf_link(sc, qtype);
++                      ath_rx_edma_buf_link(sc, qtype, flush);
+               } else {
+-                      ath_rx_buf_relink(sc, bf);
+-                      ath9k_hw_rxena(ah);
++                      ath_rx_buf_relink(sc, bf, flush);
++                      if (!flush)
++                              ath9k_hw_rxena(ah);
+               }
 +
-+      wdev->conn->state = CFG80211_CONN_AUTH_FAILED;
-+      schedule_work(&rdev->conn_work);
++              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
+ };
  
- void cfg80211_sme_disassoc(struct wireless_dev *wdev)
-@@ -399,7 +416,13 @@ void cfg80211_sme_disassoc(struct wirele
+ 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);
  
- void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
- {
--      cfg80211_sme_disassoc(wdev);
-+      struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
++      /* Will be cleared in ath9k_start() */
++      set_bit(ATH_OP_INVALID, &common->op_flags);
 +
-+      if (!wdev->conn)
-+              return;
+       /* 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 
+ {
+       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);
+-      /* 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);
+       }
+       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;
 +
-+      wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
-+      schedule_work(&rdev->conn_work);
- }
+       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;
+-              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)
  
- static int cfg80211_sme_connect(struct wireless_dev *wdev,
+       /* re-enable hardware interrupt */
+       ath9k_hw_enable_interrupts(ah);
++      if (sc->intrstatus)
++              tasklet_schedule(&sc->intr_tq);
++
+ 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;
+       if (status & SCHED_INTR)
+               sched = true;