mac80211: update to latest version from trunk
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 8 Oct 2011 18:11:25 +0000 (18:11 +0000)
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 8 Oct 2011 18:11:25 +0000 (18:11 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@28388 3c298f89-4303-0410-b956-a3cf2f4a3e73

57 files changed:
package/mac80211/Makefile
package/mac80211/files/lib/wifi/mac80211.sh
package/mac80211/patches/018-revert_printk_va_format.patch
package/mac80211/patches/120-pr_fmt_warnings.patch
package/mac80211/patches/130-fix_sublevel_check.patch [new file with mode: 0644]
package/mac80211/patches/140-mesh_pathtbl_backport.patch [new file with mode: 0644]
package/mac80211/patches/300-pending_work.patch
package/mac80211/patches/310-ibss_ht.patch
package/mac80211/patches/400-ath_move_debug_code.patch
package/mac80211/patches/406-regd_no_assoc_hints.patch
package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
package/mac80211/patches/511-ath9k_increase_bcbuf.patch
package/mac80211/patches/512-ath9k_reduce_rxbuf.patch
package/mac80211/patches/513-ath9k_channelbw_debugfs.patch
package/mac80211/patches/520-mac80211_minstrel_ht_aggr_delay.patch
package/mac80211/patches/522-mac80211_reduce_txqueuelen.patch [new file with mode: 0644]
package/mac80211/patches/530-mac80211_cur_txpower.patch
package/mac80211/patches/531-ath9k_cur_txpower.patch
package/mac80211/patches/540-ath9k_limit_qlen.patch [moved from package/mac80211/patches/550-ath9k_limit_qlen.patch with 80% similarity]
package/mac80211/patches/540-ath9k_txkeyidx_u8.patch [deleted file]
package/mac80211/patches/541-ath9k_aggr_queue_cleanup.patch [deleted file]
package/mac80211/patches/541-ath9k_sw_retry_reduce.patch [moved from package/mac80211/patches/551-ath9k_sw_retry_reduce.patch with 84% similarity]
package/mac80211/patches/542-ath9k_move_seqno.patch [deleted file]
package/mac80211/patches/543-ath9k_move_seqno_alloc.patch [deleted file]
package/mac80211/patches/544-ath9k_defer_buffer_setup.patch [deleted file]
package/mac80211/patches/545-ath9k_aggr_padding_fix.patch [deleted file]
package/mac80211/patches/546-ath9k_retry_cache_sync.patch [deleted file]
package/mac80211/patches/550-ath9k_ar9280_cold_reset.patch [moved from package/mac80211/patches/593-ath9k_ar9280_cold_reset.patch with 100% similarity]
package/mac80211/patches/551-ath9k_fix_keymiss_handling.patch [new file with mode: 0644]
package/mac80211/patches/552-ath9k_fix_phyerror.patch [new file with mode: 0644]
package/mac80211/patches/560-mac80211_defer_bar_tx.patch [deleted file]
package/mac80211/patches/560-minstrel_ht_optimize.patch [new file with mode: 0644]
package/mac80211/patches/561-mac80211_tx_status.patch [new file with mode: 0644]
package/mac80211/patches/562-ath9k_tx_status.patch [new file with mode: 0644]
package/mac80211/patches/570-ath9k_fix_ack_cts_timeout.patch [deleted file]
package/mac80211/patches/570-ath9k_tx_stop_failure_debug.patch [new file with mode: 0644]
package/mac80211/patches/571-ath9k_reset_debug.patch [new file with mode: 0644]
package/mac80211/patches/572-ath9k_fix_tx_retry.patch [new file with mode: 0644]
package/mac80211/patches/573-ath9k_fix_tx_flush_bar.patch [new file with mode: 0644]
package/mac80211/patches/580-ath9k_cleanup_set_interrupt.patch [new file with mode: 0644]
package/mac80211/patches/580-ath9k_remove_common_chainmask.patch [deleted file]
package/mac80211/patches/581-ath9k_cleanup_txpower_handling.patch [new file with mode: 0644]
package/mac80211/patches/581-ath9k_use_reset_work.patch [deleted file]
package/mac80211/patches/582-ath9k_merge_reset_functions.patch [deleted file]
package/mac80211/patches/582-ath9k_remove_current_rd_ext.patch [new file with mode: 0644]
package/mac80211/patches/583-ath9k_antenna_control.patch [deleted file]
package/mac80211/patches/583-ath9k_remove_eep_reg_1.patch [new file with mode: 0644]
package/mac80211/patches/584-ath9k_fix_reset.patch [deleted file]
package/mac80211/patches/585-ath9k_fix_beacon_timer.patch [deleted file]
package/mac80211/patches/586-ath9k_fix_rx_flush.patch [deleted file]
package/mac80211/patches/590-ath9k_fix_5ghz_adc_cal.patch [deleted file]
package/mac80211/patches/591-ath9k_cleanup_rx_status_rate.patch [deleted file]
package/mac80211/patches/592-ath9k_strip_initvals.patch [deleted file]
package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
package/mac80211/patches/800-b43-gpio-mask-module-option.patch
package/mac80211/patches/810-b43_no_pio.patch

index 1a04695..f22b52b 100644 (file)
@@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=mac80211
 
-PKG_VERSION:=2011-08-26
+PKG_VERSION:=2011-09-14
 PKG_RELEASE:=1
 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
-PKG_MD5SUM:=37218b56e8a30b351662087d68948825
+PKG_MD5SUM:=a5627e6079e8d0f0baf7045141503a3d
 
 PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
index 7254909..1ae0c20 100644 (file)
@@ -302,6 +302,13 @@ enable_mac80211() {
        fixed=""
        local hostapd_ctrl=""
 
+       [ -n "$country" ] && {
+               iw reg get | grep -q "^country $country:" || {
+                       iw reg set "$country"
+                       sleep 1
+               }
+       }
+
        config_get ath9k_chanbw "$device" ath9k_chanbw
        [ -n "$ath9k_chanbw" -a -d /sys/kernel/debug/ieee80211/$phy/ath9k ] && echo "$ath9k_chanbw" > /sys/kernel/debug/ieee80211/$phy/ath9k/chanbw
 
index 6aff41a..646ed1c 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -337,83 +337,59 @@ static int b43_ratelimit(struct b43_wl *
+@@ -339,83 +339,59 @@ static int b43_ratelimit(struct b43_wl *
  
  void b43info(struct b43_wl *wl, const char *fmt, ...)
  {
index 9b69328..920398e 100644 (file)
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/etherdevice.h>
+--- a/compat/crc8.c
++++ b/compat/crc8.c
+@@ -14,6 +14,7 @@
+  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  */
++#undef pr_fmt
+ #define pr_fmt(fmt)           KBUILD_MODNAME ": " fmt
+ #include <linux/module.h>
diff --git a/package/mac80211/patches/130-fix_sublevel_check.patch b/package/mac80211/patches/130-fix_sublevel_check.patch
new file mode 100644 (file)
index 0000000..b233311
--- /dev/null
@@ -0,0 +1,22 @@
+--- a/config.mk
++++ b/config.mk
+@@ -20,16 +20,16 @@ COMPAT_LATEST_VERSION = 1
+ KERNEL_VERSION := $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^\([0-9]\)\..*/\1/p')
+ ifneq ($(KERNEL_VERSION),2)
+-KERNEL_SUBLEVEL := $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^3\.\([0-9]\+\).*/\1/p')
++COMPAT_KERNEL_SUBLEVEL := $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^3\.\([0-9]\+\).*/\1/p')
+ else
+ COMPAT_26LATEST_VERSION = 39
+ KERNEL_26SUBLEVEL := $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^2\.6\.\([0-9]\+\).*/\1/p')
+ COMPAT_26VERSIONS := $(shell I=$(COMPAT_26LATEST_VERSION); while [ "$$I" -gt $(KERNEL_26SUBLEVEL) ]; do echo $$I; I=$$(($$I - 1)); done)
+ $(foreach ver,$(COMPAT_26VERSIONS),$(eval CONFIG_COMPAT_KERNEL_2_6_$(ver)=y))
+-KERNEL_SUBLEVEL := -1
++COMPAT_KERNEL_SUBLEVEL := -1
+ endif
+-COMPAT_VERSIONS := $(shell I=$(COMPAT_LATEST_VERSION); while [ "$$I" -gt $(KERNEL_SUBLEVEL) ]; do echo $$I; I=$$(($$I - 1)); done)
++COMPAT_VERSIONS := $(shell I=$(COMPAT_LATEST_VERSION); while [ "$$I" -gt $(COMPAT_KERNEL_SUBLEVEL) ]; do echo $$I; I=$$(($$I - 1)); done)
+ $(foreach ver,$(COMPAT_VERSIONS),$(eval CONFIG_COMPAT_KERNEL_3_$(ver)=y))
+ ifdef CONFIG_COMPAT_KERNEL_2_6_24
diff --git a/package/mac80211/patches/140-mesh_pathtbl_backport.patch b/package/mac80211/patches/140-mesh_pathtbl_backport.patch
new file mode 100644 (file)
index 0000000..aae5559
--- /dev/null
@@ -0,0 +1,10 @@
+--- a/net/mac80211/mesh_pathtbl.c
++++ b/net/mac80211/mesh_pathtbl.c
+@@ -844,7 +844,6 @@ static void table_flush_by_iface(struct 
+       struct hlist_node *p;
+       int i;
+-      WARN_ON(!rcu_read_lock_held());
+       for_each_mesh_entry(tbl, p, node, i) {
+               mpath = node->mpath;
+               if (mpath->sdata != sdata)
index 2f403b8..d3bcece 100644 (file)
+--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+@@ -170,33 +170,104 @@ static bool ar9002_hw_get_isr(struct ath
+       return true;
+ }
+-static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
+-                                bool is_firstseg, bool is_lastseg,
+-                                const void *ds0, dma_addr_t buf_addr,
+-                                unsigned int qcu)
++static void
++ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
+ {
+       struct ar5416_desc *ads = AR5416DESC(ds);
++      u32 ctl1, ctl6;
+-      ads->ds_data = buf_addr;
+-
+-      if (is_firstseg) {
+-              ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
+-      } else if (is_lastseg) {
+-              ads->ds_ctl0 = 0;
+-              ads->ds_ctl1 = seglen;
+-              ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+-              ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+-      } else {
+-              ads->ds_ctl0 = 0;
+-              ads->ds_ctl1 = seglen | AR_TxMore;
+-              ads->ds_ctl2 = 0;
+-              ads->ds_ctl3 = 0;
+-      }
+       ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+       ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+       ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+       ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+       ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
++
++      ACCESS_ONCE(ads->ds_link) = i->link;
++      ACCESS_ONCE(ads->ds_data) = i->buf_addr[0];
++
++      ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore);
++      ctl6 = SM(i->keytype, AR_EncrType);
++
++      if (AR_SREV_9285(ah)) {
++              ads->ds_ctl8 = 0;
++              ads->ds_ctl9 = 0;
++              ads->ds_ctl10 = 0;
++              ads->ds_ctl11 = 0;
++      }
++
++      if ((i->is_first || i->is_last) &&
++          i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) {
++              ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0)
++                      | set11nTries(i->rates, 1)
++                      | set11nTries(i->rates, 2)
++                      | set11nTries(i->rates, 3)
++                      | (i->dur_update ? AR_DurUpdateEna : 0)
++                      | SM(0, AR_BurstDur);
++
++              ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0)
++                      | set11nRate(i->rates, 1)
++                      | set11nRate(i->rates, 2)
++                      | set11nRate(i->rates, 3);
++      } else {
++              ACCESS_ONCE(ads->ds_ctl2) = 0;
++              ACCESS_ONCE(ads->ds_ctl3) = 0;
++      }
++
++      if (!i->is_first) {
++              ACCESS_ONCE(ads->ds_ctl0) = 0;
++              ACCESS_ONCE(ads->ds_ctl1) = ctl1;
++              ACCESS_ONCE(ads->ds_ctl6) = ctl6;
++              return;
++      }
++
++      ctl1 |= (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0)
++              | SM(i->type, AR_FrameType)
++              | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
++              | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
++              | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
++
++      switch (i->aggr) {
++      case AGGR_BUF_FIRST:
++              ctl6 |= SM(i->aggr_len, AR_AggrLen);
++              /* fall through */
++      case AGGR_BUF_MIDDLE:
++              ctl1 |= AR_IsAggr | AR_MoreAggr;
++              ctl6 |= SM(i->ndelim, AR_PadDelim);
++              break;
++      case AGGR_BUF_LAST:
++              ctl1 |= AR_IsAggr;
++              break;
++      case AGGR_BUF_NONE:
++              break;
++      }
++
++      ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
++              | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
++              | SM(i->txpower, AR_XmitPower)
++              | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
++              | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
++              | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
++              | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
++              | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
++                 (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
++
++      ACCESS_ONCE(ads->ds_ctl1) = ctl1;
++      ACCESS_ONCE(ads->ds_ctl6) = ctl6;
++
++      if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST)
++              return;
++
++      ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0)
++              | set11nPktDurRTSCTS(i->rates, 1);
++
++      ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2)
++              | set11nPktDurRTSCTS(i->rates, 3);
++
++      ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0)
++              | set11nRateFlags(i->rates, 1)
++              | set11nRateFlags(i->rates, 2)
++              | set11nRateFlags(i->rates, 3)
++              | SM(i->rtscts_rate, AR_RTSCTSRate);
+ }
+ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
+@@ -271,145 +342,6 @@ static int ar9002_hw_proc_txdesc(struct 
+       return 0;
+ }
+-static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
+-                                  u32 pktLen, enum ath9k_pkt_type type,
+-                                  u32 txPower, u8 keyIx,
+-                                  enum ath9k_key_type keyType, u32 flags)
+-{
+-      struct ar5416_desc *ads = AR5416DESC(ds);
+-
+-      if (txPower > 63)
+-              txPower = 63;
+-
+-      ads->ds_ctl0 = (pktLen & AR_FrameLen)
+-              | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+-              | SM(txPower, AR_XmitPower)
+-              | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+-              | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+-              | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
+-
+-      ads->ds_ctl1 =
+-              (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
+-              | SM(type, AR_FrameType)
+-              | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+-              | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+-              | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+-
+-      ads->ds_ctl6 = SM(keyType, AR_EncrType);
+-
+-      if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
+-              ads->ds_ctl8 = 0;
+-              ads->ds_ctl9 = 0;
+-              ads->ds_ctl10 = 0;
+-              ads->ds_ctl11 = 0;
+-      }
+-}
+-
+-static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
+-{
+-      struct ar5416_desc *ads = AR5416DESC(ds);
+-
+-      if (val)
+-              ads->ds_ctl0 |= AR_ClrDestMask;
+-      else
+-              ads->ds_ctl0 &= ~AR_ClrDestMask;
+-}
+-
+-static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
+-                                        void *lastds,
+-                                        u32 durUpdateEn, u32 rtsctsRate,
+-                                        u32 rtsctsDuration,
+-                                        struct ath9k_11n_rate_series series[],
+-                                        u32 nseries, u32 flags)
+-{
+-      struct ar5416_desc *ads = AR5416DESC(ds);
+-      struct ar5416_desc *last_ads = AR5416DESC(lastds);
+-      u32 ds_ctl0;
+-
+-      if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
+-              ds_ctl0 = ads->ds_ctl0;
+-
+-              if (flags & ATH9K_TXDESC_RTSENA) {
+-                      ds_ctl0 &= ~AR_CTSEnable;
+-                      ds_ctl0 |= AR_RTSEnable;
+-              } else {
+-                      ds_ctl0 &= ~AR_RTSEnable;
+-                      ds_ctl0 |= AR_CTSEnable;
+-              }
+-
+-              ads->ds_ctl0 = ds_ctl0;
+-      } else {
+-              ads->ds_ctl0 =
+-                      (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
+-      }
+-
+-      ads->ds_ctl2 = set11nTries(series, 0)
+-              | set11nTries(series, 1)
+-              | set11nTries(series, 2)
+-              | set11nTries(series, 3)
+-              | (durUpdateEn ? AR_DurUpdateEna : 0)
+-              | SM(0, AR_BurstDur);
+-
+-      ads->ds_ctl3 = set11nRate(series, 0)
+-              | set11nRate(series, 1)
+-              | set11nRate(series, 2)
+-              | set11nRate(series, 3);
+-
+-      ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
+-              | set11nPktDurRTSCTS(series, 1);
+-
+-      ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
+-              | set11nPktDurRTSCTS(series, 3);
+-
+-      ads->ds_ctl7 = set11nRateFlags(series, 0)
+-              | set11nRateFlags(series, 1)
+-              | set11nRateFlags(series, 2)
+-              | set11nRateFlags(series, 3)
+-              | SM(rtsctsRate, AR_RTSCTSRate);
+-      last_ads->ds_ctl2 = ads->ds_ctl2;
+-      last_ads->ds_ctl3 = ads->ds_ctl3;
+-}
+-
+-static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
+-                                      u32 aggrLen)
+-{
+-      struct ar5416_desc *ads = AR5416DESC(ds);
+-
+-      ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+-      ads->ds_ctl6 &= ~AR_AggrLen;
+-      ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
+-}
+-
+-static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
+-                                       u32 numDelims)
+-{
+-      struct ar5416_desc *ads = AR5416DESC(ds);
+-      unsigned int ctl6;
+-
+-      ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+-
+-      ctl6 = ads->ds_ctl6;
+-      ctl6 &= ~AR_PadDelim;
+-      ctl6 |= SM(numDelims, AR_PadDelim);
+-      ads->ds_ctl6 = ctl6;
+-}
+-
+-static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
+-{
+-      struct ar5416_desc *ads = AR5416DESC(ds);
+-
+-      ads->ds_ctl1 |= AR_IsAggr;
+-      ads->ds_ctl1 &= ~AR_MoreAggr;
+-      ads->ds_ctl6 &= ~AR_PadDelim;
+-}
+-
+-static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
+-{
+-      struct ar5416_desc *ads = AR5416DESC(ds);
+-
+-      ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
+-}
+-
+ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+                         u32 size, u32 flags)
+ {
+@@ -433,13 +365,6 @@ void ar9002_hw_attach_mac_ops(struct ath
+       ops->rx_enable = ar9002_hw_rx_enable;
+       ops->set_desc_link = ar9002_hw_set_desc_link;
+       ops->get_isr = ar9002_hw_get_isr;
+-      ops->fill_txdesc = ar9002_hw_fill_txdesc;
++      ops->set_txdesc = ar9002_set_txdesc;
+       ops->proc_txdesc = ar9002_hw_proc_txdesc;
+-      ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
+-      ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
+-      ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
+-      ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
+-      ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
+-      ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
+-      ops->set_clrdmask = ar9002_hw_set_clrdmask;
+ }
+--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+@@ -652,8 +652,9 @@ static void ar9003_hw_detect_outlier(int
+                       outlier_idx = max_idx;
+               else
+                       outlier_idx = min_idx;
++
++              mp_coeff[outlier_idx] = mp_avg;
+       }
+-      mp_coeff[outlier_idx] = mp_avg;
+ }
+ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
+@@ -884,6 +885,7 @@ static bool ar9003_hw_init_cal(struct at
+       if (txiqcal_done)
+               ar9003_hw_tx_iq_cal_post_proc(ah);
++      ath9k_hw_loadnf(ah, chan);
+       ath9k_hw_start_nfcal(ah, true);
+       /* Initialize list pointers */
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -21,6 +21,132 @@ static void ar9003_hw_rx_enable(struct a
+       REG_WRITE(hw, AR_CR, 0);
+ }
++static void
++ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
++{
++      struct ar9003_txc *ads = ds;
++      int checksum = 0;
++      u32 val, ctl12, ctl17;
++
++      val = (ATHEROS_VENDOR_ID << AR_DescId_S) |
++            (1 << AR_TxRxDesc_S) |
++            (1 << AR_CtrlStat_S) |
++            (i->qcu << AR_TxQcuNum_S) | 0x17;
++
++      checksum += val;
++      ACCESS_ONCE(ads->info) = val;
++
++      checksum += i->link;
++      ACCESS_ONCE(ads->link) = i->link;
++
++      checksum += i->buf_addr[0];
++      ACCESS_ONCE(ads->data0) = i->buf_addr[0];
++      checksum += i->buf_addr[1];
++      ACCESS_ONCE(ads->data1) = i->buf_addr[1];
++      checksum += i->buf_addr[2];
++      ACCESS_ONCE(ads->data2) = i->buf_addr[2];
++      checksum += i->buf_addr[3];
++      ACCESS_ONCE(ads->data3) = i->buf_addr[3];
++
++      checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen);
++      ACCESS_ONCE(ads->ctl3) = val;
++      checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen);
++      ACCESS_ONCE(ads->ctl5) = val;
++      checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen);
++      ACCESS_ONCE(ads->ctl7) = val;
++      checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen);
++      ACCESS_ONCE(ads->ctl9) = val;
++
++      checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff);
++      ACCESS_ONCE(ads->ctl10) = checksum;
++
++      if (i->is_first || i->is_last) {
++              ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0)
++                      | set11nTries(i->rates, 1)
++                      | set11nTries(i->rates, 2)
++                      | set11nTries(i->rates, 3)
++                      | (i->dur_update ? AR_DurUpdateEna : 0)
++                      | SM(0, AR_BurstDur);
++
++              ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0)
++                      | set11nRate(i->rates, 1)
++                      | set11nRate(i->rates, 2)
++                      | set11nRate(i->rates, 3);
++      } else {
++              ACCESS_ONCE(ads->ctl13) = 0;
++              ACCESS_ONCE(ads->ctl14) = 0;
++      }
++
++      ads->ctl20 = 0;
++      ads->ctl21 = 0;
++      ads->ctl22 = 0;
++
++      ctl17 = SM(i->keytype, AR_EncrType);
++      if (!i->is_first) {
++              ACCESS_ONCE(ads->ctl11) = 0;
++              ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore;
++              ACCESS_ONCE(ads->ctl15) = 0;
++              ACCESS_ONCE(ads->ctl16) = 0;
++              ACCESS_ONCE(ads->ctl17) = ctl17;
++              ACCESS_ONCE(ads->ctl18) = 0;
++              ACCESS_ONCE(ads->ctl19) = 0;
++              return;
++      }
++
++      ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
++              | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
++              | SM(i->txpower, AR_XmitPower)
++              | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
++              | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
++              | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
++              | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
++              | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
++                 (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
++
++      ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ?
++               SM(i->keyix, AR_DestIdx) : 0)
++              | SM(i->type, AR_FrameType)
++              | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
++              | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
++              | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
++
++      ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
++      switch (i->aggr) {
++      case AGGR_BUF_FIRST:
++              ctl17 |= SM(i->aggr_len, AR_AggrLen);
++              /* fall through */
++      case AGGR_BUF_MIDDLE:
++              ctl12 |= AR_IsAggr | AR_MoreAggr;
++              ctl17 |= SM(i->ndelim, AR_PadDelim);
++              break;
++      case AGGR_BUF_LAST:
++              ctl12 |= AR_IsAggr;
++              break;
++      case AGGR_BUF_NONE:
++              break;
++      }
++
++      val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S;
++      ctl12 |= SM(val, AR_PAPRDChainMask);
++
++      ACCESS_ONCE(ads->ctl12) = ctl12;
++      ACCESS_ONCE(ads->ctl17) = ctl17;
++
++      ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0)
++              | set11nPktDurRTSCTS(i->rates, 1);
++
++      ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2)
++              | set11nPktDurRTSCTS(i->rates, 3);
++
++      ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0)
++              | set11nRateFlags(i->rates, 1)
++              | set11nRateFlags(i->rates, 2)
++              | set11nRateFlags(i->rates, 3)
++              | SM(i->rtscts_rate, AR_RTSCTSRate);
++
++      ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
++}
++
+ static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
+ {
+       int checksum;
+@@ -185,47 +311,6 @@ static bool ar9003_hw_get_isr(struct ath
+       return true;
+ }
+-static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
+-                                bool is_firstseg, bool is_lastseg,
+-                                const void *ds0, dma_addr_t buf_addr,
+-                                unsigned int qcu)
+-{
+-      struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+-      unsigned int descid = 0;
+-
+-      ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
+-                                   (1 << AR_TxRxDesc_S) |
+-                                   (1 << AR_CtrlStat_S) |
+-                                   (qcu << AR_TxQcuNum_S) | 0x17;
+-
+-      ads->data0 = buf_addr;
+-      ads->data1 = 0;
+-      ads->data2 = 0;
+-      ads->data3 = 0;
+-
+-      ads->ctl3 = (seglen << AR_BufLen_S);
+-      ads->ctl3 &= AR_BufLen;
+-
+-      /* Fill in pointer checksum and descriptor id */
+-      ads->ctl10 = ar9003_calc_ptr_chksum(ads);
+-      ads->ctl10 |= (descid << AR_TxDescId_S);
+-
+-      if (is_firstseg) {
+-              ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
+-      } else if (is_lastseg) {
+-              ads->ctl11 = 0;
+-              ads->ctl12 = 0;
+-              ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
+-              ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
+-      } else {
+-              /* XXX Intermediate descriptor in a multi-descriptor frame.*/
+-              ads->ctl11 = 0;
+-              ads->ctl12 = AR_TxMore;
+-              ads->ctl13 = 0;
+-              ads->ctl14 = 0;
+-      }
+-}
+-
+ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
+                                struct ath_tx_status *ts)
+ {
+@@ -310,161 +395,6 @@ static int ar9003_hw_proc_txdesc(struct 
+       return 0;
+ }
+-static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
+-              u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
+-              u8 keyIx, enum ath9k_key_type keyType, u32 flags)
+-{
+-      struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+-
+-      if (txpower > ah->txpower_limit)
+-              txpower = ah->txpower_limit;
+-
+-      if (txpower > 63)
+-              txpower = 63;
+-
+-      ads->ctl11 = (pktlen & AR_FrameLen)
+-              | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+-              | SM(txpower, AR_XmitPower)
+-              | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+-              | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+-              | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
+-
+-      ads->ctl12 =
+-              (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
+-              | SM(type, AR_FrameType)
+-              | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+-              | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+-              | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+-
+-      ads->ctl17 = SM(keyType, AR_EncrType) |
+-                   (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
+-      ads->ctl18 = 0;
+-      ads->ctl19 = AR_Not_Sounding;
+-
+-      ads->ctl20 = 0;
+-      ads->ctl21 = 0;
+-      ads->ctl22 = 0;
+-}
+-
+-static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
+-{
+-      struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+-
+-      if (val)
+-              ads->ctl11 |= AR_ClrDestMask;
+-      else
+-              ads->ctl11 &= ~AR_ClrDestMask;
+-}
+-
+-static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
+-                                        void *lastds,
+-                                        u32 durUpdateEn, u32 rtsctsRate,
+-                                        u32 rtsctsDuration,
+-                                        struct ath9k_11n_rate_series series[],
+-                                        u32 nseries, u32 flags)
+-{
+-      struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+-      struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
+-      u_int32_t ctl11;
+-
+-      if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
+-              ctl11 = ads->ctl11;
+-
+-              if (flags & ATH9K_TXDESC_RTSENA) {
+-                      ctl11 &= ~AR_CTSEnable;
+-                      ctl11 |= AR_RTSEnable;
+-              } else {
+-                      ctl11 &= ~AR_RTSEnable;
+-                      ctl11 |= AR_CTSEnable;
+-              }
+-
+-              ads->ctl11 = ctl11;
+-      } else {
+-              ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
+-      }
+-
+-      ads->ctl13 = set11nTries(series, 0)
+-              |  set11nTries(series, 1)
+-              |  set11nTries(series, 2)
+-              |  set11nTries(series, 3)
+-              |  (durUpdateEn ? AR_DurUpdateEna : 0)
+-              |  SM(0, AR_BurstDur);
+-
+-      ads->ctl14 = set11nRate(series, 0)
+-              |  set11nRate(series, 1)
+-              |  set11nRate(series, 2)
+-              |  set11nRate(series, 3);
+-
+-      ads->ctl15 = set11nPktDurRTSCTS(series, 0)
+-              |  set11nPktDurRTSCTS(series, 1);
+-
+-      ads->ctl16 = set11nPktDurRTSCTS(series, 2)
+-              |  set11nPktDurRTSCTS(series, 3);
+-
+-      ads->ctl18 = set11nRateFlags(series, 0)
+-              |  set11nRateFlags(series, 1)
+-              |  set11nRateFlags(series, 2)
+-              |  set11nRateFlags(series, 3)
+-              | SM(rtsctsRate, AR_RTSCTSRate);
+-      ads->ctl19 = AR_Not_Sounding;
+-
+-      last_ads->ctl13 = ads->ctl13;
+-      last_ads->ctl14 = ads->ctl14;
+-}
+-
+-static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
+-                                      u32 aggrLen)
+-{
+-      struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+-
+-      ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
+-
+-      ads->ctl17 &= ~AR_AggrLen;
+-      ads->ctl17 |= SM(aggrLen, AR_AggrLen);
+-}
+-
+-static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
+-                                       u32 numDelims)
+-{
+-      struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+-      unsigned int ctl17;
+-
+-      ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
+-
+-      /*
+-       * We use a stack variable to manipulate ctl6 to reduce uncached
+-       * read modify, modfiy, write.
+-       */
+-      ctl17 = ads->ctl17;
+-      ctl17 &= ~AR_PadDelim;
+-      ctl17 |= SM(numDelims, AR_PadDelim);
+-      ads->ctl17 = ctl17;
+-}
+-
+-static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
+-{
+-      struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+-
+-      ads->ctl12 |= AR_IsAggr;
+-      ads->ctl12 &= ~AR_MoreAggr;
+-      ads->ctl17 &= ~AR_PadDelim;
+-}
+-
+-static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
+-{
+-      struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+-
+-      ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
+-}
+-
+-void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains)
+-{
+-      struct ar9003_txc *ads = ds;
+-
+-      ads->ctl12 |= SM(chains, AR_PAPRDChainMask);
+-}
+-EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc);
+-
+ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
+ {
+       struct ath_hw_ops *ops = ath9k_hw_ops(hw);
+@@ -472,15 +402,8 @@ void ar9003_hw_attach_mac_ops(struct ath
+       ops->rx_enable = ar9003_hw_rx_enable;
+       ops->set_desc_link = ar9003_hw_set_desc_link;
+       ops->get_isr = ar9003_hw_get_isr;
+-      ops->fill_txdesc = ar9003_hw_fill_txdesc;
++      ops->set_txdesc = ar9003_set_txdesc;
+       ops->proc_txdesc = ar9003_hw_proc_txdesc;
+-      ops->set11n_txdesc = ar9003_hw_set11n_txdesc;
+-      ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario;
+-      ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first;
+-      ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle;
+-      ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
+-      ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
+-      ops->set_clrdmask = ar9003_hw_set_clrdmask;
+ }
+ void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -87,17 +87,14 @@ struct ath_config {
+  * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
+  * @BUF_AGGR: Indicates whether the buffer can be aggregated
+  *    (used in aggregation scheduling)
+- * @BUF_XRETRY: To denote excessive retries of the buffer
+  */
+ enum buffer_type {
+       BUF_AMPDU               = BIT(0),
+       BUF_AGGR                = BIT(1),
+-      BUF_XRETRY              = BIT(2),
+ };
+ #define bf_isampdu(bf)                (bf->bf_state.bf_type & BUF_AMPDU)
+ #define bf_isaggr(bf)         (bf->bf_state.bf_type & BUF_AGGR)
+-#define bf_isxretried(bf)     (bf->bf_state.bf_type & BUF_XRETRY)
+ #define ATH_TXSTATUS_RING_SIZE 64
+@@ -216,6 +213,7 @@ struct ath_frame_info {
+ struct ath_buf_state {
+       u8 bf_type;
+       u8 bfs_paprd;
++      u8 ndelim;
+       u16 seqno;
+       unsigned long bfs_paprd_timestamp;
+ };
+@@ -230,7 +228,6 @@ struct ath_buf {
+       dma_addr_t bf_daddr;            /* physical addr of desc */
+       dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
+       bool bf_stale;
+-      u16 bf_flags;
+       struct ath_buf_state bf_state;
+ };
+@@ -277,8 +274,7 @@ struct ath_tx_control {
+ };
+ #define ATH_TX_ERROR        0x01
+-#define ATH_TX_XRETRY       0x02
+-#define ATH_TX_BAR          0x04
++#define ATH_TX_BAR          0x02
+ /**
+  * @txq_map:  Index is mac80211 queue number.  This is
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -73,44 +73,39 @@ static void ath_beacon_setup(struct ath_
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+-      struct ath_desc *ds;
+-      struct ath9k_11n_rate_series series[4];
+-      int flags, ctsrate = 0, ctsduration = 0;
++      struct ath_tx_info info;
+       struct ieee80211_supported_band *sband;
++      u8 chainmask = ah->txchainmask;
+       u8 rate = 0;
+       ath9k_reset_beacon_status(sc);
+-      ds = bf->bf_desc;
+-      flags = ATH9K_TXDESC_NOACK;
+-
+-      ds->ds_link = 0;
+-
+       sband = &sc->sbands[common->hw->conf.channel->band];
+       rate = sband->bitrates[rateidx].hw_value;
+       if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+               rate |= sband->bitrates[rateidx].hw_value_short;
+-      ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
+-                             ATH9K_PKT_TYPE_BEACON,
+-                             MAX_RATE_POWER,
+-                             ATH9K_TXKEYIX_INVALID,
+-                             ATH9K_KEY_TYPE_CLEAR,
+-                             flags);
+-
+-      /* NB: beacon's BufLen must be a multiple of 4 bytes */
+-      ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
+-                          true, true, ds, bf->bf_buf_addr,
+-                          sc->beacon.beaconq);
+-
+-      memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
+-      series[0].Tries = 1;
+-      series[0].Rate = rate;
+-      series[0].ChSel = ath_txchainmask_reduction(sc,
+-                      ah->txchainmask, series[0].Rate);
+-      series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
+-      ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
+-                                   series, 4, 0);
++      memset(&info, 0, sizeof(info));
++      info.pkt_len = skb->len + FCS_LEN;
++      info.type = ATH9K_PKT_TYPE_BEACON;
++      info.txpower = MAX_RATE_POWER;
++      info.keyix = ATH9K_TXKEYIX_INVALID;
++      info.keytype = ATH9K_KEY_TYPE_CLEAR;
++      info.flags = ATH9K_TXDESC_NOACK;
++
++      info.buf_addr[0] = bf->bf_buf_addr;
++      info.buf_len[0] = roundup(skb->len, 4);
++
++      info.is_first = true;
++      info.is_last = true;
++
++      info.qcu = sc->beacon.beaconq;
++
++      info.rates[0].Tries = 1;
++      info.rates[0].Rate = rate;
++      info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate);
++
++      ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
+ }
+ static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
+@@ -517,6 +512,7 @@ static void ath_beacon_config_ap(struct 
+       /* Set the computed AP beacon timers */
+       ath9k_hw_disable_interrupts(ah);
++      sc->sc_flags |= SC_OP_TSF_RESET;
+       ath9k_beacon_init(sc, nexttbtt, intval);
+       sc->beacon.bmisscnt = 0;
+       ath9k_hw_set_interrupts(ah, ah->imask);
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -826,7 +826,8 @@ static ssize_t read_file_misc(struct fil
+ }
+ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+-                     struct ath_tx_status *ts, struct ath_txq *txq)
++                     struct ath_tx_status *ts, struct ath_txq *txq,
++                     unsigned int flags)
+ {
+ #define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\
+                       [sc->debug.tsidx].c)
+@@ -836,12 +837,12 @@ void ath_debug_stat_tx(struct ath_softc 
+       sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
+       if (bf_isampdu(bf)) {
+-              if (bf_isxretried(bf))
++              if (flags & ATH_TX_BAR)
+                       TX_STAT_INC(qnum, a_xretries);
+               else
+                       TX_STAT_INC(qnum, a_completed);
+       } else {
+-              if (bf_isxretried(bf))
++              if (ts->ts_status & ATH9K_TXERR_XRETRY)
+                       TX_STAT_INC(qnum, xretries);
+               else
+                       TX_STAT_INC(qnum, completed);
+--- a/drivers/net/wireless/ath/ath9k/debug.h
++++ b/drivers/net/wireless/ath/ath9k/debug.h
+@@ -230,7 +230,8 @@ int ath9k_init_debug(struct ath_hw *ah);
+ void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
+ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
+ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+-                     struct ath_tx_status *ts, struct ath_txq *txq);
++                     struct ath_tx_status *ts, struct ath_txq *txq,
++                     unsigned int flags);
+ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
+ #else
+@@ -252,7 +253,8 @@ static inline void ath_debug_stat_interr
+ static inline void ath_debug_stat_tx(struct ath_softc *sc,
+                                    struct ath_buf *bf,
+                                    struct ath_tx_status *ts,
+-                                   struct ath_txq *txq)
++                                   struct ath_txq *txq,
++                                   unsigned int flags)
+ {
+ }
+--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
+@@ -54,13 +54,10 @@ static inline bool ath9k_hw_getisr(struc
+       return ath9k_hw_ops(ah)->get_isr(ah, masked);
+ }
+-static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen,
+-                                bool is_firstseg, bool is_lastseg,
+-                                const void *ds0, dma_addr_t buf_addr,
+-                                unsigned int qcu)
++static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
++                                     struct ath_tx_info *i)
+ {
+-      ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg,
+-                                    ds0, buf_addr, qcu);
++      return ath9k_hw_ops(ah)->set_txdesc(ah, ds, i);
+ }
+ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
+@@ -69,55 +66,6 @@ static inline int ath9k_hw_txprocdesc(st
+       return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
+ }
+-static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
+-                                        u32 pktLen, enum ath9k_pkt_type type,
+-                                        u32 txPower, u32 keyIx,
+-                                        enum ath9k_key_type keyType,
+-                                        u32 flags)
+-{
+-      ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx,
+-                                    keyType, flags);
+-}
+-
+-static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
+-                                      void *lastds,
+-                                      u32 durUpdateEn, u32 rtsctsRate,
+-                                      u32 rtsctsDuration,
+-                                      struct ath9k_11n_rate_series series[],
+-                                      u32 nseries, u32 flags)
+-{
+-      ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn,
+-                                          rtsctsRate, rtsctsDuration, series,
+-                                          nseries, flags);
+-}
+-
+-static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
+-                                      u32 aggrLen)
+-{
+-      ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen);
+-}
+-
+-static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
+-                                             u32 numDelims)
+-{
+-      ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims);
+-}
+-
+-static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
+-{
+-      ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds);
+-}
+-
+-static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
+-{
+-      ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
+-}
+-
+-static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
+-{
+-      ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
+-}
+-
+ static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+               struct ath_hw_antcomb_conf *antconf)
+ {
+@@ -233,11 +181,6 @@ static inline void ath9k_hw_restore_chai
+       return ath9k_hw_private_ops(ah)->restore_chainmask(ah);
+ }
+-static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value)
+-{
+-      return ath9k_hw_private_ops(ah)->set_diversity(ah, value);
+-}
+-
+ static inline bool ath9k_hw_ani_control(struct ath_hw *ah,
+                                       enum ath9k_ani_cmd cmd, int param)
+ {
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1496,14 +1496,16 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+       }
+       ah->noise = ath9k_hw_getchan_noise(ah, chan);
++      if ((AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) ||
++          (AR_SREV_9300_20_OR_LATER(ah) && IS_CHAN_5GHZ(chan)))
++              bChannelChange = false;
++
+       if (bChannelChange &&
+           (ah->chip_fullsleep != true) &&
+           (ah->curchan != NULL) &&
+           (chan->channel != ah->curchan->channel) &&
+           ((chan->channelFlags & CHANNEL_ALL) ==
+-           (ah->curchan->channelFlags & CHANNEL_ALL)) &&
+-          (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
+-
++           (ah->curchan->channelFlags & CHANNEL_ALL))) {
+               if (ath9k_hw_channel_change(ah, chan)) {
+                       ath9k_hw_loadnf(ah, ah->curchan);
+                       ath9k_hw_start_nfcal(ah, true);
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -583,7 +583,6 @@ struct ath_hw_private_ops {
+       bool (*rfbus_req)(struct ath_hw *ah);
+       void (*rfbus_done)(struct ath_hw *ah);
+       void (*restore_chainmask)(struct ath_hw *ah);
+-      void (*set_diversity)(struct ath_hw *ah, bool value);
+       u32 (*compute_pll_control)(struct ath_hw *ah,
+                                  struct ath9k_channel *chan);
+       bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
+@@ -615,30 +614,10 @@ struct ath_hw_ops {
+                         u8 rxchainmask,
+                         bool longcal);
+       bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
+-      void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen,
+-                          bool is_firstseg, bool is_is_lastseg,
+-                          const void *ds0, dma_addr_t buf_addr,
+-                          unsigned int qcu);
++      void (*set_txdesc)(struct ath_hw *ah, void *ds,
++                         struct ath_tx_info *i);
+       int (*proc_txdesc)(struct ath_hw *ah, void *ds,
+                          struct ath_tx_status *ts);
+-      void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
+-                            u32 pktLen, enum ath9k_pkt_type type,
+-                            u32 txPower, u8 keyIx,
+-                            enum ath9k_key_type keyType,
+-                            u32 flags);
+-      void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
+-                              void *lastds,
+-                              u32 durUpdateEn, u32 rtsctsRate,
+-                              u32 rtsctsDuration,
+-                              struct ath9k_11n_rate_series series[],
+-                              u32 nseries, u32 flags);
+-      void (*set11n_aggr_first)(struct ath_hw *ah, void *ds,
+-                                u32 aggrLen);
+-      void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds,
+-                                 u32 numDelims);
+-      void (*set11n_aggr_last)(struct ath_hw *ah, void *ds);
+-      void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
+-      void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
+       void (*antdiv_comb_conf_get)(struct ath_hw *ah,
+                       struct ath_hw_antcomb_conf *antconf);
+       void (*antdiv_comb_conf_set)(struct ath_hw *ah,
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -62,18 +62,6 @@ void ath9k_hw_txstart(struct ath_hw *ah,
+ }
+ EXPORT_SYMBOL(ath9k_hw_txstart);
+-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
+-{
+-      struct ar5416_desc *ads = AR5416DESC(ds);
+-
+-      ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+-      ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+-      ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+-      ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+-      ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+-}
+-EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
+-
+ u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
+ {
+       u32 npend;
+@@ -596,7 +584,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+       else
+               rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
+-      rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
++      rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);
+       rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
+       rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -17,10 +17,6 @@
+ #ifndef MAC_H
+ #define MAC_H
+-#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ?                \
+-                              MS(ads->ds_rxstatus0, AR_RxRate) :      \
+-                              (ads->ds_rxstatus3 >> 2) & 0xFF)
+-
+ #define set11nTries(_series, _index) \
+       (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
+@@ -263,7 +259,11 @@ struct ath_desc {
+ #define ATH9K_TXDESC_VMF              0x0100
+ #define ATH9K_TXDESC_FRAG_IS_ON       0x0200
+ #define ATH9K_TXDESC_LOWRXCHAIN               0x0400
+-#define ATH9K_TXDESC_LDPC             0x00010000
++#define ATH9K_TXDESC_LDPC             0x0800
++#define ATH9K_TXDESC_CLRDMASK         0x1000
++
++#define ATH9K_TXDESC_PAPRD            0x70000
++#define ATH9K_TXDESC_PAPRD_S          16
+ #define ATH9K_RXDESC_INTREQ           0x0020
+@@ -659,6 +659,13 @@ struct ath9k_11n_rate_series {
+       u32 RateFlags;
+ };
++enum aggr_type {
++      AGGR_BUF_NONE,
++      AGGR_BUF_FIRST,
++      AGGR_BUF_MIDDLE,
++      AGGR_BUF_LAST,
++};
++
+ enum ath9k_key_type {
+       ATH9K_KEY_TYPE_CLEAR,
+       ATH9K_KEY_TYPE_WEP,
+@@ -666,6 +673,33 @@ enum ath9k_key_type {
+       ATH9K_KEY_TYPE_TKIP,
+ };
++struct ath_tx_info {
++      u8 qcu;
++
++      bool is_first;
++      bool is_last;
++
++      enum aggr_type aggr;
++      u8 ndelim;
++      u16 aggr_len;
++
++      dma_addr_t link;
++      int pkt_len;
++      u32 flags;
++
++      dma_addr_t buf_addr[4];
++      int buf_len[4];
++
++      struct ath9k_11n_rate_series rates[4];
++      u8 rtscts_rate;
++      bool dur_update;
++
++      enum ath9k_pkt_type type;
++      enum ath9k_key_type keytype;
++      u8 keyix;
++      u8 txpower;
++};
++
+ struct ath_hw;
+ struct ath9k_channel;
+ enum ath9k_int;
+@@ -673,7 +707,6 @@ enum ath9k_int;
+ u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
+ void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
+ void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
+-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
+ u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
+ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
+ bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -111,24 +111,29 @@ void ath9k_ps_wakeup(struct ath_softc *s
+ void ath9k_ps_restore(struct ath_softc *sc)
+ {
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      enum ath9k_power_mode mode;
+       unsigned long flags;
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       if (--sc->ps_usecount != 0)
+               goto unlock;
+-      spin_lock(&common->cc_lock);
+-      ath_hw_cycle_counters_update(common);
+-      spin_unlock(&common->cc_lock);
+-
+       if (sc->ps_idle)
+-              ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
++              mode = ATH9K_PM_FULL_SLEEP;
+       else if (sc->ps_enabled &&
+                !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
+                             PS_WAIT_FOR_CAB |
+                             PS_WAIT_FOR_PSPOLL_DATA |
+                             PS_WAIT_FOR_TX_ACK)))
+-              ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
++              mode = ATH9K_PM_NETWORK_SLEEP;
++      else
++              goto unlock;
++
++      spin_lock(&common->cc_lock);
++      ath_hw_cycle_counters_update(common);
++      spin_unlock(&common->cc_lock);
++
++      ath9k_hw_setpower(sc->sc_ah, mode);
+  unlock:
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+@@ -247,8 +252,8 @@ static bool ath_prepare_reset(struct ath
+       if (!flush) {
+               if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+-                      ath_rx_tasklet(sc, 0, true);
+-              ath_rx_tasklet(sc, 0, false);
++                      ath_rx_tasklet(sc, 1, true);
++              ath_rx_tasklet(sc, 1, false);
+       } else {
+               ath_flushrecv(sc);
+       }
+@@ -669,15 +674,15 @@ void ath9k_tasklet(unsigned long data)
+       u32 status = sc->intrstatus;
+       u32 rxmask;
++      ath9k_ps_wakeup(sc);
++      spin_lock(&sc->sc_pcu_lock);
++
+       if ((status & ATH9K_INT_FATAL) ||
+           (status & ATH9K_INT_BB_WATCHDOG)) {
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+-              return;
++              goto out;
+       }
+-      ath9k_ps_wakeup(sc);
+-      spin_lock(&sc->sc_pcu_lock);
+-
+       /*
+        * Only run the baseband hang check if beacons stop working in AP or
+        * IBSS mode, because it has a high false positive rate. For station
+@@ -725,6 +730,7 @@ void ath9k_tasklet(unsigned long data)
+               if (status & ATH9K_INT_GENTIMER)
+                       ath_gen_timer_isr(sc->sc_ah);
++out:
+       /* re-enable hardware interrupt */
+       ath9k_hw_enable_interrupts(ah);
+@@ -2015,6 +2021,7 @@ static void ath9k_config_bss(struct ath_
+               /* Stop ANI */
+               sc->sc_flags &= ~SC_OP_ANI_RUN;
+               del_timer_sync(&common->ani.timer);
++              memset(&sc->caldata, 0, sizeof(sc->caldata));
+       }
+ }
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -332,16 +332,16 @@ static int ath_pci_resume(struct device 
+       if ((val & 0x0000ff00) != 0)
+               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
++      ath9k_ps_wakeup(sc);
+       /* Enable LED */
+       ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
+                           AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+-      ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
++      ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
+         /*
+          * Reset key cache to sane defaults (all entries cleared) instead of
+          * semi-random values after suspend/resume.
+          */
+-      ath9k_ps_wakeup(sc);
+       ath9k_cmn_init_crypto(sc->sc_ah);
+       ath9k_ps_restore(sc);
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -1839,7 +1839,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
+                * If we're asked to flush receive queue, directly
+                * chain it back at the queue without processing it.
+                */
+-              if (flush)
++              if (sc->sc_flags & SC_OP_RXFLUSH)
+                       goto requeue_drop_frag;
+               retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
+@@ -1967,7 +1967,8 @@ requeue:
+               } else {
+                       list_move_tail(&bf->list, &sc->rx.rxbuf);
+                       ath_rx_buf_link(sc, bf);
+-                      ath9k_hw_rxena(ah);
++                      if (!flush)
++                              ath9k_hw_rxena(ah);
+               }
+       } while (1);
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -56,10 +56,9 @@ static void ath_tx_complete_buf(struct a
+                               struct ath_tx_status *ts, int txok, int sendbar);
+ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+                            struct list_head *head, bool internal);
+-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
+ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+                            struct ath_tx_status *ts, int nframes, int nbad,
+-                           int txok, bool update_rc);
++                           int txok);
+ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+                             int seqno);
+ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+@@ -263,6 +262,7 @@ static void ath_tx_set_retry(struct ath_
+                            struct sk_buff *skb)
+ {
+       struct ath_frame_info *fi = get_frame_info(skb);
++      struct ath_buf *bf = fi->bf;
+       struct ieee80211_hdr *hdr;
+       TX_STAT_INC(txq->axq_qnum, a_retries);
+@@ -271,6 +271,8 @@ static void ath_tx_set_retry(struct ath_
+       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
++      dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
++              sizeof(*hdr), DMA_TO_DEVICE);
+ }
+ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
+@@ -390,11 +392,9 @@ static void ath_tx_complete_aggr(struct 
+               while (bf) {
+                       bf_next = bf->bf_next;
+-                      bf->bf_state.bf_type |= BUF_XRETRY;
+                       if (!bf->bf_stale || bf_next != NULL)
+                               list_move_tail(&bf->list, &bf_head);
+-                      ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+                               0, 0);
+@@ -470,7 +470,6 @@ static void ath_tx_complete_aggr(struct 
+                               clear_filter = true;
+                               txpending = 1;
+                       } else {
+-                              bf->bf_state.bf_type |= BUF_XRETRY;
+                               txfail = 1;
+                               sendbar = 1;
+                               txfail_cnt++;
+@@ -497,17 +496,14 @@ static void ath_tx_complete_aggr(struct 
+                       if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+                               memcpy(tx_info->control.rates, rates, sizeof(rates));
+-                              ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true);
++                              ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
+                               rc_update = false;
+-                      } else {
+-                              ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false);
+                       }
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+                               !txfail, sendbar);
+               } else {
+                       /* retry the un-acked ones */
+-                      ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
+                       if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
+                               if (bf->bf_next == NULL && bf_last->bf_stale) {
+                                       struct ath_buf *tbf;
+@@ -523,26 +519,13 @@ static void ath_tx_complete_aggr(struct 
+                                               ath_tx_update_baw(sc, tid, seqno);
+                                               spin_unlock_bh(&txq->axq_lock);
+-                                              bf->bf_state.bf_type |=
+-                                                      BUF_XRETRY;
+-                                              ath_tx_rc_status(sc, bf, ts, nframes,
+-                                                              nbad, 0, false);
+                                               ath_tx_complete_buf(sc, bf, txq,
+                                                                   &bf_head,
+-                                                                  ts, 0, 0);
++                                                                  ts, 0, 1);
+                                               break;
+                                       }
+-                                      ath9k_hw_cleartxdesc(sc->sc_ah,
+-                                                           tbf->bf_desc);
+                                       fi->bf = tbf;
+-                              } else {
+-                                      /*
+-                                       * Clear descriptor status words for
+-                                       * software retry
+-                                       */
+-                                      ath9k_hw_cleartxdesc(sc->sc_ah,
+-                                                           bf->bf_desc);
+                               }
+                       }
+@@ -778,7 +761,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+               if (!bf)
+                       continue;
+-              bf->bf_state.bf_type |= BUF_AMPDU;
++              bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
+               seqno = bf->bf_state.seqno;
+               if (!bf_first)
+                       bf_first = bf;
+@@ -805,8 +788,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+               }
+               tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+-              if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
+-                      !(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)))
++              if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
+                       break;
+               /* do not exceed subframe limit */
+@@ -828,20 +810,17 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+               nframes++;
+               bf->bf_next = NULL;
+-              ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
+               /* link buffers of this frame to the aggregate */
+               if (!fi->retries)
+                       ath_tx_addto_baw(sc, tid, seqno);
+-              ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
++              bf->bf_state.ndelim = ndelim;
+               __skb_unlink(skb, &tid->buf_q);
+               list_add_tail(&bf->list, bf_q);
+-              if (bf_prev) {
++              if (bf_prev)
+                       bf_prev->bf_next = bf;
+-                      ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
+-                                             bf->bf_daddr);
+-              }
++
+               bf_prev = bf;
+       } while (!skb_queue_empty(&tid->buf_q));
+@@ -852,12 +831,245 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ #undef PADBYTES
+ }
++/*
++ * rix - rate index
++ * pktlen - total bytes (delims + data + fcs + pads + pad delims)
++ * width  - 0 for 20 MHz, 1 for 40 MHz
++ * half_gi - to use 4us v/s 3.6 us for symbol time
++ */
++static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
++                          int width, int half_gi, bool shortPreamble)
++{
++      u32 nbits, nsymbits, duration, nsymbols;
++      int streams;
++
++      /* find number of symbols: PLCP + data */
++      streams = HT_RC_2_STREAMS(rix);
++      nbits = (pktlen << 3) + OFDM_PLCP_BITS;
++      nsymbits = bits_per_symbol[rix % 8][width] * streams;
++      nsymbols = (nbits + nsymbits - 1) / nsymbits;
++
++      if (!half_gi)
++              duration = SYMBOL_TIME(nsymbols);
++      else
++              duration = SYMBOL_TIME_HALFGI(nsymbols);
++
++      /* addup duration for legacy/ht training and signal fields */
++      duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
++
++      return duration;
++}
++
++static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
++                           struct ath_tx_info *info, int len)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      struct sk_buff *skb;
++      struct ieee80211_tx_info *tx_info;
++      struct ieee80211_tx_rate *rates;
++      const struct ieee80211_rate *rate;
++      struct ieee80211_hdr *hdr;
++      int i;
++      u8 rix = 0;
++
++      skb = bf->bf_mpdu;
++      tx_info = IEEE80211_SKB_CB(skb);
++      rates = tx_info->control.rates;
++      hdr = (struct ieee80211_hdr *)skb->data;
++
++      /* set dur_update_en for l-sig computation except for PS-Poll frames */
++      info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
++
++      /*
++       * We check if Short Preamble is needed for the CTS rate by
++       * checking the BSS's global flag.
++       * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
++       */
++      rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
++      info->rtscts_rate = rate->hw_value;
++      if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
++              info->rtscts_rate |= rate->hw_value_short;
++
++      for (i = 0; i < 4; i++) {
++              bool is_40, is_sgi, is_sp;
++              int phy;
++
++              if (!rates[i].count || (rates[i].idx < 0))
++                      continue;
++
++              rix = rates[i].idx;
++              info->rates[i].Tries = rates[i].count;
++
++                  if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
++                      info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
++                      info->flags |= ATH9K_TXDESC_RTSENA;
++              } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
++                      info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
++                      info->flags |= ATH9K_TXDESC_CTSENA;
++              }
++
++              if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
++                      info->rates[i].RateFlags |= ATH9K_RATESERIES_2040;
++              if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
++                      info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
++
++              is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
++              is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
++              is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
++
++              if (rates[i].flags & IEEE80211_TX_RC_MCS) {
++                      /* MCS rates */
++                      info->rates[i].Rate = rix | 0x80;
++                      info->rates[i].ChSel = ath_txchainmask_reduction(sc,
++                                      ah->txchainmask, info->rates[i].Rate);
++                      info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len,
++                               is_40, is_sgi, is_sp);
++                      if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
++                              info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
++                      continue;
++              }
++
++              /* legacy rates */
++              if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
++                  !(rate->flags & IEEE80211_RATE_ERP_G))
++                      phy = WLAN_RC_PHY_CCK;
++              else
++                      phy = WLAN_RC_PHY_OFDM;
++
++              rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
++              info->rates[i].Rate = rate->hw_value;
++              if (rate->hw_value_short) {
++                      if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
++                              info->rates[i].Rate |= rate->hw_value_short;
++              } else {
++                      is_sp = false;
++              }
++
++              if (bf->bf_state.bfs_paprd)
++                      info->rates[i].ChSel = ah->txchainmask;
++              else
++                      info->rates[i].ChSel = ath_txchainmask_reduction(sc,
++                                      ah->txchainmask, info->rates[i].Rate);
++
++              info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
++                      phy, rate->bitrate * 100, len, rix, is_sp);
++      }
++
++      /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
++      if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
++              info->flags &= ~ATH9K_TXDESC_RTSENA;
++
++      /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
++      if (info->flags & ATH9K_TXDESC_RTSENA)
++              info->flags &= ~ATH9K_TXDESC_CTSENA;
++}
++
++static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
++{
++      struct ieee80211_hdr *hdr;
++      enum ath9k_pkt_type htype;
++      __le16 fc;
++
++      hdr = (struct ieee80211_hdr *)skb->data;
++      fc = hdr->frame_control;
++
++      if (ieee80211_is_beacon(fc))
++              htype = ATH9K_PKT_TYPE_BEACON;
++      else if (ieee80211_is_probe_resp(fc))
++              htype = ATH9K_PKT_TYPE_PROBE_RESP;
++      else if (ieee80211_is_atim(fc))
++              htype = ATH9K_PKT_TYPE_ATIM;
++      else if (ieee80211_is_pspoll(fc))
++              htype = ATH9K_PKT_TYPE_PSPOLL;
++      else
++              htype = ATH9K_PKT_TYPE_NORMAL;
++
++      return htype;
++}
++
++static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
++                           struct ath_txq *txq, int len)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
++      struct ath_buf *bf_first = bf;
++      struct ath_tx_info info;
++      bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR);
++
++      memset(&info, 0, sizeof(info));
++      info.is_first = true;
++      info.is_last = true;
++      info.txpower = MAX_RATE_POWER;
++      info.qcu = txq->axq_qnum;
++
++      info.flags = ATH9K_TXDESC_INTREQ;
++      if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
++              info.flags |= ATH9K_TXDESC_NOACK;
++      if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
++              info.flags |= ATH9K_TXDESC_LDPC;
++
++      ath_buf_set_rate(sc, bf, &info, len);
++
++      if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
++              info.flags |= ATH9K_TXDESC_CLRDMASK;
++
++      if (bf->bf_state.bfs_paprd)
++              info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S;
++
++
++      while (bf) {
++              struct sk_buff *skb = bf->bf_mpdu;
++              struct ath_frame_info *fi = get_frame_info(skb);
++              struct ieee80211_hdr *hdr;
++              int padpos, padsize;
++
++              info.type = get_hw_packet_type(skb);
++              if (bf->bf_next)
++                      info.link = bf->bf_next->bf_daddr;
++              else
++                      info.link = 0;
++
++              if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
++                      hdr = (struct ieee80211_hdr *)skb->data;
++                      padpos = ath9k_cmn_padpos(hdr->frame_control);
++                      padsize = padpos & 3;
++
++                      info.buf_addr[0] = bf->bf_buf_addr;
++                      info.buf_len[0] = padpos + padsize;
++                      info.buf_addr[1] = info.buf_addr[0] + padpos;
++                      info.buf_len[1] = skb->len - padpos;
++              } else {
++                      info.buf_addr[0] = bf->bf_buf_addr;
++                      info.buf_len[0] = skb->len;
++              }
++
++              info.pkt_len = fi->framelen;
++              info.keyix = fi->keyix;
++              info.keytype = fi->keytype;
++
++              if (aggr) {
++                      if (bf == bf_first)
++                              info.aggr = AGGR_BUF_FIRST;
++                      else if (!bf->bf_next)
++                              info.aggr = AGGR_BUF_LAST;
++                      else
++                              info.aggr = AGGR_BUF_MIDDLE;
++
++                      info.ndelim = bf->bf_state.ndelim;
++                      info.aggr_len = len;
++              }
++
++              ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
++              bf = bf->bf_next;
++      }
++}
++
+ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
+                             struct ath_atx_tid *tid)
+ {
+       struct ath_buf *bf;
+       enum ATH_AGGR_STATUS status;
+-      struct ath_frame_info *fi;
++      struct ieee80211_tx_info *tx_info;
+       struct list_head bf_q;
+       int aggr_len;
+@@ -878,34 +1090,25 @@ static void ath_tx_sched_aggr(struct ath
+               bf = list_first_entry(&bf_q, struct ath_buf, list);
+               bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
++              tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+               if (tid->ac->clear_ps_filter) {
+                       tid->ac->clear_ps_filter = false;
+-                      ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
++                      tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
++              } else {
++                      tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
+               }
+               /* if only one frame, send as non-aggregate */
+               if (bf == bf->bf_lastbf) {
+-                      fi = get_frame_info(bf->bf_mpdu);
+-
+-                      bf->bf_state.bf_type &= ~BUF_AGGR;
+-                      ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
+-                      ath_buf_set_rate(sc, bf, fi->framelen);
+-                      ath_tx_txqaddbuf(sc, txq, &bf_q, false);
+-                      continue;
++                      aggr_len = get_frame_info(bf->bf_mpdu)->framelen;
++                      bf->bf_state.bf_type = BUF_AMPDU;
++              } else {
++                      TX_STAT_INC(txq->axq_qnum, a_aggr);
+               }
+-              /* setup first desc of aggregate */
+-              bf->bf_state.bf_type |= BUF_AGGR;
+-              ath_buf_set_rate(sc, bf, aggr_len);
+-              ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len);
+-
+-              /* anchor last desc of aggregate */
+-              ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
+-
++              ath_tx_fill_desc(sc, bf, txq, aggr_len);
+               ath_tx_txqaddbuf(sc, txq, &bf_q, false);
+-              TX_STAT_INC(txq->axq_qnum, a_aggr);
+-
+       } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
+                status != ATH_AGGR_BAW_CLOSED);
+ }
+@@ -1483,7 +1686,7 @@ static void ath_tx_send_ampdu(struct ath
+       if (!bf)
+               return;
+-      bf->bf_state.bf_type |= BUF_AMPDU;
++      bf->bf_state.bf_type = BUF_AMPDU;
+       INIT_LIST_HEAD(&bf_head);
+       list_add(&bf->list, &bf_head);
+@@ -1493,7 +1696,7 @@ static void ath_tx_send_ampdu(struct ath
+       /* Queue to h/w without aggregation */
+       TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
+       bf->bf_lastbf = bf;
+-      ath_buf_set_rate(sc, bf, fi->framelen);
++      ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen);
+       ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
+ }
+@@ -1513,41 +1716,18 @@ static void ath_tx_send_normal(struct at
+       INIT_LIST_HEAD(&bf_head);
+       list_add_tail(&bf->list, &bf_head);
+-      bf->bf_state.bf_type &= ~BUF_AMPDU;
++      bf->bf_state.bf_type = 0;
+       /* update starting sequence number for subsequent ADDBA request */
+       if (tid)
+               INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+       bf->bf_lastbf = bf;
+-      ath_buf_set_rate(sc, bf, fi->framelen);
++      ath_tx_fill_desc(sc, bf, txq, fi->framelen);
+       ath_tx_txqaddbuf(sc, txq, &bf_head, false);
+       TX_STAT_INC(txq->axq_qnum, queued);
+ }
+-static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
+-{
+-      struct ieee80211_hdr *hdr;
+-      enum ath9k_pkt_type htype;
+-      __le16 fc;
+-
+-      hdr = (struct ieee80211_hdr *)skb->data;
+-      fc = hdr->frame_control;
+-
+-      if (ieee80211_is_beacon(fc))
+-              htype = ATH9K_PKT_TYPE_BEACON;
+-      else if (ieee80211_is_probe_resp(fc))
+-              htype = ATH9K_PKT_TYPE_PROBE_RESP;
+-      else if (ieee80211_is_atim(fc))
+-              htype = ATH9K_PKT_TYPE_ATIM;
+-      else if (ieee80211_is_pspoll(fc))
+-              htype = ATH9K_PKT_TYPE_PSPOLL;
+-      else
+-              htype = ATH9K_PKT_TYPE_NORMAL;
+-
+-      return htype;
+-}
+-
+ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
+                            int framelen)
+ {
+@@ -1575,51 +1755,6 @@ static void setup_frame_info(struct ieee
+       fi->framelen = framelen;
+ }
+-static int setup_tx_flags(struct sk_buff *skb)
+-{
+-      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+-      int flags = 0;
+-
+-      flags |= ATH9K_TXDESC_INTREQ;
+-
+-      if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
+-              flags |= ATH9K_TXDESC_NOACK;
+-
+-      if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
+-              flags |= ATH9K_TXDESC_LDPC;
+-
+-      return flags;
+-}
+-
+-/*
+- * rix - rate index
+- * pktlen - total bytes (delims + data + fcs + pads + pad delims)
+- * width  - 0 for 20 MHz, 1 for 40 MHz
+- * half_gi - to use 4us v/s 3.6 us for symbol time
+- */
+-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
+-                          int width, int half_gi, bool shortPreamble)
+-{
+-      u32 nbits, nsymbits, duration, nsymbols;
+-      int streams;
+-
+-      /* find number of symbols: PLCP + data */
+-      streams = HT_RC_2_STREAMS(rix);
+-      nbits = (pktlen << 3) + OFDM_PLCP_BITS;
+-      nsymbits = bits_per_symbol[rix % 8][width] * streams;
+-      nsymbols = (nbits + nsymbits - 1) / nsymbits;
+-
+-      if (!half_gi)
+-              duration = SYMBOL_TIME(nsymbols);
+-      else
+-              duration = SYMBOL_TIME_HALFGI(nsymbols);
+-
+-      /* addup duration for legacy/ht training and signal fields */
+-      duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+-
+-      return duration;
+-}
+-
+ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
+ {
+       struct ath_hw *ah = sc->sc_ah;
+@@ -1632,118 +1767,6 @@ u8 ath_txchainmask_reduction(struct ath_
+               return chainmask;
+ }
+-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
+-{
+-      struct ath_hw *ah = sc->sc_ah;
+-      struct ath9k_11n_rate_series series[4];
+-      struct sk_buff *skb;
+-      struct ieee80211_tx_info *tx_info;
+-      struct ieee80211_tx_rate *rates;
+-      const struct ieee80211_rate *rate;
+-      struct ieee80211_hdr *hdr;
+-      int i, flags = 0;
+-      u8 rix = 0, ctsrate = 0;
+-      bool is_pspoll;
+-
+-      memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
+-
+-      skb = bf->bf_mpdu;
+-      tx_info = IEEE80211_SKB_CB(skb);
+-      rates = tx_info->control.rates;
+-      hdr = (struct ieee80211_hdr *)skb->data;
+-      is_pspoll = ieee80211_is_pspoll(hdr->frame_control);
+-
+-      /*
+-       * We check if Short Preamble is needed for the CTS rate by
+-       * checking the BSS's global flag.
+-       * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
+-       */
+-      rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
+-      ctsrate = rate->hw_value;
+-      if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+-              ctsrate |= rate->hw_value_short;
+-
+-      for (i = 0; i < 4; i++) {
+-              bool is_40, is_sgi, is_sp;
+-              int phy;
+-
+-              if (!rates[i].count || (rates[i].idx < 0))
+-                      continue;
+-
+-              rix = rates[i].idx;
+-              series[i].Tries = rates[i].count;
+-
+-                  if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+-                      series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+-                      flags |= ATH9K_TXDESC_RTSENA;
+-              } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+-                      series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+-                      flags |= ATH9K_TXDESC_CTSENA;
+-              }
+-
+-              if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+-                      series[i].RateFlags |= ATH9K_RATESERIES_2040;
+-              if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+-                      series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
+-
+-              is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
+-              is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
+-              is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
+-
+-              if (rates[i].flags & IEEE80211_TX_RC_MCS) {
+-                      /* MCS rates */
+-                      series[i].Rate = rix | 0x80;
+-                      series[i].ChSel = ath_txchainmask_reduction(sc,
+-                                      ah->txchainmask, series[i].Rate);
+-                      series[i].PktDuration = ath_pkt_duration(sc, rix, len,
+-                               is_40, is_sgi, is_sp);
+-                      if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
+-                              series[i].RateFlags |= ATH9K_RATESERIES_STBC;
+-                      continue;
+-              }
+-
+-              /* legacy rates */
+-              if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
+-                  !(rate->flags & IEEE80211_RATE_ERP_G))
+-                      phy = WLAN_RC_PHY_CCK;
+-              else
+-                      phy = WLAN_RC_PHY_OFDM;
+-
+-              rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
+-              series[i].Rate = rate->hw_value;
+-              if (rate->hw_value_short) {
+-                      if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+-                              series[i].Rate |= rate->hw_value_short;
+-              } else {
+-                      is_sp = false;
+-              }
+-
+-              if (bf->bf_state.bfs_paprd)
+-                      series[i].ChSel = ah->txchainmask;
+-              else
+-                      series[i].ChSel = ath_txchainmask_reduction(sc,
+-                                      ah->txchainmask, series[i].Rate);
+-
+-              series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
+-                      phy, rate->bitrate * 100, len, rix, is_sp);
+-      }
+-
+-      /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+-      if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
+-              flags &= ~ATH9K_TXDESC_RTSENA;
+-
+-      /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
+-      if (flags & ATH9K_TXDESC_RTSENA)
+-              flags &= ~ATH9K_TXDESC_CTSENA;
+-
+-      /* set dur_update_en for l-sig computation except for PS-Poll frames */
+-      ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
+-                                   bf->bf_lastbf->bf_desc,
+-                                   !is_pspoll, ctsrate,
+-                                   0, series, 4, flags);
+-
+-}
+-
+ /*
+  * Assign a descriptor (and sequence number if necessary,
+  * and map buffer for DMA. Frees skb on error
+@@ -1753,13 +1776,10 @@ static struct ath_buf *ath_tx_setup_buff
+                                          struct ath_atx_tid *tid,
+                                          struct sk_buff *skb)
+ {
+-      struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_frame_info *fi = get_frame_info(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ath_buf *bf;
+-      struct ath_desc *ds;
+-      int frm_type;
+       u16 seqno;
+       bf = ath_tx_get_buffer(sc);
+@@ -1777,7 +1797,6 @@ static struct ath_buf *ath_tx_setup_buff
+               bf->bf_state.seqno = seqno;
+       }
+-      bf->bf_flags = setup_tx_flags(skb);
+       bf->bf_mpdu = skb;
+       bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+@@ -1791,22 +1810,6 @@ static struct ath_buf *ath_tx_setup_buff
+               goto error;
+       }
+-      frm_type = get_hw_packet_type(skb);
+-
+-      ds = bf->bf_desc;
+-      ath9k_hw_set_desc_link(ah, ds, 0);
+-
+-      ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER,
+-                             fi->keyix, fi->keytype, bf->bf_flags);
+-
+-      ath9k_hw_filltxdesc(ah, ds,
+-                          skb->len,   /* segment length */
+-                          true,       /* first segment */
+-                          true,       /* last segment */
+-                          ds,         /* first descriptor */
+-                          bf->bf_buf_addr,
+-                          txq->axq_qnum);
+-
+       fi->bf = bf;
+       return bf;
+@@ -1849,16 +1852,9 @@ static void ath_tx_start_dma(struct ath_
+               bf->bf_state.bfs_paprd = txctl->paprd;
+-              if (bf->bf_state.bfs_paprd)
+-                      ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
+-                                                 bf->bf_state.bfs_paprd);
+-
+               if (txctl->paprd)
+                       bf->bf_state.bfs_paprd_timestamp = jiffies;
+-              if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
+-                      ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
+-
+               ath_tx_send_normal(sc, txctl->txq, tid, skb);
+       }
+@@ -1899,15 +1895,18 @@ int ath_tx_start(struct ieee80211_hw *hw
+               hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+       }
+-      /* Add the padding after the header if this is not already done */
+-      padpos = ath9k_cmn_padpos(hdr->frame_control);
+-      padsize = padpos & 3;
+-      if (padsize && skb->len > padpos) {
+-              if (skb_headroom(skb) < padsize)
+-                      return -ENOMEM;
+-
+-              skb_push(skb, padsize);
+-              memmove(skb->data, skb->data + padsize, padpos);
++      if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
++              /* Add the padding after the header if this is not already done */
++              padpos = ath9k_cmn_padpos(hdr->frame_control);
++              padsize = padpos & 3;
++              if (padsize && skb->len > padpos) {
++                      if (skb_headroom(skb) < padsize)
++                              return -ENOMEM;
++
++                      skb_push(skb, padsize);
++                      memmove(skb->data, skb->data + padsize, padpos);
++                      hdr = (struct ieee80211_hdr *) skb->data;
++              }
+       }
+       if ((vif && vif->type != NL80211_IFTYPE_AP &&
+@@ -1953,20 +1952,21 @@ static void ath_tx_complete(struct ath_s
+       if (tx_flags & ATH_TX_BAR)
+               tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+-      if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
++      if (!(tx_flags & ATH_TX_ERROR))
+               /* Frame was ACKed */
+               tx_info->flags |= IEEE80211_TX_STAT_ACK;
+-      }
+-      padpos = ath9k_cmn_padpos(hdr->frame_control);
+-      padsize = padpos & 3;
+-      if (padsize && skb->len>padpos+padsize) {
+-              /*
+-               * Remove MAC header padding before giving the frame back to
+-               * mac80211.
+-               */
+-              memmove(skb->data + padsize, skb->data, padpos);
+-              skb_pull(skb, padsize);
++      if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
++              padpos = ath9k_cmn_padpos(hdr->frame_control);
++              padsize = padpos & 3;
++              if (padsize && skb->len>padpos+padsize) {
++                      /*
++                       * Remove MAC header padding before giving the frame back to
++                       * mac80211.
++                       */
++                      memmove(skb->data + padsize, skb->data, padpos);
++                      skb_pull(skb, padsize);
++              }
+       }
+       if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
+@@ -2000,18 +2000,18 @@ static void ath_tx_complete_buf(struct a
+                               struct ath_tx_status *ts, int txok, int sendbar)
+ {
+       struct sk_buff *skb = bf->bf_mpdu;
++      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       unsigned long flags;
+       int tx_flags = 0;
+       if (sendbar)
+               tx_flags = ATH_TX_BAR;
+-      if (!txok) {
++      if (!txok)
+               tx_flags |= ATH_TX_ERROR;
+-              if (bf_isxretried(bf))
+-                      tx_flags |= ATH_TX_XRETRY;
+-      }
++      if (ts->ts_status & ATH9K_TXERR_FILT)
++              tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+       dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
+       bf->bf_buf_addr = 0;
+@@ -2024,7 +2024,7 @@ static void ath_tx_complete_buf(struct a
+               else
+                       complete(&sc->paprd_complete);
+       } else {
+-              ath_debug_stat_tx(sc, bf, ts, txq);
++              ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
+               ath_tx_complete(sc, skb, tx_flags, txq);
+       }
+       /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
+@@ -2042,7 +2042,7 @@ static void ath_tx_complete_buf(struct a
+ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+                            struct ath_tx_status *ts, int nframes, int nbad,
+-                           int txok, bool update_rc)
++                           int txok)
+ {
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+@@ -2057,9 +2057,7 @@ static void ath_tx_rc_status(struct ath_
+       tx_rateindex = ts->ts_rateindex;
+       WARN_ON(tx_rateindex >= hw->max_rates);
+-      if (ts->ts_status & ATH9K_TXERR_FILT)
+-              tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+-      if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
++      if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+               tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+               BUG_ON(nbad > nframes);
+@@ -2069,7 +2067,7 @@ static void ath_tx_rc_status(struct ath_
+       }
+       if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
+-          (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
++          (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
+               /*
+                * If an underrun error is seen assume it as an excessive
+                * retry only if max frame trigger level has been reached
+@@ -2082,9 +2080,9 @@ static void ath_tx_rc_status(struct ath_
+                * successfully by eventually preferring slower rates.
+                * This itself should also alleviate congestion on the bus.
+                */
+-              if (ieee80211_is_data(hdr->frame_control) &&
+-                  (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
+-                                   ATH9K_TX_DELIM_UNDERRUN)) &&
++              if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
++                                           ATH9K_TX_DELIM_UNDERRUN)) &&
++                  ieee80211_is_data(hdr->frame_control) &&
+                   ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
+                       tx_info->status.rates[tx_rateindex].count =
+                               hw->max_rate_tries;
+@@ -2115,13 +2113,7 @@ static void ath_tx_process_buffer(struct
+       spin_unlock_bh(&txq->axq_lock);
+       if (!bf_isampdu(bf)) {
+-              /*
+-               * This frame is sent out as a single frame.
+-               * Use hardware retry status for this frame.
+-               */
+-              if (ts->ts_status & ATH9K_TXERR_XRETRY)
+-                      bf->bf_state.bf_type |= BUF_XRETRY;
+-              ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
++              ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
+               ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
+       } else
+               ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
 --- a/net/mac80211/agg-rx.c
 +++ b/net/mac80211/agg-rx.c
-@@ -184,6 +184,8 @@ static void ieee80211_send_addba_resp(st
+@@ -180,6 +180,8 @@ static void ieee80211_send_addba_resp(st
                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);
                                          IEEE80211_STYPE_ACTION);
 --- a/net/mac80211/agg-tx.c
 +++ b/net/mac80211/agg-tx.c
-@@ -79,7 +79,8 @@ static void ieee80211_send_addba_request
+@@ -77,7 +77,8 @@ static void ieee80211_send_addba_request
        memcpy(mgmt->da, da, ETH_ALEN);
        memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        if (sdata->vif.type == NL80211_IFTYPE_AP ||
                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);
-@@ -398,7 +399,8 @@ int ieee80211_start_tx_ba_session(struct
+@@ -397,7 +398,8 @@ int ieee80211_start_tx_ba_session(struct
         */
        if (sdata->vif.type != NL80211_IFTYPE_STATION &&
            sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
                        break;
 --- a/net/mac80211/rx.c
 +++ b/net/mac80211/rx.c
-@@ -2160,7 +2160,8 @@ ieee80211_rx_h_action(struct ieee80211_r
+@@ -2163,7 +2163,8 @@ ieee80211_rx_h_action(struct ieee80211_r
                 */
                if (sdata->vif.type != NL80211_IFTYPE_STATION &&
                    sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
                        break;
  
                /* verify action_code is present */
-@@ -2375,13 +2376,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+@@ -2378,13 +2379,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
  
        if (!ieee80211_vif_is_mesh(&sdata->vif) &&
            sdata->vif.type != NL80211_IFTYPE_ADHOC &&
                break;
        case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
        case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
-@@ -2724,10 +2726,16 @@ static int prepare_for_handlers(struct i
+@@ -2727,10 +2729,16 @@ static int prepare_for_handlers(struct i
                }
                break;
        case NL80211_IFTYPE_WDS:
        WLAN_STA_CLEAR_PS_FILT  = 1<<9,
        WLAN_STA_MFP            = 1<<10,
        WLAN_STA_BLOCK_BA       = 1<<11,
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -278,17 +278,19 @@ void ieee80211_tx_status(struct ieee8021
+               }
+               if (!acked && ieee80211_is_back_req(fc)) {
++                      u16 control;
++
+                       /*
+-                       * BAR failed, let's tear down the BA session as a
+-                       * last resort as some STAs (Intel 5100 on Windows)
+-                       * can get stuck when the BA window isn't flushed
+-                       * correctly.
++                       * BAR failed, store the last SSN and retry sending
++                       * the BAR when the next unicast transmission on the
++                       * same TID succeeds.
+                        */
+                       bar = (struct ieee80211_bar *) skb->data;
+-                      if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
++                      control = le16_to_cpu(bar->control);
++                      if (!(control & IEEE80211_BAR_CTRL_MULTI_TID)) {
+                               u16 ssn = le16_to_cpu(bar->start_seq_num);
+-                              tid = (bar->control &
++                              tid = (control &
+                                      IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
+                                     IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -704,8 +704,10 @@ static void ar5008_hw_override_ini(struc
+               REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
+       }
+-      if (!AR_SREV_5416_20_OR_LATER(ah) ||
+-          AR_SREV_9280_20_OR_LATER(ah))
++      REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
++                  AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
++
++      if (AR_SREV_9280_20_OR_LATER(ah))
+               return;
+       /*
+        * Disable BB clock gating
+@@ -802,7 +804,8 @@ static int ar5008_hw_process_ini(struct 
+       /* Write ADDAC shifts */
+       REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+-      ah->eep_ops->set_addac(ah, chan);
++      if (ah->eep_ops->set_addac)
++              ah->eep_ops->set_addac(ah, chan);
+       if (AR_SREV_5416_22_OR_LATER(ah)) {
+               REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
+@@ -1007,24 +1010,6 @@ static void ar5008_restore_chainmask(str
+       }
+ }
+-static void ar5008_set_diversity(struct ath_hw *ah, bool value)
+-{
+-      u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
+-      if (value)
+-              v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+-      else
+-              v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+-      REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
+-}
+-
+-static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah,
+-                                       struct ath9k_channel *chan)
+-{
+-      if (chan && IS_CHAN_5GHZ(chan))
+-              return 0x1450;
+-      return 0x1458;
+-}
+-
+ static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah,
+                                        struct ath9k_channel *chan)
+ {
+@@ -1654,7 +1639,6 @@ void ar5008_hw_attach_phy_ops(struct ath
+       priv_ops->rfbus_req = ar5008_hw_rfbus_req;
+       priv_ops->rfbus_done = ar5008_hw_rfbus_done;
+       priv_ops->restore_chainmask = ar5008_restore_chainmask;
+-      priv_ops->set_diversity = ar5008_set_diversity;
+       priv_ops->do_getnf = ar5008_hw_do_getnf;
+       priv_ops->set_radar_params = ar5008_hw_set_radar_params;
+@@ -1664,9 +1648,7 @@ void ar5008_hw_attach_phy_ops(struct ath
+       } else
+               priv_ops->ani_control = ar5008_hw_ani_control_old;
+-      if (AR_SREV_9100(ah))
+-              priv_ops->compute_pll_control = ar9100_hw_compute_pll_control;
+-      else if (AR_SREV_9160_10_OR_LATER(ah))
++      if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
+               priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
+       else
+               priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
 +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -671,7 +671,7 @@ static int ar9003_hw_process_ini(struct 
-               REG_WRITE_ARRAY(&ah->iniModesAdditional,
-                               modesIndex, regWrites);
+@@ -592,6 +592,9 @@ static void ar9003_hw_override_ini(struc
+       val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
+       REG_WRITE(ah, AR_PCU_MISC_MODE2,
+                 val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
++
++      REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
++                  AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+ }
  
--      if (AR_SREV_9300(ah))
-+      if (AR_SREV_9330(ah))
-               REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
+ static void ar9003_hw_prog_ini(struct ath_hw *ah,
+@@ -785,16 +788,6 @@ static void ar9003_hw_rfbus_done(struct 
+       REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+ }
  
-       if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -975,7 +975,10 @@ void ath9k_hw_init_global_settings(struc
-       if (ah->misc_mode != 0)
-               REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
+-static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
+-{
+-      u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
+-      if (value)
+-              v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+-      else
+-              v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+-      REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
+-}
+-
+ static bool ar9003_hw_ani_control(struct ath_hw *ah,
+                                 enum ath9k_ani_cmd cmd, int param)
+ {
+@@ -1277,7 +1270,6 @@ void ar9003_hw_attach_phy_ops(struct ath
+       priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
+       priv_ops->rfbus_req = ar9003_hw_rfbus_req;
+       priv_ops->rfbus_done = ar9003_hw_rfbus_done;
+-      priv_ops->set_diversity = ar9003_hw_set_diversity;
+       priv_ops->ani_control = ar9003_hw_ani_control;
+       priv_ops->do_getnf = ar9003_hw_do_getnf;
+       priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
+--- a/drivers/net/wireless/ath/ath9k/eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom.c
+@@ -456,12 +456,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs
+               pPdGainBoundaries[i] =
+                       min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
  
--      rx_lat = 37;
-+      if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-+              rx_lat = 41;
-+      else
-+              rx_lat = 37;
-       tx_lat = 54;
-       if (IS_CHAN_HALF_RATE(chan)) {
-@@ -989,7 +992,7 @@ void ath9k_hw_init_global_settings(struc
-               sifstime = 32;
-       } else if (IS_CHAN_QUARTER_RATE(chan)) {
-               eifs = 340;
--              rx_lat *= 4;
-+              rx_lat = (rx_lat * 4) - 1;
-               tx_lat *= 4;
-               if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-                   tx_lat += 22;
-@@ -997,8 +1000,14 @@ void ath9k_hw_init_global_settings(struc
-               slottime = 21;
-               sifstime = 64;
-       } else {
--              eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/common->clockrate;
--              reg = REG_READ(ah, AR_USEC);
-+              if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
-+                      eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
-+                      reg = AR_USEC_ASYNC_FIFO;
-+              } else {
-+                      eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/
-+                              common->clockrate;
-+                      reg = REG_READ(ah, AR_USEC);
-+              }
-               rx_lat = MS(reg, AR_USEC_RX_LAT);
-               tx_lat = MS(reg, AR_USEC_TX_LAT);
+-              if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
+-                      minDelta = pPdGainBoundaries[0] - 23;
+-                      pPdGainBoundaries[0] = 23;
+-              } else {
+-                      minDelta = 0;
+-              }
++              minDelta = 0;
+               if (i == 0) {
+                       if (AR_SREV_9280_20_OR_LATER(ah))
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -405,12 +405,7 @@ static void ath9k_hw_set_4k_power_cal_ta
+       REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
+       for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+-              if (AR_SREV_5416_20_OR_LATER(ah) &&
+-                  (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+-                  (i != 0)) {
+-                      regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+-              } else
+-                      regChainOffset = i * 0x1000;
++              regChainOffset = i * 0x1000;
  
-@@ -2441,13 +2450,13 @@ void ath9k_hw_set_txpowerlimit(struct at
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
-       struct ath9k_channel *chan = ah->curchan;
-       struct ieee80211_channel *channel = chan->chan;
--      int reg_pwr = min_t(int, MAX_RATE_POWER, regulatory->power_limit);
-+      int reg_pwr = min_t(int, MAX_RATE_POWER, limit);
-       int chan_pwr = channel->max_power * 2;
+               if (pEepData->baseEepHeader.txMask & (1 << i)) {
+                       pRawDataset = pEepData->calPierData2G[i];
+@@ -423,19 +418,17 @@ static void ath9k_hw_set_4k_power_cal_ta
  
+                       ENABLE_REGWRITE_BUFFER(ah);
+-                      if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
+-                              REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+-                                        SM(pdGainOverlap_t2,
+-                                           AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+-                                        | SM(gainBoundaries[0],
+-                                             AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+-                                        | SM(gainBoundaries[1],
+-                                             AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+-                                        | SM(gainBoundaries[2],
+-                                             AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+-                                        | SM(gainBoundaries[3],
+-                                     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+-                      }
++                      REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
++                                SM(pdGainOverlap_t2,
++                                   AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
++                                | SM(gainBoundaries[0],
++                                     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
++                                | SM(gainBoundaries[1],
++                                     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
++                                | SM(gainBoundaries[2],
++                                     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
++                                | SM(gainBoundaries[3],
++                             AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+                       regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+                       for (j = 0; j < 32; j++) {
+@@ -715,10 +708,8 @@ static void ath9k_hw_4k_set_txpower(stru
        if (test)
-               reg_pwr = chan_pwr = MAX_RATE_POWER;
+           return;
  
--      regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER);
-+      regulatory->power_limit = reg_pwr;
+-      if (AR_SREV_9280_20_OR_LATER(ah)) {
+-              for (i = 0; i < Ar5416RateSize; i++)
+-                      ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
+-      }
++      for (i = 0; i < Ar5416RateSize; i++)
++              ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
  
-       ah->eep_ops->set_txpower(ah, chan,
-                                ath9k_regd_get_ctl(regulatory, chan),
---- a/drivers/net/wireless/ath/ath9k/reg.h
-+++ b/drivers/net/wireless/ath/ath9k/reg.h
-@@ -619,6 +619,7 @@
- #define AR_D_GBL_IFS_EIFS         0x10b0
- #define AR_D_GBL_IFS_EIFS_M       0x0000FFFF
- #define AR_D_GBL_IFS_EIFS_RESV0   0xFFFF0000
-+#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO 363
- #define AR_D_GBL_IFS_MISC        0x10f0
- #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL        0x00000007
-@@ -1503,6 +1504,7 @@ enum {
- #define AR_USEC_TX_LAT_S     14
- #define AR_USEC_RX_LAT       0x1F800000
- #define AR_USEC_RX_LAT_S     23
-+#define AR_USEC_ASYNC_FIFO   0x12E00074
- #define AR_RESET_TSF        0x8020
- #define AR_RESET_TSF_ONCE   0x01000000
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -582,7 +582,10 @@ static bool ath_lookup_legacy(struct ath
-       tx_info = IEEE80211_SKB_CB(skb);
-       rates = tx_info->control.rates;
+       ENABLE_REGWRITE_BUFFER(ah);
  
--      for (i = 3; i >= 0; i--) {
-+      for (i = 0; i < 4; i++) {
-+              if (!rates[i].count || rates[i].idx < 0)
-+                      break;
+@@ -788,28 +779,6 @@ static void ath9k_hw_4k_set_txpower(stru
+       REGWRITE_BUFFER_FLUSH(ah);
+ }
+-static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
+-                                struct ath9k_channel *chan)
+-{
+-      struct modal_eep_4k_header *pModal;
+-      struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+-      u8 biaslevel;
+-
+-      if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
+-              return;
+-
+-      if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
+-              return;
+-
+-      pModal = &eep->modalHeader;
+-
+-      if (pModal->xpaBiasLvl != 0xff) {
+-              biaslevel = pModal->xpaBiasLvl;
+-              INI_RA(&ah->iniAddac, 7, 1) =
+-                (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
+-      }
+-}
+-
+ static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
+                                struct modal_eep_4k_header *pModal,
+                                struct ar5416_eeprom_4k *eep,
+@@ -877,6 +846,7 @@ static void ath9k_hw_4k_set_board_values
+       u8 txRxAttenLocal;
+       u8 ob[5], db1[5], db2[5];
+       u8 ant_div_control1, ant_div_control2;
++      u8 bb_desired_scale;
+       u32 regVal;
+       pModal = &eep->modalHeader;
+@@ -1096,30 +1066,29 @@ static void ath9k_hw_4k_set_board_values
+                                     AR_PHY_SETTLING_SWITCH,
+                                     pModal->swSettleHt40);
+       }
+-      if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
+-              u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
+-                              EEP_4K_BB_DESIRED_SCALE_MASK);
+-              if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
+-                      u32 pwrctrl, mask, clr;
+-
+-                      mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
+-                      pwrctrl = mask * bb_desired_scale;
+-                      clr = mask * 0x1f;
+-                      REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
+-                      REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
+-                      REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+-
+-                      mask = BIT(0)|BIT(5)|BIT(15);
+-                      pwrctrl = mask * bb_desired_scale;
+-                      clr = mask * 0x1f;
+-                      REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
+-
+-                      mask = BIT(0)|BIT(5);
+-                      pwrctrl = mask * bb_desired_scale;
+-                      clr = mask * 0x1f;
+-                      REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
+-                      REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
+-              }
++
++      bb_desired_scale = (pModal->bb_scale_smrt_antenna &
++                      EEP_4K_BB_DESIRED_SCALE_MASK);
++      if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
++              u32 pwrctrl, mask, clr;
 +
-               if (!(rates[i].flags & IEEE80211_TX_RC_MCS))
-                       return true;
++              mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
++              pwrctrl = mask * bb_desired_scale;
++              clr = mask * 0x1f;
++              REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
++              REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
++              REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
++
++              mask = BIT(0)|BIT(5)|BIT(15);
++              pwrctrl = mask * bb_desired_scale;
++              clr = mask * 0x1f;
++              REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
++
++              mask = BIT(0)|BIT(5);
++              pwrctrl = mask * bb_desired_scale;
++              clr = mask * 0x1f;
++              REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
++              REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
+       }
+ }
+@@ -1161,7 +1130,6 @@ const struct eeprom_ops eep_4k_ops = {
+       .get_eeprom_ver         = ath9k_hw_4k_get_eeprom_ver,
+       .get_eeprom_rev         = ath9k_hw_4k_get_eeprom_rev,
+       .set_board_values       = ath9k_hw_4k_set_board_values,
+-      .set_addac              = ath9k_hw_4k_set_addac,
+       .set_txpower            = ath9k_hw_4k_set_txpower,
+       .get_spur_channel       = ath9k_hw_4k_get_spur_channel
+ };
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -851,10 +851,8 @@ static void ath9k_hw_ar9287_set_txpower(
+       if (test)
+               return;
+-      if (AR_SREV_9280_20_OR_LATER(ah)) {
+-              for (i = 0; i < Ar5416RateSize; i++)
+-                      ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
+-      }
++      for (i = 0; i < Ar5416RateSize; i++)
++              ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
+       ENABLE_REGWRITE_BUFFER(ah);
+@@ -944,11 +942,6 @@ static void ath9k_hw_ar9287_set_txpower(
+       REGWRITE_BUFFER_FLUSH(ah);
+ }
+-static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
+-                                    struct ath9k_channel *chan)
+-{
+-}
+-
+ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
+                                            struct ath9k_channel *chan)
+ {
+@@ -1100,7 +1093,6 @@ const struct eeprom_ops eep_ar9287_ops =
+       .get_eeprom_ver         = ath9k_hw_ar9287_get_eeprom_ver,
+       .get_eeprom_rev         = ath9k_hw_ar9287_get_eeprom_rev,
+       .set_board_values       = ath9k_hw_ar9287_set_board_values,
+-      .set_addac              = ath9k_hw_ar9287_set_addac,
+       .set_txpower            = ath9k_hw_ar9287_set_txpower,
+       .get_spur_channel       = ath9k_hw_ar9287_get_spur_channel
+ };
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -547,8 +547,7 @@ static void ath9k_hw_def_set_board_value
+                               break;
+               }
+-              if (AR_SREV_5416_20_OR_LATER(ah) &&
+-                  (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
++              if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
+                       regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+               else
+                       regChainOffset = i * 0x1000;
+@@ -565,9 +564,8 @@ static void ath9k_hw_def_set_board_value
+                         SM(pModal->iqCalQCh[i],
+                            AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+-              if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
+-                      ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
+-                                            regChainOffset, i);
++              ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
++                                    regChainOffset, i);
+       }
+       if (AR_SREV_9280_20_OR_LATER(ah)) {
+@@ -893,8 +891,7 @@ static void ath9k_hw_set_def_power_cal_t
+                     xpdGainValues[2]);
+       for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+-              if (AR_SREV_5416_20_OR_LATER(ah) &&
+-                  (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
++              if ((ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+                   (i != 0)) {
+                       regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+               } else
+@@ -935,27 +932,24 @@ static void ath9k_hw_set_def_power_cal_t
+                       ENABLE_REGWRITE_BUFFER(ah);
+-                      if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
+-                              if (OLC_FOR_AR9280_20_LATER) {
+-                                      REG_WRITE(ah,
+-                                              AR_PHY_TPCRG5 + regChainOffset,
+-                                              SM(0x6,
+-                                              AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+-                                              SM_PD_GAIN(1) | SM_PD_GAIN(2) |
+-                                              SM_PD_GAIN(3) | SM_PD_GAIN(4));
+-                              } else {
+-                                      REG_WRITE(ah,
+-                                              AR_PHY_TPCRG5 + regChainOffset,
+-                                              SM(pdGainOverlap_t2,
+-                                              AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
+-                                              SM_PDGAIN_B(0, 1) |
+-                                              SM_PDGAIN_B(1, 2) |
+-                                              SM_PDGAIN_B(2, 3) |
+-                                              SM_PDGAIN_B(3, 4));
+-                              }
++                      if (OLC_FOR_AR9280_20_LATER) {
++                              REG_WRITE(ah,
++                                      AR_PHY_TPCRG5 + regChainOffset,
++                                      SM(0x6,
++                                      AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
++                                      SM_PD_GAIN(1) | SM_PD_GAIN(2) |
++                                      SM_PD_GAIN(3) | SM_PD_GAIN(4));
++                      } else {
++                              REG_WRITE(ah,
++                                      AR_PHY_TPCRG5 + regChainOffset,
++                                      SM(pdGainOverlap_t2,
++                                      AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
++                                      SM_PDGAIN_B(0, 1) |
++                                      SM_PDGAIN_B(1, 2) |
++                                      SM_PDGAIN_B(2, 3) |
++                                      SM_PDGAIN_B(3, 4));
+                       }
+-
+                       ath9k_adjust_pdadc_values(ah, pwr_table_offset,
+                                                 diff, pdadcValues);
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -506,7 +506,6 @@ static void ath9k_init_misc(struct ath_s
+               sc->sc_flags |= SC_OP_RXAGGR;
        }
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -796,7 +796,7 @@ static int __must_check __sta_info_destr
-               BUG_ON(!sdata->bss);
-               atomic_dec(&sdata->bss->num_sta_ps);
--              __sta_info_clear_tim_bit(sdata->bss, sta);
-+              sta_info_clear_tim_bit(sta);
+-      ath9k_hw_set_diversity(sc->sc_ah, true);
+       sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
+       memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -800,10 +800,6 @@
+ #define AR_SREV_5416(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
+        ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
+-#define AR_SREV_5416_20_OR_LATER(_ah) \
+-      (((AR_SREV_5416(_ah)) && \
+-       ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
+-       ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
+ #define AR_SREV_5416_22_OR_LATER(_ah) \
+       (((AR_SREV_5416(_ah)) && \
+        ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
+--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+@@ -869,6 +869,7 @@ static bool ar9002_hw_init_cal(struct at
+       ar9002_hw_pa_cal(ah, true);
+       /* Do NF Calibration after DC offset and other calibrations */
++      ath9k_hw_loadnf(ah, chan);
+       ath9k_hw_start_nfcal(ah, true);
+       if (ah->caldata)
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -671,7 +671,6 @@ enum queue_stop_reason {
+       IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
+       IEEE80211_QUEUE_STOP_REASON_SUSPEND,
+       IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
+-      IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE,
+ };
+ #ifdef CONFIG_MAC80211_LEDS
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1921,24 +1921,8 @@ static void ieee80211_rx_mgmt_beacon(str
+               rcu_read_unlock();
+-              /*
+-               * Whenever the AP announces the HT mode change that can be
+-               * 40MHz intolerant or etc., it would be safer to stop tx
+-               * queues before doing hw config to avoid buffer overflow.
+-               */
+-              ieee80211_stop_queues_by_reason(&sdata->local->hw,
+-                              IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE);
+-
+-              /* flush out all packets */
+-              synchronize_net();
+-
+-              drv_flush(local, false);
+-
+               changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
+                                              bssid, ap_ht_cap_flags);
+-
+-              ieee80211_wake_queues_by_reason(&sdata->local->hw,
+-                              IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE);
        }
  
-       local->num_sta--;
+       /* Note: country IE parsing is done for us by cfg80211 */
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -1611,7 +1611,8 @@ static void handle_irq_beacon(struct b43
+@@ -1613,7 +1613,8 @@ static void handle_irq_beacon(struct b43
        u32 cmd, beacon0_valid, beacon1_valid;
  
        if (!b43_is_mode(wl, NL80211_IFTYPE_AP) &&
index eb1c8fc..6e0de5b 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/net/cfg80211.h
 +++ b/include/net/cfg80211.h
-@@ -1085,6 +1085,7 @@ struct cfg80211_ibss_params {
+@@ -1101,6 +1101,7 @@ struct cfg80211_ibss_params {
        u8 *ssid;
        u8 *bssid;
        struct ieee80211_channel *channel;
@@ -8,7 +8,7 @@
        u8 *ie;
        u8 ssid_len, ie_len;
        u16 beacon_interval;
-@@ -2584,6 +2585,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
+@@ -2612,6 +2613,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
                                      const u8 *bssid,
                                      const u8 *ssid, size_t ssid_len,
                                      u16 capa_mask, u16 capa_val);
@@ -23,7 +23,7 @@
                  struct ieee80211_channel *channel,
 --- a/net/wireless/nl80211.c
 +++ b/net/wireless/nl80211.c
-@@ -4470,13 +4470,41 @@ static int nl80211_join_ibss(struct sk_b
+@@ -4539,13 +4539,41 @@ static int nl80211_join_ibss(struct sk_b
                ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        }
  
@@ -89,7 +89,7 @@
                      struct wireless_dev *wdev, int freq,
 --- a/net/wireless/core.h
 +++ b/net/wireless/core.h
-@@ -441,6 +441,9 @@ cfg80211_can_add_interface(struct cfg802
+@@ -439,6 +439,9 @@ cfg80211_can_add_interface(struct cfg802
  struct ieee80211_channel *
  rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
                  int freq, enum nl80211_channel_type channel_type);
                                       struct ieee80211_channel *channel,
 --- a/net/mac80211/ieee80211_i.h
 +++ b/net/mac80211/ieee80211_i.h
-@@ -464,6 +464,7 @@ struct ieee80211_if_ibss {
+@@ -465,6 +465,7 @@ struct ieee80211_if_ibss {
        u8 ssid_len, ie_len;
        u8 *ie;
        struct ieee80211_channel *channel;
  
        unsigned long ibss_join_req;
        /* probe response/beacon for IBSS */
-@@ -1089,6 +1090,7 @@ void ieee80211_ibss_notify_scan_complete
+@@ -1090,6 +1091,7 @@ void ieee80211_ibss_notify_scan_complete
  void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
  struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
                                        u8 *bssid, u8 *addr, u32 supp_rates,
  #define debug_noinline noinline
 --- a/net/mac80211/util.c
 +++ b/net/mac80211/util.c
-@@ -841,23 +841,8 @@ int ieee80211_build_preq_ies(struct ieee
+@@ -839,23 +839,8 @@ int ieee80211_build_preq_ies(struct ieee
                offset = noffset;
        }
  
  
        /*
         * If adding more here, adjust code in main.c
-@@ -1381,3 +1366,100 @@ void ieee80211_disable_rssi_reports(stru
+@@ -1378,3 +1363,100 @@ void ieee80211_disable_rssi_reports(stru
        _ieee80211_enable_rssi_reports(sdata, 0, 0);
  }
  EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
  static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
 --- a/net/mac80211/agg-tx.c
 +++ b/net/mac80211/agg-tx.c
-@@ -84,6 +84,8 @@ static void ieee80211_send_addba_request
+@@ -82,6 +82,8 @@ static void ieee80211_send_addba_request
                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);
  
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                          IEEE80211_STYPE_ACTION);
-@@ -400,7 +402,8 @@ int ieee80211_start_tx_ba_session(struct
+@@ -399,7 +401,8 @@ int ieee80211_start_tx_ba_session(struct
        if (sdata->vif.type != NL80211_IFTYPE_STATION &&
            sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
            sdata->vif.type != NL80211_IFTYPE_AP &&
        if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
 --- a/net/mac80211/ht.c
 +++ b/net/mac80211/ht.c
-@@ -203,6 +203,8 @@ void ieee80211_send_delba(struct ieee802
+@@ -199,6 +199,8 @@ void ieee80211_send_delba(struct ieee802
                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);
        if (params->ie) {
 --- a/net/mac80211/rx.c
 +++ b/net/mac80211/rx.c
-@@ -2161,7 +2161,8 @@ ieee80211_rx_h_action(struct ieee80211_r
+@@ -2164,7 +2164,8 @@ ieee80211_rx_h_action(struct ieee80211_r
                if (sdata->vif.type != NL80211_IFTYPE_STATION &&
                    sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
                    sdata->vif.type != NL80211_IFTYPE_AP &&
                        break;
  
                /* verify action_code is present */
-@@ -2696,7 +2697,8 @@ static int prepare_for_handlers(struct i
+@@ -2699,7 +2700,8 @@ static int prepare_for_handlers(struct i
                        else
                                rate_idx = status->rate_idx;
                        rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
        case NL80211_IFTYPE_MESH_POINT:
 --- a/net/mac80211/agg-rx.c
 +++ b/net/mac80211/agg-rx.c
-@@ -186,6 +186,8 @@ static void ieee80211_send_addba_resp(st
+@@ -182,6 +182,8 @@ static void ieee80211_send_addba_resp(st
                memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
        else if (sdata->vif.type == NL80211_IFTYPE_WDS)
                memcpy(mgmt->bssid, da, ETH_ALEN);
index 47f3b4a..f92d38f 100644 (file)
@@ -11,7 +11,7 @@
 +              debug.o
 --- a/drivers/net/wireless/ath/ath.h
 +++ b/drivers/net/wireless/ath/ath.h
-@@ -277,13 +277,6 @@ ath_dbg(struct ath_common *common, enum 
+@@ -274,13 +274,6 @@ void ath_dbg(struct ath_common *common, 
  #endif /* CONFIG_ATH_DEBUG */
  
  /** Returns string describing opmode, or NULL if unknown mode. */
index 582d569..14ea04b 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/wireless/reg.c
 +++ b/net/wireless/reg.c
-@@ -1642,6 +1642,8 @@ void regulatory_hint_11d(struct wiphy *w
+@@ -1653,6 +1653,8 @@ void regulatory_hint_11d(struct wiphy *w
        enum environment_cap env = ENVIRON_ANY;
        struct regulatory_request *request;
  
@@ -9,7 +9,7 @@
        mutex_lock(&reg_mutex);
  
        if (unlikely(!last_request))
-@@ -1848,6 +1850,8 @@ static void restore_regulatory_settings(
+@@ -1859,6 +1861,8 @@ static void restore_regulatory_settings(
  
  void regulatory_hint_disconnect(void)
  {
index 13f11bb..f9050d5 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1491,15 +1491,6 @@ static int ath9k_add_interface(struct ie
+@@ -1473,15 +1473,6 @@ static int ath9k_add_interface(struct ie
                }
        }
  
@@ -16,7 +16,7 @@
        ath_dbg(common, ATH_DBG_CONFIG,
                "Attach a VIF of type: %d\n", vif->type);
  
-@@ -1525,15 +1516,6 @@ static int ath9k_change_interface(struct
+@@ -1507,15 +1498,6 @@ static int ath9k_change_interface(struct
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
  
index 742088c..012a6be 100644 (file)
@@ -1,9 +1,9 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1272,6 +1272,53 @@ static const struct file_operations fops
-       .llseek = default_llseek,
+@@ -1585,6 +1585,53 @@ static const struct file_operations fops
  };
  
 +static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
 +                           size_t count, loff_t *ppos)
 +{
@@ -54,7 +54,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
-@@ -1328,6 +1375,9 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1643,6 +1690,9 @@ int ath9k_init_debug(struct ath_hw *ah)
        debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
                           sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
  
@@ -62,5 +62,5 @@
 +                          &fops_eeprom);
 +
        sc->debug.regidx = 0;
-       return 0;
- }
+       memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp));
+       sc->debug.sampidx = 0;
index 2931a5e..483b382 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -366,7 +366,7 @@ struct ath_vif {
+@@ -363,7 +363,7 @@ struct ath_vif {
   * number of beacon intervals, the game's up.
   */
  #define BSTUCK_THRESH                 9
index 7451e61..cf03404 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -123,7 +123,7 @@ void ath_descdma_cleanup(struct ath_soft
+@@ -120,7 +120,7 @@ void ath_descdma_cleanup(struct ath_soft
  /* RX / TX */
  /***********/
  
index b144af4..4ac3e1c 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -587,6 +587,7 @@ struct ath_softc {
+@@ -585,6 +585,7 @@ struct ath_softc {
        struct ieee80211_hw *hw;
        struct device *dev;
  
@@ -10,7 +10,7 @@
        struct survey_info *cur_survey;
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1378,6 +1378,9 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1693,6 +1693,9 @@ int ath9k_init_debug(struct ath_hw *ah)
        debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_eeprom);
  
 +                         &sc->chan_bw);
 +
        sc->debug.regidx = 0;
-       return 0;
- }
+       memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp));
+       sc->debug.sampidx = 0;
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1654,9 +1654,10 @@ static int ath9k_config(struct ieee80211
+@@ -1636,9 +1636,10 @@ static int ath9k_config(struct ieee80211
  
        if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
                struct ieee80211_channel *curchan = hw->conf.channel;
@@ -34,7 +34,7 @@
                unsigned long flags;
  
                if (ah->curchan)
-@@ -1709,7 +1710,23 @@ static int ath9k_config(struct ieee80211
+@@ -1691,7 +1692,23 @@ static int ath9k_config(struct ieee80211
                        memset(&sc->survey[pos], 0, sizeof(struct survey_info));
                }
  
@@ -61,9 +61,9 @@
                        return -EINVAL;
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1507,6 +1507,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-       }
-       ah->noise = ath9k_hw_getchan_noise(ah, chan);
+@@ -1509,6 +1509,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+           (AR_SREV_9300_20_OR_LATER(ah) && IS_CHAN_5GHZ(chan)))
+               bChannelChange = false;
  
 +      if (!ah->curchan || ((ah->curchan->channelFlags ^ chan->channelFlags) &
 +          (CHANNEL_HALF | CHANNEL_QUARTER)))
index c0a6bf3..282c63a 100644 (file)
        ieee80211_start_tx_ba_session(pubsta, tid, 5000);
  }
  
-@@ -452,7 +460,7 @@ minstrel_ht_tx_status(void *priv, struct
+@@ -453,7 +461,7 @@ minstrel_ht_tx_status(void *priv, struct
        if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
                minstrel_ht_update_stats(mp, mi);
--              minstrel_aggr_check(mp, sta, skb);
-+              minstrel_aggr_check(mp, mi, sta, skb);
+               if (!(info->flags & IEEE80211_TX_CTL_AMPDU))
+-                      minstrel_aggr_check(mp, sta, skb);
++                      minstrel_aggr_check(mp, mi, sta, skb);
        }
  }
  
diff --git a/package/mac80211/patches/522-mac80211_reduce_txqueuelen.patch b/package/mac80211/patches/522-mac80211_reduce_txqueuelen.patch
new file mode 100644 (file)
index 0000000..948d204
--- /dev/null
@@ -0,0 +1,10 @@
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -685,6 +685,7 @@ static const struct net_device_ops ieee8
+ static void ieee80211_if_setup(struct net_device *dev)
+ {
+       ether_setup(dev);
++      dev->tx_queue_len = 32;
+       dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+       netdev_attach_ops(dev, &ieee80211_dataif_ops);
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
index a8a042b..4ca84a6 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -790,7 +790,7 @@ enum ieee80211_smps_mode {
+@@ -798,7 +798,7 @@ enum ieee80211_smps_mode {
   */
  struct ieee80211_conf {
        u32 flags;
@@ -11,7 +11,7 @@
        u16 listen_interval;
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -1551,7 +1551,7 @@ static int ieee80211_get_tx_power(struct
+@@ -1568,7 +1568,7 @@ static int ieee80211_get_tx_power(struct
  {
        struct ieee80211_local *local = wiphy_priv(wiphy);
  
index 8e104d9..894d780 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1732,6 +1732,8 @@ static int ath9k_config(struct ieee80211
+@@ -1714,6 +1714,8 @@ static int ath9k_config(struct ieee80211
                        return -EINVAL;
                }
  
@@ -9,7 +9,7 @@
                /*
                 * The most recent snapshot of channel->noisefloor for the old
                 * channel is only available after the hardware reset. Copy it to
-@@ -1749,6 +1751,7 @@ static int ath9k_config(struct ieee80211
+@@ -1731,6 +1733,7 @@ static int ath9k_config(struct ieee80211
                ath9k_cmn_update_txpow(ah, sc->curtxpow,
                                       sc->config.txpowlimit, &sc->curtxpow);
                ath9k_ps_restore(sc);
        }
  
        if (disable_radio) {
---- a/drivers/net/wireless/ath/ath9k/common.c
-+++ b/drivers/net/wireless/ath/ath9k/common.c
-@@ -161,10 +161,12 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
- void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
-                           u16 new_txpow, u16 *txpower)
- {
-+      struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
-+
-       if (cur_txpow != new_txpow) {
-               ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
-               /* read back in case value is clamped */
--              *txpower = ath9k_hw_regulatory(ah)->power_limit;
-+              *txpower = min_t(u16, reg->power_limit, reg->max_power_level);
-       }
- }
- EXPORT_SYMBOL(ath9k_cmn_update_txpow);
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -240,6 +240,7 @@ struct ath_atx_tid {
+@@ -237,6 +237,7 @@ struct ath_atx_tid {
        struct ath_node *an;
        struct ath_atx_ac *ac;
        unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
@@ -8,7 +8,7 @@
        u16 seq_start;
        u16 seq_next;
        u16 baw_size;
-@@ -286,6 +287,9 @@ struct ath_tx_control {
+@@ -282,6 +283,9 @@ struct ath_tx_control {
   *  (axq_qnum).
   */
  struct ath_tx {
@@ -20,7 +20,7 @@
        spinlock_t txbuflock;
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1341,6 +1341,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1654,6 +1654,10 @@ int ath9k_init_debug(struct ath_hw *ah)
                            sc, &fops_wiphy);
        debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_xmit);
@@ -33,7 +33,7 @@
        debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
 --- a/drivers/net/wireless/ath/ath9k/xmit.c
 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -351,6 +351,14 @@ static void ath_tx_count_frames(struct a
+@@ -350,6 +350,14 @@ static void ath_tx_count_frames(struct a
        }
  }
  
@@ -48,7 +48,7 @@
  
  static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                                 struct ath_buf *bf, struct list_head *bf_q,
-@@ -441,6 +449,8 @@ static void ath_tx_complete_aggr(struct 
+@@ -438,6 +446,8 @@ static void ath_tx_complete_aggr(struct 
        __skb_queue_head_init(&bf_pending);
  
        ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
        while (bf) {
                u16 seqno = bf->bf_state.seqno;
  
-@@ -839,6 +849,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+@@ -816,6 +826,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
                        ath_tx_addto_baw(sc, tid, seqno);
-               ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
+               bf->bf_state.ndelim = ndelim;
  
 +              tid->buf_pending++;
                __skb_unlink(skb, &tid->buf_q);
                list_add_tail(&bf->list, bf_q);
-               if (bf_prev) {
-@@ -1494,6 +1505,8 @@ static void ath_tx_send_ampdu(struct ath
+               if (bf_prev)
+@@ -1693,6 +1704,8 @@ static void ath_tx_send_ampdu(struct ath
        /* Add sub-frame to BAW */
        ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
  
@@ -74,7 +74,7 @@
        /* Queue to h/w without aggregation */
        TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
        bf->bf_lastbf = bf;
-@@ -1822,23 +1835,13 @@ error:
+@@ -1821,23 +1834,13 @@ error:
  
  /* FIXME: tx power */
  static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
  
        if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
                /*
-@@ -1880,6 +1883,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -1872,6 +1875,7 @@ int ath_tx_start(struct ieee80211_hw *hw
        struct ieee80211_vif *vif = info->control.vif;
        struct ath_softc *sc = hw->priv;
        struct ath_txq *txq = txctl->txq;
        int padpos, padsize;
        int frmlen = skb->len + FCS_LEN;
        int q;
-@@ -1912,6 +1916,7 @@ int ath_tx_start(struct ieee80211_hw *hw
-               skb_push(skb, padsize);
-               memmove(skb->data, skb->data + padsize, padpos);
-+              hdr = (struct ieee80211_hdr *) skb->data;
-       }
-       if ((vif && vif->type != NL80211_IFTYPE_AP &&
-@@ -1921,6 +1926,24 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -1916,6 +1920,24 @@ int ath_tx_start(struct ieee80211_hw *hw
  
        setup_frame_info(hw, skb, frmlen);
  
        /*
         * At this point, the vif, hw_key and sta pointers in the tx control
         * info are no longer valid (overwritten by the ath_frame_info data.
-@@ -1935,7 +1958,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -1930,7 +1952,7 @@ int ath_tx_start(struct ieee80211_hw *hw
        }
        spin_unlock_bh(&txq->axq_lock);
  
diff --git a/package/mac80211/patches/540-ath9k_txkeyidx_u8.patch b/package/mac80211/patches/540-ath9k_txkeyidx_u8.patch
deleted file mode 100644 (file)
index 2b59533..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
-@@ -273,7 +273,7 @@ static int ar9002_hw_proc_txdesc(struct 
- static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
-                                   u32 pktLen, enum ath9k_pkt_type type,
--                                  u32 txPower, u32 keyIx,
-+                                  u32 txPower, u8 keyIx,
-                                   enum ath9k_key_type keyType, u32 flags)
- {
-       struct ar5416_desc *ads = AR5416DESC(ds);
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -207,8 +207,8 @@ struct ath_atx_ac {
- struct ath_frame_info {
-       int framelen;
--      u32 keyix;
-       enum ath9k_key_type keytype;
-+      u8 keyix;
-       u8 retries;
-       u16 seqno;
- };
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -623,7 +623,7 @@ struct ath_hw_ops {
-                          struct ath_tx_status *ts);
-       void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
-                             u32 pktLen, enum ath9k_pkt_type type,
--                            u32 txPower, u32 keyIx,
-+                            u32 txPower, u8 keyIx,
-                             enum ath9k_key_type keyType,
-                             u32 flags);
-       void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -194,7 +194,7 @@ struct ath_htc_rx_status {
- #define ATH9K_RX_DECRYPT_BUSY     0x40
- #define ATH9K_RXKEYIX_INVALID ((u8)-1)
--#define ATH9K_TXKEYIX_INVALID ((u32)-1)
-+#define ATH9K_TXKEYIX_INVALID ((u8)-1)
- enum ath9k_phyerr {
-       ATH9K_PHYERR_UNDERRUN             = 0,  /* Transmit underrun */
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -312,7 +312,7 @@ static int ar9003_hw_proc_txdesc(struct 
- static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
-               u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
--              u32 keyIx, enum ath9k_key_type keyType, u32 flags)
-+              u8 keyIx, enum ath9k_key_type keyType, u32 flags)
- {
-       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
diff --git a/package/mac80211/patches/541-ath9k_aggr_queue_cleanup.patch b/package/mac80211/patches/541-ath9k_aggr_queue_cleanup.patch
deleted file mode 100644 (file)
index 27c144f..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -206,6 +206,7 @@ struct ath_atx_ac {
- };
- struct ath_frame_info {
-+      struct ath_buf *bf;
-       int framelen;
-       enum ath9k_key_type keytype;
-       u8 keyix;
-@@ -235,7 +236,7 @@ struct ath_buf {
- struct ath_atx_tid {
-       struct list_head list;
--      struct list_head buf_q;
-+      struct sk_buff_head buf_q;
-       struct ath_node *an;
-       struct ath_atx_ac *ac;
-       unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct
-                                       " tid: %p %s %s %i %p %p\n",
-                                       tid, tid->sched ? "sched" : "idle",
-                                       tid->paused ? "paused" : "running",
--                                      list_empty(&tid->buf_q),
-+                                      skb_queue_empty(&tid->buf_q),
-                                       tid->an, tid->ac);
-                       if (len >= size)
-                               goto done;
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -129,7 +129,7 @@ static void ath_tx_resume_tid(struct ath
-       spin_lock_bh(&txq->axq_lock);
-       tid->paused = false;
--      if (list_empty(&tid->buf_q))
-+      if (skb_queue_empty(&tid->buf_q))
-               goto unlock;
-       ath_tx_queue_tid(txq, tid);
-@@ -149,6 +149,7 @@ static struct ath_frame_info *get_frame_
- static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
- {
-       struct ath_txq *txq = tid->ac->txq;
-+      struct sk_buff *skb;
-       struct ath_buf *bf;
-       struct list_head bf_head;
-       struct ath_tx_status ts;
-@@ -159,12 +160,13 @@ static void ath_tx_flush_tid(struct ath_
-       memset(&ts, 0, sizeof(ts));
-       spin_lock_bh(&txq->axq_lock);
--      while (!list_empty(&tid->buf_q)) {
--              bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
--              list_move_tail(&bf->list, &bf_head);
-+      while ((skb = __skb_dequeue(&tid->buf_q))) {
-+              fi = get_frame_info(skb);
-+              bf = fi->bf;
-+
-+              list_add_tail(&bf->list, &bf_head);
-               spin_unlock_bh(&txq->axq_lock);
--              fi = get_frame_info(bf->bf_mpdu);
-               if (fi->retries) {
-                       ath_tx_update_baw(sc, tid, fi->seqno);
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
-@@ -219,6 +221,7 @@ static void ath_tid_drain(struct ath_sof
-                         struct ath_atx_tid *tid)
- {
-+      struct sk_buff *skb;
-       struct ath_buf *bf;
-       struct list_head bf_head;
-       struct ath_tx_status ts;
-@@ -227,14 +230,12 @@ static void ath_tid_drain(struct ath_sof
-       memset(&ts, 0, sizeof(ts));
-       INIT_LIST_HEAD(&bf_head);
--      for (;;) {
--              if (list_empty(&tid->buf_q))
--                      break;
-+      while ((skb = __skb_dequeue(&tid->buf_q))) {
-+              fi = get_frame_info(skb);
-+              bf = fi->bf;
--              bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
--              list_move_tail(&bf->list, &bf_head);
-+              list_add_tail(&bf->list, &bf_head);
--              fi = get_frame_info(bf->bf_mpdu);
-               if (fi->retries)
-                       ath_tx_update_baw(sc, tid, fi->seqno);
-@@ -349,7 +350,8 @@ static void ath_tx_complete_aggr(struct 
-       struct ieee80211_tx_info *tx_info;
-       struct ath_atx_tid *tid = NULL;
-       struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
--      struct list_head bf_head, bf_pending;
-+      struct list_head bf_head;
-+      struct sk_buff_head bf_pending;
-       u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
-       u32 ba[WME_BA_BMP_SIZE >> 5];
-       int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
-@@ -422,8 +424,7 @@ static void ath_tx_complete_aggr(struct 
-               }
-       }
--      INIT_LIST_HEAD(&bf_pending);
--      INIT_LIST_HEAD(&bf_head);
-+      __skb_queue_head_init(&bf_pending);
-       ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
-       while (bf) {
-@@ -467,10 +468,10 @@ static void ath_tx_complete_aggr(struct 
-                * Make sure the last desc is reclaimed if it
-                * not a holding desc.
-                */
--              if (!bf_last->bf_stale || bf_next != NULL)
-+              INIT_LIST_HEAD(&bf_head);
-+              if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
-+                  bf_next != NULL || !bf_last->bf_stale)
-                       list_move_tail(&bf->list, &bf_head);
--              else
--                      INIT_LIST_HEAD(&bf_head);
-               if (!txpending || (tid->state & AGGR_CLEANUP)) {
-                       /*
-@@ -521,7 +522,7 @@ static void ath_tx_complete_aggr(struct 
-                                       ath9k_hw_cleartxdesc(sc->sc_ah,
-                                                            tbf->bf_desc);
--                                      list_add_tail(&tbf->list, &bf_head);
-+                                      fi->bf = tbf;
-                               } else {
-                                       /*
-                                        * Clear descriptor status words for
-@@ -536,21 +537,21 @@ static void ath_tx_complete_aggr(struct 
-                        * Put this buffer to the temporary pending
-                        * queue to retain ordering
-                        */
--                      list_splice_tail_init(&bf_head, &bf_pending);
-+                      __skb_queue_tail(&bf_pending, skb);
-               }
-               bf = bf_next;
-       }
-       /* prepend un-acked frames to the beginning of the pending frame queue */
--      if (!list_empty(&bf_pending)) {
-+      if (!skb_queue_empty(&bf_pending)) {
-               if (an->sleeping)
-                       ieee80211_sta_set_tim(sta);
-               spin_lock_bh(&txq->axq_lock);
-               if (clear_filter)
-                       tid->ac->clear_ps_filter = true;
--              list_splice(&bf_pending, &tid->buf_q);
-+              skb_queue_splice(&bf_pending, &tid->buf_q);
-               if (!an->sleeping)
-                       ath_tx_queue_tid(txq, tid);
-               spin_unlock_bh(&txq->axq_lock);
-@@ -743,19 +744,22 @@ static enum ATH_AGGR_STATUS ath_tx_form_
-                                            int *aggr_len)
- {
- #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
--      struct ath_buf *bf, *bf_first, *bf_prev = NULL;
-+      struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
-       int rl = 0, nframes = 0, ndelim, prev_al = 0;
-       u16 aggr_limit = 0, al = 0, bpad = 0,
-               al_delta, h_baw = tid->baw_size / 2;
-       enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
-       struct ieee80211_tx_info *tx_info;
-       struct ath_frame_info *fi;
--
--      bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
-+      struct sk_buff *skb;
-       do {
--              bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
--              fi = get_frame_info(bf->bf_mpdu);
-+              skb = skb_peek(&tid->buf_q);
-+              fi = get_frame_info(skb);
-+              bf = fi->bf;
-+
-+              if (!bf_first)
-+                      bf_first = bf;
-               /* do not step over block-ack window */
-               if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
-@@ -808,7 +812,9 @@ static enum ATH_AGGR_STATUS ath_tx_form_
-               if (!fi->retries)
-                       ath_tx_addto_baw(sc, tid, fi->seqno);
-               ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
--              list_move_tail(&bf->list, bf_q);
-+
-+              __skb_unlink(skb, &tid->buf_q);
-+              list_add_tail(&bf->list, bf_q);
-               if (bf_prev) {
-                       bf_prev->bf_next = bf;
-                       ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
-@@ -816,7 +822,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
-               }
-               bf_prev = bf;
--      } while (!list_empty(&tid->buf_q));
-+      } while (!skb_queue_empty(&tid->buf_q));
-       *aggr_len = al;
-@@ -834,7 +840,7 @@ static void ath_tx_sched_aggr(struct ath
-       int aggr_len;
-       do {
--              if (list_empty(&tid->buf_q))
-+              if (skb_queue_empty(&tid->buf_q))
-                       return;
-               INIT_LIST_HEAD(&bf_q);
-@@ -955,7 +961,7 @@ bool ath_tx_aggr_sleep(struct ath_softc 
-               spin_lock_bh(&txq->axq_lock);
--              if (!list_empty(&tid->buf_q))
-+              if (!skb_queue_empty(&tid->buf_q))
-                       buffered = true;
-               tid->sched = false;
-@@ -988,7 +994,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
-               spin_lock_bh(&txq->axq_lock);
-               ac->clear_ps_filter = true;
--              if (!list_empty(&tid->buf_q) && !tid->paused) {
-+              if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
-                       ath_tx_queue_tid(txq, tid);
-                       ath_txq_schedule(sc, txq);
-               }
-@@ -1332,7 +1338,7 @@ void ath_txq_schedule(struct ath_softc *
-                        * add tid to round-robin queue if more frames
-                        * are pending for the tid
-                        */
--                      if (!list_empty(&tid->buf_q))
-+                      if (!skb_queue_empty(&tid->buf_q))
-                               ath_tx_queue_tid(txq, tid);
-                       if (tid == last_tid ||
-@@ -1438,7 +1444,7 @@ static void ath_tx_send_ampdu(struct ath
-        * - seqno is not within block-ack window
-        * - h/w queue depth exceeds low water mark
-        */
--      if (!list_empty(&tid->buf_q) || tid->paused ||
-+      if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
-           !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
-           txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
-               /*
-@@ -1446,7 +1452,7 @@ static void ath_tx_send_ampdu(struct ath
-                * for aggregation.
-                */
-               TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
--              list_add_tail(&bf->list, &tid->buf_q);
-+              __skb_queue_tail(&tid->buf_q, bf->bf_mpdu);
-               if (!txctl->an || !txctl->an->sleeping)
-                       ath_tx_queue_tid(txctl->txq, tid);
-               return;
-@@ -1777,6 +1783,7 @@ static struct ath_buf *ath_tx_setup_buff
-                           bf->bf_buf_addr,
-                           txq->axq_qnum);
-+      fi->bf = bf;
-       return bf;
- }
-@@ -2394,7 +2401,7 @@ void ath_tx_node_init(struct ath_softc *
-               tid->sched     = false;
-               tid->paused    = false;
-               tid->state &= ~AGGR_CLEANUP;
--              INIT_LIST_HEAD(&tid->buf_q);
-+              __skb_queue_head_init(&tid->buf_q);
-               acno = TID_TO_WME_AC(tidno);
-               tid->ac = &an->ac[acno];
-               tid->state &= ~AGGR_ADDBA_COMPLETE;
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/xmit.c
 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -260,14 +260,17 @@ static void ath_tid_drain(struct ath_sof
+@@ -259,14 +259,17 @@ static void ath_tid_drain(struct ath_sof
  }
  
  static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
@@ -20,7 +20,7 @@
                return;
  
        hdr = (struct ieee80211_hdr *)skb->data;
-@@ -383,6 +386,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -382,6 +385,7 @@ static void ath_tx_complete_aggr(struct 
        int nframes;
        u8 tidno;
        bool clear_filter;
@@ -28,7 +28,7 @@
  
        skb = bf->bf_mpdu;
        hdr = (struct ieee80211_hdr *)skb->data;
-@@ -391,6 +395,10 @@ static void ath_tx_complete_aggr(struct 
+@@ -390,6 +394,10 @@ static void ath_tx_complete_aggr(struct 
  
        memcpy(rates, tx_info->control.rates, sizeof(rates));
  
@@ -39,7 +39,7 @@
        rcu_read_lock();
  
        sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
-@@ -478,7 +486,8 @@ static void ath_tx_complete_aggr(struct 
+@@ -475,7 +483,8 @@ static void ath_tx_complete_aggr(struct 
                        } else if (fi->retries < ATH_MAX_SW_RETRIES) {
                                if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
                                    !an->sleeping)
@@ -51,7 +51,7 @@
                                txpending = 1;
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -543,7 +543,7 @@ struct ath_ant_comb {
+@@ -540,7 +540,7 @@ struct ath_ant_comb {
  #define DEFAULT_CACHELINE       32
  #define ATH_REGCLASSIDS_MAX     10
  #define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
diff --git a/package/mac80211/patches/542-ath9k_move_seqno.patch b/package/mac80211/patches/542-ath9k_move_seqno.patch
deleted file mode 100644 (file)
index c0d293a..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -211,12 +211,12 @@ struct ath_frame_info {
-       enum ath9k_key_type keytype;
-       u8 keyix;
-       u8 retries;
--      u16 seqno;
- };
- struct ath_buf_state {
-       u8 bf_type;
-       u8 bfs_paprd;
-+      u16 seqno;
-       unsigned long bfs_paprd_timestamp;
- };
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -168,7 +168,7 @@ static void ath_tx_flush_tid(struct ath_
-               spin_unlock_bh(&txq->axq_lock);
-               if (fi->retries) {
--                      ath_tx_update_baw(sc, tid, fi->seqno);
-+                      ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
-               } else {
-                       ath_tx_send_normal(sc, txq, NULL, &bf_head);
-@@ -237,7 +237,7 @@ static void ath_tid_drain(struct ath_sof
-               list_add_tail(&bf->list, &bf_head);
-               if (fi->retries)
--                      ath_tx_update_baw(sc, tid, fi->seqno);
-+                      ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
-               spin_unlock(&txq->axq_lock);
-               ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-@@ -327,7 +327,7 @@ static void ath_tx_count_frames(struct a
-       while (bf) {
-               fi = get_frame_info(bf->bf_mpdu);
--              ba_index = ATH_BA_INDEX(seq_st, fi->seqno);
-+              ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno);
-               (*nframes)++;
-               if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
-@@ -428,6 +428,8 @@ static void ath_tx_complete_aggr(struct 
-       ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
-       while (bf) {
-+              u16 seqno = bf->bf_state.seqno;
-+
-               txfail = txpending = sendbar = 0;
-               bf_next = bf->bf_next;
-@@ -435,7 +437,7 @@ static void ath_tx_complete_aggr(struct 
-               tx_info = IEEE80211_SKB_CB(skb);
-               fi = get_frame_info(skb);
--              if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) {
-+              if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
-                       /* transmit completion, subframe is
-                        * acked by block ack */
-                       acked_cnt++;
-@@ -479,7 +481,7 @@ static void ath_tx_complete_aggr(struct 
-                        * block-ack window
-                        */
-                       spin_lock_bh(&txq->axq_lock);
--                      ath_tx_update_baw(sc, tid, fi->seqno);
-+                      ath_tx_update_baw(sc, tid, seqno);
-                       spin_unlock_bh(&txq->axq_lock);
-                       if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
-@@ -507,7 +509,7 @@ static void ath_tx_complete_aggr(struct 
-                                        */
-                                       if (!tbf) {
-                                               spin_lock_bh(&txq->axq_lock);
--                                              ath_tx_update_baw(sc, tid, fi->seqno);
-+                                              ath_tx_update_baw(sc, tid, seqno);
-                                               spin_unlock_bh(&txq->axq_lock);
-                                               bf->bf_state.bf_type |=
-@@ -752,17 +754,19 @@ static enum ATH_AGGR_STATUS ath_tx_form_
-       struct ieee80211_tx_info *tx_info;
-       struct ath_frame_info *fi;
-       struct sk_buff *skb;
-+      u16 seqno;
-       do {
-               skb = skb_peek(&tid->buf_q);
-               fi = get_frame_info(skb);
-               bf = fi->bf;
-+              seqno = bf->bf_state.seqno;
-               if (!bf_first)
-                       bf_first = bf;
-               /* do not step over block-ack window */
--              if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
-+              if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
-                       status = ATH_AGGR_BAW_CLOSED;
-                       break;
-               }
-@@ -810,7 +814,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
-               /* link buffers of this frame to the aggregate */
-               if (!fi->retries)
--                      ath_tx_addto_baw(sc, tid, fi->seqno);
-+                      ath_tx_addto_baw(sc, tid, seqno);
-               ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
-               __skb_unlink(skb, &tid->buf_q);
-@@ -1434,6 +1438,7 @@ static void ath_tx_send_ampdu(struct ath
- {
-       struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
-       struct list_head bf_head;
-+      u16 seqno = bf->bf_state.seqno;
-       bf->bf_state.bf_type |= BUF_AMPDU;
-@@ -1445,7 +1450,7 @@ static void ath_tx_send_ampdu(struct ath
-        * - h/w queue depth exceeds low water mark
-        */
-       if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
--          !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
-+          !BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) ||
-           txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
-               /*
-                * Add this frame to software queue for scheduling later
-@@ -1463,7 +1468,7 @@ static void ath_tx_send_ampdu(struct ath
-       /* Add sub-frame to BAW */
-       if (!fi->retries)
--              ath_tx_addto_baw(sc, tid, fi->seqno);
-+              ath_tx_addto_baw(sc, tid, seqno);
-       /* Queue to h/w without aggregation */
-       TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
-@@ -1519,39 +1524,19 @@ static enum ath9k_pkt_type get_hw_packet
- static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
-                            int framelen)
- {
--      struct ath_softc *sc = hw->priv;
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_sta *sta = tx_info->control.sta;
-       struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
--      struct ieee80211_hdr *hdr;
-+      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct ath_frame_info *fi = get_frame_info(skb);
-       struct ath_node *an = NULL;
--      struct ath_atx_tid *tid;
-       enum ath9k_key_type keytype;
--      u16 seqno = 0;
--      u8 tidno;
-       keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
-       if (sta)
-               an = (struct ath_node *) sta->drv_priv;
--      hdr = (struct ieee80211_hdr *)skb->data;
--      if (an && ieee80211_is_data_qos(hdr->frame_control) &&
--              conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
--
--              tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
--
--              /*
--               * Override seqno set by upper layer with the one
--               * in tx aggregation state.
--               */
--              tid = ATH_AN_2_TID(an, tidno);
--              seqno = tid->seq_next;
--              hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
--              INCR(tid->seq_next, IEEE80211_SEQ_MAX);
--      }
--
-       memset(fi, 0, sizeof(*fi));
-       if (hw_key)
-               fi->keyix = hw_key->hw_key_idx;
-@@ -1561,7 +1546,6 @@ static void setup_frame_info(struct ieee
-               fi->keyix = ATH9K_TXKEYIX_INVALID;
-       fi->keytype = keytype;
-       fi->framelen = framelen;
--      fi->seqno = seqno;
- }
- static int setup_tx_flags(struct sk_buff *skb)
-@@ -1797,6 +1781,7 @@ static void ath_tx_start_dma(struct ath_
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct list_head bf_head;
-       struct ath_atx_tid *tid = NULL;
-+      u16 seqno;
-       u8 tidno;
-       spin_lock_bh(&txctl->txq->axq_lock);
-@@ -1806,6 +1791,12 @@ static void ath_tx_start_dma(struct ath_
-                       IEEE80211_QOS_CTL_TID_MASK;
-               tid = ATH_AN_2_TID(txctl->an, tidno);
-+              seqno = tid->seq_next;
-+              hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
-+              INCR(tid->seq_next, IEEE80211_SEQ_MAX);
-+
-+              bf->bf_state.seqno = seqno;
-+
-               WARN_ON(tid->ac->txq != txctl->txq);
-       }
diff --git a/package/mac80211/patches/543-ath9k_move_seqno_alloc.patch b/package/mac80211/patches/543-ath9k_move_seqno_alloc.patch
deleted file mode 100644 (file)
index 8de5fd2..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -1717,17 +1717,19 @@ static void ath_buf_set_rate(struct ath_
- }
--static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
-+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
-                                          struct ath_txq *txq,
-+                                         struct ath_atx_tid *tid,
-                                          struct sk_buff *skb)
- {
--      struct ath_softc *sc = hw->priv;
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath_frame_info *fi = get_frame_info(skb);
-+      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct ath_buf *bf;
-       struct ath_desc *ds;
-       int frm_type;
-+      u16 seqno;
-       bf = ath_tx_get_buffer(sc);
-       if (!bf) {
-@@ -1737,6 +1739,13 @@ static struct ath_buf *ath_tx_setup_buff
-       ATH_TXBUF_RESET(bf);
-+      if (tid) {
-+              seqno = tid->seq_next;
-+              hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
-+              INCR(tid->seq_next, IEEE80211_SEQ_MAX);
-+              bf->bf_state.seqno = seqno;
-+      }
-+
-       bf->bf_flags = setup_tx_flags(skb);
-       bf->bf_mpdu = skb;
-@@ -1773,15 +1782,15 @@ static struct ath_buf *ath_tx_setup_buff
- }
- /* FIXME: tx power */
--static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
-+static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
-                            struct ath_tx_control *txctl)
- {
--      struct sk_buff *skb = bf->bf_mpdu;
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct list_head bf_head;
-       struct ath_atx_tid *tid = NULL;
--      u16 seqno;
-+      struct ath_buf *bf;
-+      int ret = 0;
-       u8 tidno;
-       spin_lock_bh(&txctl->txq->axq_lock);
-@@ -1791,15 +1800,15 @@ static void ath_tx_start_dma(struct ath_
-                       IEEE80211_QOS_CTL_TID_MASK;
-               tid = ATH_AN_2_TID(txctl->an, tidno);
--              seqno = tid->seq_next;
--              hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
--              INCR(tid->seq_next, IEEE80211_SEQ_MAX);
--
--              bf->bf_state.seqno = seqno;
--
-               WARN_ON(tid->ac->txq != txctl->txq);
-       }
-+      bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
-+      if (unlikely(!bf)) {
-+              ret = -ENOMEM;
-+              goto out;
-+      }
-+
-       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
-               /*
-                * Try aggregation if it's a unicast data frame
-@@ -1825,7 +1834,9 @@ static void ath_tx_start_dma(struct ath_
-               ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
-       }
-+out:
-       spin_unlock_bh(&txctl->txq->axq_lock);
-+      return ret;
- }
- /* Upon failure caller should free skb */
-@@ -1838,7 +1849,6 @@ int ath_tx_start(struct ieee80211_hw *hw
-       struct ieee80211_vif *vif = info->control.vif;
-       struct ath_softc *sc = hw->priv;
-       struct ath_txq *txq = txctl->txq;
--      struct ath_buf *bf;
-       int padpos, padsize;
-       int frmlen = skb->len + FCS_LEN;
-       int q;
-@@ -1885,10 +1895,6 @@ int ath_tx_start(struct ieee80211_hw *hw
-        * info are no longer valid (overwritten by the ath_frame_info data.
-        */
--      bf = ath_tx_setup_buffer(hw, txctl->txq, skb);
--      if (unlikely(!bf))
--              return -ENOMEM;
--
-       q = skb_get_queue_mapping(skb);
-       spin_lock_bh(&txq->axq_lock);
-       if (txq == sc->tx.txq_map[q] &&
-@@ -1898,9 +1904,7 @@ int ath_tx_start(struct ieee80211_hw *hw
-       }
-       spin_unlock_bh(&txq->axq_lock);
--      ath_tx_start_dma(sc, bf, txctl);
--
--      return 0;
-+      return ath_tx_start_dma(sc, skb, txctl);
- }
- /*****************/
diff --git a/package/mac80211/patches/544-ath9k_defer_buffer_setup.patch b/package/mac80211/patches/544-ath9k_defer_buffer_setup.patch
deleted file mode 100644 (file)
index d91ced0..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -48,8 +48,9 @@ static u16 bits_per_symbol[][2] = {
- #define IS_HT_RATE(_rate)     ((_rate) & 0x80)
- static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
--                             struct ath_atx_tid *tid,
--                             struct list_head *bf_head);
-+                             struct ath_atx_tid *tid, struct sk_buff *skb);
-+static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-+                          int tx_flags, struct ath_txq *txq);
- static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
-                               struct ath_txq *txq, struct list_head *bf_q,
-                               struct ath_tx_status *ts, int txok, int sendbar);
-@@ -61,6 +62,10 @@ static void ath_tx_rc_status(struct ath_
-                            int txok, bool update_rc);
- static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
-                             int seqno);
-+static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
-+                                         struct ath_txq *txq,
-+                                         struct ath_atx_tid *tid,
-+                                         struct sk_buff *skb);
- enum {
-       MCS_HT20,
-@@ -164,14 +169,13 @@ static void ath_tx_flush_tid(struct ath_
-               fi = get_frame_info(skb);
-               bf = fi->bf;
--              list_add_tail(&bf->list, &bf_head);
--
-               spin_unlock_bh(&txq->axq_lock);
--              if (fi->retries) {
-+              if (bf && fi->retries) {
-+                      list_add_tail(&bf->list, &bf_head);
-                       ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
-               } else {
--                      ath_tx_send_normal(sc, txq, NULL, &bf_head);
-+                      ath_tx_send_normal(sc, txq, NULL, skb);
-               }
-               spin_lock_bh(&txq->axq_lock);
-       }
-@@ -234,6 +238,13 @@ static void ath_tid_drain(struct ath_sof
-               fi = get_frame_info(skb);
-               bf = fi->bf;
-+              if (!bf) {
-+                      spin_unlock(&txq->axq_lock);
-+                      ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
-+                      spin_lock(&txq->axq_lock);
-+                      continue;
-+              }
-+
-               list_add_tail(&bf->list, &bf_head);
-               if (fi->retries)
-@@ -760,8 +771,14 @@ static enum ATH_AGGR_STATUS ath_tx_form_
-               skb = skb_peek(&tid->buf_q);
-               fi = get_frame_info(skb);
-               bf = fi->bf;
--              seqno = bf->bf_state.seqno;
-+              if (!fi->bf)
-+                      bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-+              if (!bf)
-+                      continue;
-+
-+              bf->bf_state.bf_type |= BUF_AMPDU;
-+              seqno = bf->bf_state.seqno;
-               if (!bf_first)
-                       bf_first = bf;
-@@ -1434,13 +1451,11 @@ static void ath_tx_txqaddbuf(struct ath_
- }
- static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
--                            struct ath_buf *bf, struct ath_tx_control *txctl)
-+                            struct sk_buff *skb, struct ath_tx_control *txctl)
- {
--      struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
-+      struct ath_frame_info *fi = get_frame_info(skb);
-       struct list_head bf_head;
--      u16 seqno = bf->bf_state.seqno;
--
--      bf->bf_state.bf_type |= BUF_AMPDU;
-+      struct ath_buf *bf;
-       /*
-        * Do not queue to h/w when any of the following conditions is true:
-@@ -1450,25 +1465,29 @@ static void ath_tx_send_ampdu(struct ath
-        * - h/w queue depth exceeds low water mark
-        */
-       if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
--          !BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) ||
-+          !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
-           txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
-               /*
-                * Add this frame to software queue for scheduling later
-                * for aggregation.
-                */
-               TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
--              __skb_queue_tail(&tid->buf_q, bf->bf_mpdu);
-+              __skb_queue_tail(&tid->buf_q, skb);
-               if (!txctl->an || !txctl->an->sleeping)
-                       ath_tx_queue_tid(txctl->txq, tid);
-               return;
-       }
-+      bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
-+      if (!bf)
-+              return;
-+
-+      bf->bf_state.bf_type |= BUF_AMPDU;
-       INIT_LIST_HEAD(&bf_head);
-       list_add(&bf->list, &bf_head);
-       /* Add sub-frame to BAW */
--      if (!fi->retries)
--              ath_tx_addto_baw(sc, tid, seqno);
-+      ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
-       /* Queue to h/w without aggregation */
-       TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
-@@ -1478,13 +1497,21 @@ static void ath_tx_send_ampdu(struct ath
- }
- static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
--                             struct ath_atx_tid *tid,
--                             struct list_head *bf_head)
-+                             struct ath_atx_tid *tid, struct sk_buff *skb)
- {
--      struct ath_frame_info *fi;
-+      struct ath_frame_info *fi = get_frame_info(skb);
-+      struct list_head bf_head;
-       struct ath_buf *bf;
--      bf = list_first_entry(bf_head, struct ath_buf, list);
-+      bf = fi->bf;
-+      if (!bf)
-+              bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-+
-+      if (!bf)
-+              return;
-+
-+      INIT_LIST_HEAD(&bf_head);
-+      list_add_tail(&bf->list, &bf_head);
-       bf->bf_state.bf_type &= ~BUF_AMPDU;
-       /* update starting sequence number for subsequent ADDBA request */
-@@ -1492,9 +1519,8 @@ static void ath_tx_send_normal(struct at
-               INCR(tid->seq_start, IEEE80211_SEQ_MAX);
-       bf->bf_lastbf = bf;
--      fi = get_frame_info(bf->bf_mpdu);
-       ath_buf_set_rate(sc, bf, fi->framelen);
--      ath_tx_txqaddbuf(sc, txq, bf_head, false);
-+      ath_tx_txqaddbuf(sc, txq, &bf_head, false);
-       TX_STAT_INC(txq->axq_qnum, queued);
- }
-@@ -1717,6 +1743,10 @@ static void ath_buf_set_rate(struct ath_
- }
-+/*
-+ * Assign a descriptor (and sequence number if necessary,
-+ * and map buffer for DMA. Frees skb on error
-+ */
- static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
-                                          struct ath_txq *txq,
-                                          struct ath_atx_tid *tid,
-@@ -1734,7 +1764,7 @@ static struct ath_buf *ath_tx_setup_buff
-       bf = ath_tx_get_buffer(sc);
-       if (!bf) {
-               ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n");
--              return NULL;
-+              goto error;
-       }
-       ATH_TXBUF_RESET(bf);
-@@ -1757,7 +1787,7 @@ static struct ath_buf *ath_tx_setup_buff
-               ath_err(ath9k_hw_common(sc->sc_ah),
-                       "dma_mapping_error() on TX\n");
-               ath_tx_return_buffer(sc, bf);
--              return NULL;
-+              goto error;
-       }
-       frm_type = get_hw_packet_type(skb);
-@@ -1779,18 +1809,20 @@ static struct ath_buf *ath_tx_setup_buff
-       fi->bf = bf;
-       return bf;
-+
-+error:
-+      dev_kfree_skb_any(skb);
-+      return NULL;
- }
- /* FIXME: tx power */
--static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
-+static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
-                            struct ath_tx_control *txctl)
- {
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
--      struct list_head bf_head;
-       struct ath_atx_tid *tid = NULL;
-       struct ath_buf *bf;
--      int ret = 0;
-       u8 tidno;
-       spin_lock_bh(&txctl->txq->axq_lock);
-@@ -1803,21 +1835,16 @@ static int ath_tx_start_dma(struct ath_s
-               WARN_ON(tid->ac->txq != txctl->txq);
-       }
--      bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
--      if (unlikely(!bf)) {
--              ret = -ENOMEM;
--              goto out;
--      }
--
-       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
-               /*
-                * Try aggregation if it's a unicast data frame
-                * and the destination is HT capable.
-                */
--              ath_tx_send_ampdu(sc, tid, bf, txctl);
-+              ath_tx_send_ampdu(sc, tid, skb, txctl);
-       } else {
--              INIT_LIST_HEAD(&bf_head);
--              list_add_tail(&bf->list, &bf_head);
-+              bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
-+              if (!bf)
-+                      goto out;
-               bf->bf_state.bfs_paprd = txctl->paprd;
-@@ -1831,12 +1858,11 @@ static int ath_tx_start_dma(struct ath_s
-               if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
-                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
--              ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
-+              ath_tx_send_normal(sc, txctl->txq, tid, skb);
-       }
- out:
-       spin_unlock_bh(&txctl->txq->axq_lock);
--      return ret;
- }
- /* Upon failure caller should free skb */
-@@ -1904,7 +1930,8 @@ int ath_tx_start(struct ieee80211_hw *hw
-       }
-       spin_unlock_bh(&txq->axq_lock);
--      return ath_tx_start_dma(sc, skb, txctl);
-+      ath_tx_start_dma(sc, skb, txctl);
-+      return 0;
- }
- /*****************/
diff --git a/package/mac80211/patches/545-ath9k_aggr_padding_fix.patch b/package/mac80211/patches/545-ath9k_aggr_padding_fix.patch
deleted file mode 100644 (file)
index 77938c4..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -709,7 +709,9 @@ static int ath_compute_num_delims(struct
-        * Add delimiter when using RTS/CTS with aggregation
-        * and non enterprise AR9003 card
-        */
--      if (first_subfrm)
-+      if (first_subfrm && (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
-+          !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
-+          (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
-               ndelim = max(ndelim, FIRST_DESC_NDELIMS);
-       /*
---- a/drivers/net/wireless/ath/ath9k/reg.h
-+++ b/drivers/net/wireless/ath/ath9k/reg.h
-@@ -1132,7 +1132,7 @@ enum {
- #define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
- #define AR_ENT_OTP              0x40d8
- #define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
--#define AR_ENT_OTP_MPSD               0x00800000
-+#define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE               0x00800000
- #define AR_CH0_BB_DPLL1                0x16180
- #define AR_CH0_BB_DPLL1_REFDIV         0xF8000000
diff --git a/package/mac80211/patches/546-ath9k_retry_cache_sync.patch b/package/mac80211/patches/546-ath9k_retry_cache_sync.patch
deleted file mode 100644 (file)
index ed543ac..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -263,6 +263,7 @@ static void ath_tx_set_retry(struct ath_
-                            struct sk_buff *skb)
- {
-       struct ath_frame_info *fi = get_frame_info(skb);
-+      struct ath_buf *bf = fi->bf;
-       struct ieee80211_hdr *hdr;
-       TX_STAT_INC(txq->axq_qnum, a_retries);
-@@ -271,6 +272,8 @@ static void ath_tx_set_retry(struct ath_
-       hdr = (struct ieee80211_hdr *)skb->data;
-       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
-+      dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
-+              sizeof(*hdr), DMA_TO_DEVICE);
- }
- static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
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..931c50e
--- /dev/null
@@ -0,0 +1,93 @@
+--- 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
+@@ -826,7 +826,8 @@ static bool ath9k_rx_accept(struct ath_c
+               test_bit(rx_stats->rs_keyix, common->tkip_keymap);
+       strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
+               !(rx_stats->rs_status &
+-              (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));
++              (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
++               ATH9K_RXERR_KEYMISS));
+       if (!rx_stats->rs_datalen)
+               return false;
+@@ -854,6 +855,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 +864,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 +875,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;
+       }
+       /*
diff --git a/package/mac80211/patches/552-ath9k_fix_phyerror.patch b/package/mac80211/patches/552-ath9k_fix_phyerror.patch
new file mode 100644 (file)
index 0000000..3ef090e
--- /dev/null
@@ -0,0 +1,37 @@
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -425,12 +425,9 @@ void ath_rx_cleanup(struct ath_softc *sc
+ u32 ath_calcrxfilter(struct ath_softc *sc)
+ {
+-#define       RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
+-
+       u32 rfilt;
+-      rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
+-              | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
++      rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
+               | ATH9K_RX_FILTER_MCAST;
+       if (sc->rx.rxfilter & FIF_PROBE_REQ)
+--- a/drivers/net/wireless/ath/ath9k/ani.c
++++ b/drivers/net/wireless/ath/ath9k/ani.c
+@@ -502,9 +502,6 @@ static void ath9k_ani_reset_old(struct a
+               ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+                                    ATH9K_ANI_CCK_WEAK_SIG_THR);
+-              ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
+-                                   ATH9K_RX_FILTER_PHYERR);
+-
+               ath9k_ani_restart(ah);
+               return;
+       }
+@@ -525,8 +522,6 @@ static void ath9k_ani_reset_old(struct a
+               ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+                                    aniState->firstepLevel);
+-      ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
+-                           ~ATH9K_RX_FILTER_PHYERR);
+       ath9k_ani_restart(ah);
+       ENABLE_REGWRITE_BUFFER(ah);
diff --git a/package/mac80211/patches/560-mac80211_defer_bar_tx.patch b/package/mac80211/patches/560-mac80211_defer_bar_tx.patch
deleted file mode 100644 (file)
index 15f812c..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -84,6 +84,8 @@ enum ieee80211_sta_info_flags {
-  * @stop_initiator: initiator of a session stop
-  * @tx_stop: TX DelBA frame when stopping
-  * @buf_size: reorder buffer size at receiver
-+ * @failed_bar_ssn: ssn of the last failed BAR tx attempt
-+ * @bar_pending: BAR needs to be re-sent
-  *
-  * This structure's lifetime is managed by RCU, assignments to
-  * the array holding it must hold the aggregation mutex.
-@@ -104,6 +106,9 @@ struct tid_ampdu_tx {
-       u8 stop_initiator;
-       bool tx_stop;
-       u8 buf_size;
-+
-+      u16 failed_bar_ssn;
-+      bool bar_pending;
- };
- /**
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -127,12 +127,32 @@ static void ieee80211_handle_filtered_fr
-       dev_kfree_skb(skb);
- }
-+static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
-+{
-+      struct tid_ampdu_tx *tid_tx;
-+
-+      tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-+      if (!tid_tx || !tid_tx->bar_pending)
-+              return;
-+
-+      tid_tx->bar_pending = false;
-+      ieee80211_send_bar(sta->sdata, addr, tid, tid_tx->failed_bar_ssn);
-+}
-+
- static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
- {
-       struct ieee80211_mgmt *mgmt = (void *) skb->data;
-       struct ieee80211_local *local = sta->local;
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
-+      if (ieee80211_is_data_qos(mgmt->frame_control)) {
-+              struct ieee80211_hdr *hdr = (void *) skb->data;
-+              u8 *qc = ieee80211_get_qos_ctl(hdr);
-+              u16 tid = qc[0] & 0xf;
-+
-+              ieee80211_check_pending_bar(sta, hdr->addr1, tid);
-+      }
-+
-       if (ieee80211_is_action(mgmt->frame_control) &&
-           sdata->vif.type == NL80211_IFTYPE_STATION &&
-           mgmt->u.action.category == WLAN_CATEGORY_HT &&
-@@ -161,6 +181,18 @@ static void ieee80211_frame_acked(struct
-       }
- }
-+static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
-+{
-+      struct tid_ampdu_tx *tid_tx;
-+
-+      tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-+      if (!tid_tx)
-+              return;
-+
-+      tid_tx->failed_bar_ssn = ssn;
-+      tid_tx->bar_pending = true;
-+}
-+
- /*
-  * Use a static threshold for now, best value to be determined
-  * by testing ...
-@@ -246,6 +278,8 @@ void ieee80211_tx_status(struct ieee8021
-               }
-               if (!acked && ieee80211_is_back_req(fc)) {
-+                      u16 control;
-+
-                       /*
-                        * BAR failed, let's tear down the BA session as a
-                        * last resort as some STAs (Intel 5100 on Windows)
-@@ -253,11 +287,15 @@ void ieee80211_tx_status(struct ieee8021
-                        * correctly.
-                        */
-                       bar = (struct ieee80211_bar *) skb->data;
--                      if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
--                              tid = (bar->control &
-+                      control = le16_to_cpu(bar->control);
-+                      if (!(control & IEEE80211_BAR_CTRL_MULTI_TID)) {
-+                              u16 ssn = le16_to_cpu(bar->start_seq_num);
-+
-+                              tid = (control &
-                                      IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
-                                     IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
--                              ieee80211_stop_tx_ba_session(&sta->sta, tid);
-+
-+                              ieee80211_set_bar_pending(sta, tid, ssn);
-                       }
-               }
diff --git a/package/mac80211/patches/560-minstrel_ht_optimize.patch b/package/mac80211/patches/560-minstrel_ht_optimize.patch
new file mode 100644 (file)
index 0000000..d27ca59
--- /dev/null
@@ -0,0 +1,167 @@
+--- a/net/mac80211/rc80211_minstrel_ht.h
++++ b/net/mac80211/rc80211_minstrel_ht.h
+@@ -70,6 +70,8 @@ struct minstrel_mcs_group_data {
+ };
+ struct minstrel_ht_sta {
++      struct ieee80211_tx_rate tx_rates[3];
++
+       /* ampdu length (average, per sampling interval) */
+       unsigned int ampdu_len;
+       unsigned int ampdu_packets;
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -87,6 +87,10 @@ const struct mcs_group minstrel_mcs_grou
+ static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
++static void
++minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
++                     struct ieee80211_tx_rate *rate, int index,
++                     bool sample, bool rtscts);
+ /*
+  * Perform EWMA (Exponentially Weighted Moving Average) calculation
+  */
+@@ -174,6 +178,17 @@ minstrel_ht_calc_tp(struct minstrel_priv
+       mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);
+ }
++static void
++minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
++{
++      minstrel_ht_set_rate(mp, mi, &mi->tx_rates[0], mi->max_tp_rate,
++                           false, false);
++      minstrel_ht_set_rate(mp, mi, &mi->tx_rates[1], mi->max_tp_rate2,
++                           false, true);
++      minstrel_ht_set_rate(mp, mi, &mi->tx_rates[2], mi->max_prob_rate,
++                           false, true);
++}
++
+ /*
+  * Update rate statistics and select new primary rates
+  *
+@@ -292,6 +307,7 @@ minstrel_ht_update_stats(struct minstrel
+               }
+       }
++      minstrel_ht_update_rates(mp, mi);
+       mi->stats_update = jiffies;
+ }
+@@ -330,8 +346,8 @@ minstrel_next_sample_idx(struct minstrel
+ }
+ static void
+-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
+-                      bool primary)
++minstrel_downgrade_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
++                      unsigned int *idx, bool primary)
+ {
+       int group, orig_group;
+@@ -350,6 +366,7 @@ minstrel_downgrade_rate(struct minstrel_
+                       *idx = mi->groups[group].max_tp_rate;
+               else
+                       *idx = mi->groups[group].max_tp_rate2;
++              minstrel_ht_update_rates(mp, mi);
+               break;
+       }
+ }
+@@ -450,13 +467,13 @@ minstrel_ht_tx_status(void *priv, struct
+       if (rate->attempts > 30 &&
+           MINSTREL_FRAC(rate->success, rate->attempts) <
+           MINSTREL_FRAC(20, 100))
+-              minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
++              minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate, true);
+       rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
+       if (rate2->attempts > 30 &&
+           MINSTREL_FRAC(rate2->success, rate2->attempts) <
+           MINSTREL_FRAC(20, 100))
+-              minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
++              minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate2, false);
+       if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
+               minstrel_ht_update_stats(mp, mi);
+@@ -521,7 +538,6 @@ minstrel_calc_retransmit(struct minstrel
+ static void
+ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+                      struct ieee80211_tx_rate *rate, int index,
+-                     struct ieee80211_tx_rate_control *txrc,
+                      bool sample, bool rtscts)
+ {
+       const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
+@@ -609,6 +625,7 @@ minstrel_ht_get_rate(void *priv, struct 
+       struct minstrel_priv *mp = priv;
+       int sample_idx;
+       bool sample = false;
++      int last = 0;
+       if (rate_control_send_low(sta, priv_sta, txrc))
+               return;
+@@ -634,11 +651,10 @@ minstrel_ht_get_rate(void *priv, struct 
+       if (sample_idx >= 0) {
+               sample = true;
+               minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
+-                      txrc, true, false);
++                      true, false);
+               info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+       } else {
+-              minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
+-                      txrc, false, false);
++              ar[0] = mi->tx_rates[0];
+       }
+       if (mp->hw->max_rates >= 3) {
+@@ -648,33 +664,27 @@ minstrel_ht_get_rate(void *priv, struct 
+                * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
+                */
+               if (sample_idx >= 0)
+-                      minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
+-                              txrc, false, false);
++                      ar[1] = mi->tx_rates[0];
+               else
+-                      minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
+-                              txrc, false, true);
+-
+-              minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
+-                                   txrc, false, !sample);
++                      ar[1] = mi->tx_rates[1];
+-              ar[3].count = 0;
+-              ar[3].idx = -1;
++              ar[2] = mi->tx_rates[2];
++              last = 3;
+       } else if (mp->hw->max_rates == 2) {
+               /*
+                * Only 2 tx rates supported, use
+                * sample_rate -> max_prob_rate for sampling and
+                * max_tp_rate -> max_prob_rate by default.
+                */
+-              minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
+-                                   txrc, false, !sample);
+-
+-              ar[2].count = 0;
+-              ar[2].idx = -1;
++              ar[1] = mi->tx_rates[2];
++              last = 2;
+       } else {
+               /* Not using MRR, only use the first rate */
+-              ar[1].count = 0;
+-              ar[1].idx = -1;
++              last = 1;
++
+       }
++      ar[last].count = 0;
++      ar[last].idx = -1;
+       mi->total_packets++;
+@@ -766,6 +776,7 @@ minstrel_ht_update_caps(void *priv, stru
+       if (!n_supported)
+               goto use_legacy;
++      minstrel_ht_update_rates(mp, mi);
+       return;
+ use_legacy:
diff --git a/package/mac80211/patches/561-mac80211_tx_status.patch b/package/mac80211/patches/561-mac80211_tx_status.patch
new file mode 100644 (file)
index 0000000..513dd0a
--- /dev/null
@@ -0,0 +1,96 @@
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -2370,6 +2370,25 @@ static inline int ieee80211_sta_ps_trans
+ void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
+ /**
++ * ieee80211_tx_status_sta - transmit status callback
++ *
++ * Call this function for all transmitted frames after they have been
++ * transmitted. It is permissible to not call this function for
++ * multicast frames but this can affect statistics.
++ *
++ * This function may not be called in IRQ context. Calls to this function
++ * for a single hardware must be synchronized against each other. Calls
++ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
++ * may not be mixed for a single hardware.
++ *
++ * @hw: the hardware the frame was transmitted by
++ * @skb: the frame that was transmitted, owned by mac80211 after this call
++ * @sta: station for which the tx status is provided
++ */
++void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
++                           struct ieee80211_sta *sta);
++
++/**
+  * ieee80211_tx_status - transmit status callback
+  *
+  * Call this function for all transmitted frames after they have been
+@@ -2384,8 +2403,11 @@ void ieee80211_sta_set_tim(struct ieee80
+  * @hw: the hardware the frame was transmitted by
+  * @skb: the frame that was transmitted, owned by mac80211 after this call
+  */
+-void ieee80211_tx_status(struct ieee80211_hw *hw,
+-                       struct sk_buff *skb);
++static inline void ieee80211_tx_status(struct ieee80211_hw *hw,
++                                     struct sk_buff *skb)
++{
++      ieee80211_tx_status_sta(hw, skb, NULL);
++}
+ /**
+  * ieee80211_tx_status_ni - transmit status callback (in process context)
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -202,7 +202,8 @@ static void ieee80211_set_bar_pending(st
+  */
+ #define STA_LOST_PKT_THRESHOLD        50
+-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
++void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
++                           struct ieee80211_sta *pubsta)
+ {
+       struct sk_buff *skb2;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+@@ -214,7 +215,7 @@ void ieee80211_tx_status(struct ieee8021
+       struct ieee80211_tx_status_rtap_hdr *rthdr;
+       struct ieee80211_sub_if_data *sdata;
+       struct net_device *prev_dev = NULL;
+-      struct sta_info *sta, *tmp;
++      struct sta_info *sta = NULL, *tmp, *tmp2;
+       int retry_count = -1, i;
+       int rates_idx = -1;
+       bool send_to_cooked;
+@@ -244,11 +245,19 @@ void ieee80211_tx_status(struct ieee8021
+       sband = local->hw.wiphy->bands[info->band];
+       fc = hdr->frame_control;
+-      for_each_sta_info(local, hdr->addr1, sta, tmp) {
+-              /* skip wrong virtual interface */
+-              if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
+-                      continue;
++      if (!pubsta) {
++              for_each_sta_info(local, hdr->addr1, tmp, tmp2) {
++                      /* skip wrong virtual interface */
++                      if (memcmp(hdr->addr2, tmp->sdata->vif.addr, ETH_ALEN))
++                              continue;
++
++                      sta = tmp;
++              }
++      } else {
++              sta = container_of(pubsta, struct sta_info, sta);
++      }
++      if (sta) {
+               acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
+               if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) {
+                       /*
+@@ -497,7 +506,7 @@ void ieee80211_tx_status(struct ieee8021
+       rcu_read_unlock();
+       dev_kfree_skb(skb);
+ }
+-EXPORT_SYMBOL(ieee80211_tx_status);
++EXPORT_SYMBOL(ieee80211_tx_status_sta);
+ void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
+ {
diff --git a/package/mac80211/patches/562-ath9k_tx_status.patch b/package/mac80211/patches/562-ath9k_tx_status.patch
new file mode 100644 (file)
index 0000000..dfe536c
--- /dev/null
@@ -0,0 +1,121 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -50,10 +50,12 @@ static u16 bits_per_symbol[][2] = {
+ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+                              struct ath_atx_tid *tid, struct sk_buff *skb);
+ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+-                          int tx_flags, struct ath_txq *txq);
++                          int tx_flags, struct ath_txq *txq,
++                          struct ieee80211_sta *sta);
+ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+                               struct ath_txq *txq, struct list_head *bf_q,
+-                              struct ath_tx_status *ts, int txok, int sendbar);
++                              struct ath_tx_status *ts, int txok, int sendbar,
++                              struct ieee80211_sta *sta);
+ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+                            struct list_head *head, bool internal);
+ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+@@ -172,7 +174,8 @@ static void ath_tx_flush_tid(struct ath_
+               if (bf && fi->retries) {
+                       list_add_tail(&bf->list, &bf_head);
+                       ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
+-                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
++                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0,
++                              1, NULL);
+               } else {
+                       ath_tx_send_normal(sc, txq, NULL, skb);
+               }
+@@ -239,7 +242,7 @@ static void ath_tid_drain(struct ath_sof
+               if (!bf) {
+                       spin_unlock(&txq->axq_lock);
+-                      ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
++                      ath_tx_complete(sc, skb, ATH_TX_ERROR, txq, NULL);
+                       spin_lock(&txq->axq_lock);
+                       continue;
+               }
+@@ -250,7 +253,7 @@ static void ath_tid_drain(struct ath_sof
+                       ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
+               spin_unlock(&txq->axq_lock);
+-              ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
++              ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0, NULL);
+               spin_lock(&txq->axq_lock);
+       }
+@@ -412,7 +415,7 @@ static void ath_tx_complete_aggr(struct 
+                               list_move_tail(&bf->list, &bf_head);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+-                              0, 0);
++                              0, 0, NULL);
+                       bf = bf_next;
+               }
+@@ -520,7 +523,7 @@ static void ath_tx_complete_aggr(struct 
+                       }
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+-                              !txfail, sendbar);
++                              !txfail, sendbar, sta);
+               } else {
+                       /* retry the un-acked ones */
+                       if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
+@@ -540,7 +543,8 @@ static void ath_tx_complete_aggr(struct 
+                                               ath_tx_complete_buf(sc, bf, txq,
+                                                                   &bf_head,
+-                                                                  ts, 0, 1);
++                                                                  ts, 0, 1,
++                                                                  sta);
+                                               break;
+                                       }
+@@ -1465,7 +1469,8 @@ static void ath_drain_txq_list(struct at
+                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
+                                            retry_tx);
+               else
+-                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
++                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0,
++                              NULL);
+               spin_lock_bh(&txq->axq_lock);
+       }
+ }
+@@ -1970,7 +1975,8 @@ int ath_tx_start(struct ieee80211_hw *hw
+ /*****************/
+ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+-                          int tx_flags, struct ath_txq *txq)
++                          int tx_flags, struct ath_txq *txq,
++                          struct ieee80211_sta *sta)
+ {
+       struct ieee80211_hw *hw = sc->hw;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+@@ -2028,7 +2034,8 @@ static void ath_tx_complete(struct ath_s
+ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+                               struct ath_txq *txq, struct list_head *bf_q,
+-                              struct ath_tx_status *ts, int txok, int sendbar)
++                              struct ath_tx_status *ts, int txok, int sendbar,
++                              struct ieee80211_sta *sta)
+ {
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+@@ -2056,7 +2063,7 @@ static void ath_tx_complete_buf(struct a
+                       complete(&sc->paprd_complete);
+       } else {
+               ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
+-              ath_tx_complete(sc, skb, tx_flags, txq);
++              ath_tx_complete(sc, skb, tx_flags, txq, sta);
+       }
+       /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
+        * accidentally reference it later.
+@@ -2145,7 +2152,7 @@ static void ath_tx_process_buffer(struct
+       if (!bf_isampdu(bf)) {
+               ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
+-              ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
++              ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0, NULL);
+       } else
+               ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
diff --git a/package/mac80211/patches/570-ath9k_fix_ack_cts_timeout.patch b/package/mac80211/patches/570-ath9k_fix_ack_cts_timeout.patch
deleted file mode 100644 (file)
index ed955b4..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -969,7 +969,7 @@ void ath9k_hw_init_global_settings(struc
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ieee80211_conf *conf = &common->hw->conf;
-       const struct ath9k_channel *chan = ah->curchan;
--      int acktimeout;
-+      int acktimeout, ctstimeout;
-       int slottime;
-       int sifstime;
-       int rx_lat = 0, tx_lat = 0, eifs = 0;
-@@ -1029,6 +1029,7 @@ void ath9k_hw_init_global_settings(struc
-       /* As defined by IEEE 802.11-2007 17.3.8.6 */
-       acktimeout = slottime + sifstime + 3 * ah->coverage_class;
-+      ctstimeout = acktimeout;
-       /*
-        * Workaround for early ACK timeouts, add an offset to match the
-@@ -1043,7 +1044,7 @@ void ath9k_hw_init_global_settings(struc
-       ath9k_hw_set_sifs_time(ah, sifstime);
-       ath9k_hw_setslottime(ah, slottime);
-       ath9k_hw_set_ack_timeout(ah, acktimeout);
--      ath9k_hw_set_cts_timeout(ah, acktimeout);
-+      ath9k_hw_set_cts_timeout(ah, ctstimeout);
-       if (ah->globaltxtimeout != (u32) -1)
-               ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
diff --git a/package/mac80211/patches/570-ath9k_tx_stop_failure_debug.patch b/package/mac80211/patches/570-ath9k_tx_stop_failure_debug.patch
new file mode 100644 (file)
index 0000000..9a57c05
--- /dev/null
@@ -0,0 +1,27 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1512,7 +1512,8 @@ bool ath_drain_all_txq(struct ath_softc 
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_txq *txq;
+-      int i, npend = 0;
++      int i;
++      u32 npend = 0;
+       if (sc->sc_flags & SC_OP_INVALID)
+               return true;
+@@ -1524,11 +1525,12 @@ bool ath_drain_all_txq(struct ath_softc 
+               if (!ATH_TXQ_SETUP(sc, i))
+                       continue;
+-              npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
++              if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
++                      npend |= BIT(i);
+       }
+       if (npend)
+-              ath_err(common, "Failed to stop TX DMA!\n");
++              ath_err(common, "Failed to stop TX DMA, queues=%08x!\n", npend);
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (!ATH_TXQ_SETUP(sc, i))
diff --git a/package/mac80211/patches/571-ath9k_reset_debug.patch b/package/mac80211/patches/571-ath9k_reset_debug.patch
new file mode 100644 (file)
index 0000000..90e62c2
--- /dev/null
@@ -0,0 +1,124 @@
+--- a/drivers/net/wireless/ath/ath9k/debug.h
++++ b/drivers/net/wireless/ath/ath9k/debug.h
+@@ -25,8 +25,10 @@ struct ath_buf;
+ #ifdef CONFIG_ATH9K_DEBUGFS
+ #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
++#define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++
+ #else
+ #define TX_STAT_INC(q, c) do { } while (0)
++#define RESET_STAT_INC(sc, type) do { } while (0)
+ #endif
+ #ifdef CONFIG_ATH9K_DEBUGFS
+@@ -171,10 +173,21 @@ struct ath_rx_stats {
+       u8 rs_antenna;
+ };
++enum ath_reset_type {
++      RESET_TYPE_BB_HANG,
++      RESET_TYPE_BB_WATCHDOG,
++      RESET_TYPE_FATAL_INT,
++      RESET_TYPE_TX_ERROR,
++      RESET_TYPE_TX_HANG,
++      RESET_TYPE_PLL_HANG,
++      __RESET_TYPE_MAX
++};
++
+ struct ath_stats {
+       struct ath_interrupt_stats istats;
+       struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
+       struct ath_rx_stats rxstats;
++      u32 reset[__RESET_TYPE_MAX];
+ };
+ #define ATH_DBG_MAX_SAMPLES   10
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -679,6 +679,16 @@ void ath9k_tasklet(unsigned long data)
+       if ((status & ATH9K_INT_FATAL) ||
+           (status & ATH9K_INT_BB_WATCHDOG)) {
++#ifdef CONFIG_ATH9K_DEBUGFS
++              enum ath_reset_type type;
++
++              if (status & ATH9K_INT_FATAL)
++                      type = RESET_TYPE_FATAL_INT;
++              else
++                      type = RESET_TYPE_BB_WATCHDOG;
++
++              RESET_STAT_INC(sc, type);
++#endif
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+               goto out;
+       }
+@@ -995,8 +1005,10 @@ void ath_hw_check(struct work_struct *wo
+       ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
+               "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
+       if (busy >= 99) {
+-              if (++sc->hw_busy_count >= 3)
++              if (++sc->hw_busy_count >= 3) {
++                      RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++              }
+       } else if (busy >= 0)
+               sc->hw_busy_count = 0;
+@@ -1016,6 +1028,7 @@ static void ath_hw_pll_rx_hang_check(str
+                       /* Rx is hung for more than 500ms. Reset it */
+                       ath_dbg(common, ATH_DBG_RESET,
+                               "Possible RX hang, resetting");
++                      RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+                       count = 0;
+               }
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -587,8 +587,10 @@ static void ath_tx_complete_aggr(struct 
+       rcu_read_unlock();
+-      if (needreset)
++      if (needreset) {
++              RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++      }
+ }
+ static bool ath_lookup_legacy(struct ath_buf *bf)
+@@ -2270,6 +2272,7 @@ static void ath_tx_complete_poll_work(st
+       if (needreset) {
+               ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
+                       "tx hung, resetting the chip\n");
++              RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+       }
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -523,9 +523,22 @@ static ssize_t read_file_wiphy(struct fi
+       if (tmp & ATH9K_RX_FILTER_PHYRADAR)
+               len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
+       if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
+-              len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n");
+-      else
+-              len += snprintf(buf + len, sizeof(buf) - len, "\n");
++              len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
++
++      len += snprintf(buf + len, sizeof(buf) - len,
++                     "\n\nReset causes:\n"
++                     "  baseband hang: %d\n"
++                     "  baseband watchdog: %d\n"
++                     "  fatal hardware error interrupt: %d\n"
++                     "  tx hardware error: %d\n"
++                     "  tx path hang: %d\n"
++                     "  pll rx hang: %d\n",
++                     sc->debug.stats.reset[RESET_TYPE_BB_HANG],
++                     sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG],
++                     sc->debug.stats.reset[RESET_TYPE_FATAL_INT],
++                     sc->debug.stats.reset[RESET_TYPE_TX_ERROR],
++                     sc->debug.stats.reset[RESET_TYPE_TX_HANG],
++                     sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
+       if (len > sizeof(buf))
+               len = sizeof(buf);
diff --git a/package/mac80211/patches/572-ath9k_fix_tx_retry.patch b/package/mac80211/patches/572-ath9k_fix_tx_retry.patch
new file mode 100644 (file)
index 0000000..dfb09ba
--- /dev/null
@@ -0,0 +1,41 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -387,7 +387,6 @@ static void ath_tx_complete_aggr(struct 
+       struct ath_frame_info *fi;
+       int nframes;
+       u8 tidno;
+-      bool clear_filter;
+       int i, retries;
+       skb = bf->bf_mpdu;
+@@ -484,12 +483,10 @@ static void ath_tx_complete_aggr(struct 
+                                */
+                               txfail = 1;
+                       } else if (fi->retries < ATH_MAX_SW_RETRIES) {
+-                              if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
+-                                  !an->sleeping)
++                              if (txok || !an->sleeping)
+                                       ath_tx_set_retry(sc, txq, bf->bf_mpdu,
+                                                        retries);
+-                              clear_filter = true;
+                               txpending = 1;
+                       } else {
+                               txfail = 1;
+@@ -568,11 +565,13 @@ static void ath_tx_complete_aggr(struct 
+                       ieee80211_sta_set_tim(sta);
+               spin_lock_bh(&txq->axq_lock);
+-              if (clear_filter)
+-                      tid->ac->clear_ps_filter = true;
+               skb_queue_splice(&bf_pending, &tid->buf_q);
+-              if (!an->sleeping)
++              if (!an->sleeping) {
+                       ath_tx_queue_tid(txq, tid);
++
++                      if (ts->ts_status & ATH9K_TXERR_FILT)
++                              tid->ac->clear_ps_filter = true;
++              }
+               spin_unlock_bh(&txq->axq_lock);
+       }
diff --git a/package/mac80211/patches/573-ath9k_fix_tx_flush_bar.patch b/package/mac80211/patches/573-ath9k_fix_tx_flush_bar.patch
new file mode 100644 (file)
index 0000000..a87151b
--- /dev/null
@@ -0,0 +1,51 @@
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -75,9 +75,10 @@
+ #define ATH9K_TXERR_XTXOP          0x08
+ #define ATH9K_TXERR_TIMER_EXPIRED  0x10
+ #define ATH9K_TX_ACKED                   0x20
++#define ATH9K_TX_FLUSH                   0x40
+ #define ATH9K_TXERR_MASK                                              \
+       (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO |     \
+-       ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED)
++       ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED | ATH9K_TX_FLUSH)
+ #define ATH9K_TX_BA                0x01
+ #define ATH9K_TX_PWRMGMT           0x02
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -388,6 +388,7 @@ static void ath_tx_complete_aggr(struct 
+       int nframes;
+       u8 tidno;
+       int i, retries;
++      bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
+       skb = bf->bf_mpdu;
+       hdr = (struct ieee80211_hdr *)skb->data;
+@@ -482,6 +483,8 @@ static void ath_tx_complete_aggr(struct 
+                                * the un-acked sub-frames
+                                */
+                               txfail = 1;
++                      } else if (flush) {
++                              txpending = 1;
+                       } else if (fi->retries < ATH_MAX_SW_RETRIES) {
+                               if (txok || !an->sleeping)
+                                       ath_tx_set_retry(sc, txq, bf->bf_mpdu,
+@@ -540,7 +543,8 @@ static void ath_tx_complete_aggr(struct 
+                                               ath_tx_complete_buf(sc, bf, txq,
+                                                                   &bf_head,
+-                                                                  ts, 0, 1,
++                                                                  ts, 0,
++                                                                  !flush,
+                                                                   sta);
+                                               break;
+                                       }
+@@ -1446,6 +1450,7 @@ static void ath_drain_txq_list(struct at
+       struct ath_tx_status ts;
+       memset(&ts, 0, sizeof(ts));
++      ts.ts_status = ATH9K_TX_FLUSH;
+       INIT_LIST_HEAD(&bf_head);
+       while (!list_empty(list)) {
diff --git a/package/mac80211/patches/580-ath9k_cleanup_set_interrupt.patch b/package/mac80211/patches/580-ath9k_cleanup_set_interrupt.patch
new file mode 100644 (file)
index 0000000..a93857a
--- /dev/null
@@ -0,0 +1,155 @@
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -515,7 +515,7 @@ static void ath_beacon_config_ap(struct 
+       sc->sc_flags |= SC_OP_TSF_RESET;
+       ath9k_beacon_init(sc, nexttbtt, intval);
+       sc->beacon.bmisscnt = 0;
+-      ath9k_hw_set_interrupts(ah, ah->imask);
++      ath9k_hw_set_interrupts(ah);
+       ath9k_hw_enable_interrupts(ah);
+ }
+@@ -643,7 +643,7 @@ static void ath_beacon_config_sta(struct
+       ath9k_hw_set_sta_beacon_timers(ah, &bs);
+       ah->imask |= ATH9K_INT_BMISS;
+-      ath9k_hw_set_interrupts(ah, ah->imask);
++      ath9k_hw_set_interrupts(ah);
+       ath9k_hw_enable_interrupts(ah);
+ }
+@@ -679,7 +679,7 @@ static void ath_beacon_config_adhoc(stru
+       ath9k_beacon_init(sc, nexttbtt, intval);
+       sc->beacon.bmisscnt = 0;
+-      ath9k_hw_set_interrupts(ah, ah->imask);
++      ath9k_hw_set_interrupts(ah);
+       ath9k_hw_enable_interrupts(ah);
+ }
+@@ -821,11 +821,11 @@ void ath9k_set_beaconing_status(struct a
+       if (status) {
+               /* Re-enable beaconing */
+               ah->imask |= ATH9K_INT_SWBA;
+-              ath9k_hw_set_interrupts(ah, ah->imask);
++              ath9k_hw_set_interrupts(ah);
+       } else {
+               /* Disable SWBA interrupt */
+               ah->imask &= ~ATH9K_INT_SWBA;
+-              ath9k_hw_set_interrupts(ah, ah->imask);
++              ath9k_hw_set_interrupts(ah);
+               tasklet_kill(&sc->bcon_tasklet);
+               ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
+       }
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -151,7 +151,7 @@ static void ath9k_gen_timer_start(struct
+       if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
+               ath9k_hw_disable_interrupts(ah);
+               ah->imask |= ATH9K_INT_GENTIMER;
+-              ath9k_hw_set_interrupts(ah, ah->imask);
++              ath9k_hw_set_interrupts(ah);
+               ath9k_hw_enable_interrupts(ah);
+       }
+ }
+@@ -166,7 +166,7 @@ static void ath9k_gen_timer_stop(struct 
+       if (timer_table->timer_mask.val == 0) {
+               ath9k_hw_disable_interrupts(ah);
+               ah->imask &= ~ATH9K_INT_GENTIMER;
+-              ath9k_hw_set_interrupts(ah, ah->imask);
++              ath9k_hw_set_interrupts(ah);
+               ath9k_hw_enable_interrupts(ah);
+       }
+ }
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -273,7 +273,7 @@ static bool ath_complete_reset(struct at
+       ath9k_cmn_update_txpow(ah, sc->curtxpow,
+                              sc->config.txpowlimit, &sc->curtxpow);
+-      ath9k_hw_set_interrupts(ah, ah->imask);
++      ath9k_hw_set_interrupts(ah);
+       ath9k_hw_enable_interrupts(ah);
+       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
+@@ -833,7 +833,7 @@ irqreturn_t ath_isr(int irq, void *dev)
+       if (status & ATH9K_INT_RXEOL) {
+               ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+-              ath9k_hw_set_interrupts(ah, ah->imask);
++              ath9k_hw_set_interrupts(ah);
+       }
+       if (status & ATH9K_INT_MIB) {
+@@ -1409,7 +1409,7 @@ static void ath9k_calculate_summary_stat
+               ah->imask &= ~ATH9K_INT_TSFOOR;
+       }
+-      ath9k_hw_set_interrupts(ah, ah->imask);
++      ath9k_hw_set_interrupts(ah);
+       /* Set up ANI */
+       if (iter_data.naps > 0) {
+@@ -1566,7 +1566,7 @@ static void ath9k_enable_ps(struct ath_s
+       if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+               if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) {
+                       ah->imask |= ATH9K_INT_TIM_TIMER;
+-                      ath9k_hw_set_interrupts(ah, ah->imask);
++                      ath9k_hw_set_interrupts(ah);
+               }
+               ath9k_hw_setrxabort(ah, 1);
+       }
+@@ -1586,7 +1586,7 @@ static void ath9k_disable_ps(struct ath_
+                                 PS_WAIT_FOR_TX_ACK);
+               if (ah->imask & ATH9K_INT_TIM_TIMER) {
+                       ah->imask &= ~ATH9K_INT_TIM_TIMER;
+-                      ath9k_hw_set_interrupts(ah, ah->imask);
++                      ath9k_hw_set_interrupts(ah);
+               }
+       }
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -1974,7 +1974,7 @@ requeue:
+       if (!(ah->imask & ATH9K_INT_RXEOL)) {
+               ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+-              ath9k_hw_set_interrupts(ah, ah->imask);
++              ath9k_hw_set_interrupts(ah);
+       }
+       return 0;
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -827,9 +827,9 @@ void ath9k_hw_enable_interrupts(struct a
+ }
+ EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
+-void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
++void ath9k_hw_set_interrupts(struct ath_hw *ah)
+ {
+-      enum ath9k_int omask = ah->imask;
++      enum ath9k_int ints = ah->imask;
+       u32 mask, mask2;
+       struct ath9k_hw_capabilities *pCap = &ah->caps;
+       struct ath_common *common = ath9k_hw_common(ah);
+@@ -837,7 +837,7 @@ void ath9k_hw_set_interrupts(struct ath_
+       if (!(ints & ATH9K_INT_GLOBAL))
+               ath9k_hw_disable_interrupts(ah);
+-      ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
++      ath_dbg(common, ATH_DBG_INTERRUPT, "New interrupt mask 0x%x\n", ints);
+       mask = ints & ATH9K_INT_COMMON;
+       mask2 = 0;
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -735,7 +735,7 @@ int ath9k_hw_beaconq_setup(struct ath_hw
+ /* Interrupt Handling */
+ bool ath9k_hw_intrpend(struct ath_hw *ah);
+-void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
++void ath9k_hw_set_interrupts(struct ath_hw *ah);
+ void ath9k_hw_enable_interrupts(struct ath_hw *ah);
+ void ath9k_hw_disable_interrupts(struct ath_hw *ah);
diff --git a/package/mac80211/patches/580-ath9k_remove_common_chainmask.patch b/package/mac80211/patches/580-ath9k_remove_common_chainmask.patch
deleted file mode 100644 (file)
index 58d972c..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
---- a/drivers/net/wireless/ath/ath.h
-+++ b/drivers/net/wireless/ath/ath.h
-@@ -140,9 +140,6 @@ struct ath_common {
-       u8 curbssid[ETH_ALEN];
-       u8 bssidmask[ETH_ALEN];
--      u8 tx_chainmask;
--      u8 rx_chainmask;
--
-       u32 rx_bufsize;
-       u32 keymax;
---- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-@@ -113,7 +113,7 @@ static int ar9003_get_training_power_5g(
-       if (delta > scale)
-               return -1;
--      switch (get_streams(common->tx_chainmask)) {
-+      switch (get_streams(ah->txchainmask)) {
-       case 1:
-               delta = 6;
-               break;
-@@ -126,7 +126,7 @@ static int ar9003_get_training_power_5g(
-       default:
-               delta = 0;
-               ath_dbg(common, ATH_DBG_CALIBRATE,
--              "Invalid tx-chainmask: %u\n", common->tx_chainmask);
-+              "Invalid tx-chainmask: %u\n", ah->txchainmask);
-       }
-       power += delta;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -318,7 +318,6 @@ static void ath_paprd_activate(struct at
- {
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath9k_hw_cal_data *caldata = ah->caldata;
--      struct ath_common *common = ath9k_hw_common(ah);
-       int chain;
-       if (!caldata || !caldata->paprd_done)
-@@ -327,7 +326,7 @@ static void ath_paprd_activate(struct at
-       ath9k_ps_wakeup(sc);
-       ar9003_paprd_enable(ah, false);
-       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
--              if (!(common->tx_chainmask & BIT(chain)))
-+              if (!(ah->txchainmask & BIT(chain)))
-                       continue;
-               ar9003_paprd_populate_single_table(ah, caldata, chain);
-@@ -414,7 +413,7 @@ void ath_paprd_calibrate(struct work_str
-       memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
-       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
--              if (!(common->tx_chainmask & BIT(chain)))
-+              if (!(ah->txchainmask & BIT(chain)))
-                       continue;
-               chain_ok = 0;
-@@ -535,7 +534,7 @@ void ath_ani_calibrate(unsigned long dat
-       if (longcal || shortcal) {
-               common->ani.caldone =
-                       ath9k_hw_calibrate(ah, ah->curchan,
--                                              common->rx_chainmask, longcal);
-+                                              ah->rxchainmask, longcal);
-       }
-       ath9k_ps_restore(sc);
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1488,9 +1488,6 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-       u64 tsf = 0;
-       int i, r;
--      ah->txchainmask = common->tx_chainmask;
--      ah->rxchainmask = common->rx_chainmask;
--
-       if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
-               return -EIO;
-@@ -2108,6 +2105,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw
-       pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
-       pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
-+      ah->txchainmask = pCap->tx_chainmask;
-+      ah->rxchainmask = pCap->rx_chainmask;
-       ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -1660,7 +1660,7 @@ u8 ath_txchainmask_reduction(struct ath_
- static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
- {
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+      struct ath_hw *ah = sc->sc_ah;
-       struct ath9k_11n_rate_series series[4];
-       struct sk_buff *skb;
-       struct ieee80211_tx_info *tx_info;
-@@ -1720,7 +1720,7 @@ static void ath_buf_set_rate(struct ath_
-                       /* MCS rates */
-                       series[i].Rate = rix | 0x80;
-                       series[i].ChSel = ath_txchainmask_reduction(sc,
--                                      common->tx_chainmask, series[i].Rate);
-+                                      ah->txchainmask, series[i].Rate);
-                       series[i].PktDuration = ath_pkt_duration(sc, rix, len,
-                                is_40, is_sgi, is_sp);
-                       if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
-@@ -1745,10 +1745,10 @@ static void ath_buf_set_rate(struct ath_
-               }
-               if (bf->bf_state.bfs_paprd)
--                      series[i].ChSel = common->tx_chainmask;
-+                      series[i].ChSel = ah->txchainmask;
-               else
-                       series[i].ChSel = ath_txchainmask_reduction(sc,
--                                      common->tx_chainmask, series[i].Rate);
-+                                      ah->txchainmask, series[i].Rate);
-               series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
-                       phy, rate->bitrate * 100, len, rix, is_sp);
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -107,7 +107,7 @@ static void ath_beacon_setup(struct ath_
-       series[0].Tries = 1;
-       series[0].Rate = rate;
-       series[0].ChSel = ath_txchainmask_reduction(sc,
--                      common->tx_chainmask, series[0].Rate);
-+                      ah->txchainmask, series[0].Rate);
-       series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
-       ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
-                                    series, 4, 0);
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -95,11 +95,11 @@ static ssize_t read_file_tx_chainmask(st
-                            size_t count, loff_t *ppos)
- {
-       struct ath_softc *sc = file->private_data;
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+      struct ath_hw *ah = sc->sc_ah;
-       char buf[32];
-       unsigned int len;
--      len = sprintf(buf, "0x%08x\n", common->tx_chainmask);
-+      len = sprintf(buf, "0x%08x\n", ah->txchainmask);
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
- }
-@@ -107,7 +107,7 @@ static ssize_t write_file_tx_chainmask(s
-                            size_t count, loff_t *ppos)
- {
-       struct ath_softc *sc = file->private_data;
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+      struct ath_hw *ah = sc->sc_ah;
-       unsigned long mask;
-       char buf[32];
-       ssize_t len;
-@@ -120,8 +120,8 @@ static ssize_t write_file_tx_chainmask(s
-       if (strict_strtoul(buf, 0, &mask))
-               return -EINVAL;
--      common->tx_chainmask = mask;
--      sc->sc_ah->caps.tx_chainmask = mask;
-+      ah->txchainmask = mask;
-+      ah->caps.tx_chainmask = mask;
-       return count;
- }
-@@ -138,11 +138,11 @@ static ssize_t read_file_rx_chainmask(st
-                            size_t count, loff_t *ppos)
- {
-       struct ath_softc *sc = file->private_data;
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+      struct ath_hw *ah = sc->sc_ah;
-       char buf[32];
-       unsigned int len;
--      len = sprintf(buf, "0x%08x\n", common->rx_chainmask);
-+      len = sprintf(buf, "0x%08x\n", ah->rxchainmask);
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
- }
-@@ -150,7 +150,7 @@ static ssize_t write_file_rx_chainmask(s
-                            size_t count, loff_t *ppos)
- {
-       struct ath_softc *sc = file->private_data;
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+      struct ath_hw *ah = sc->sc_ah;
-       unsigned long mask;
-       char buf[32];
-       ssize_t len;
-@@ -163,8 +163,8 @@ static ssize_t write_file_rx_chainmask(s
-       if (strict_strtoul(buf, 0, &mask))
-               return -EINVAL;
--      common->rx_chainmask = mask;
--      sc->sc_ah->caps.rx_chainmask = mask;
-+      ah->rxchainmask = mask;
-+      ah->caps.rx_chainmask = mask;
-       return count;
- }
---- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
-+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
-@@ -509,8 +509,8 @@ static void setup_ht_cap(struct ath9k_ht
-       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
-       /* ath9k_htc supports only 1 or 2 stream devices */
--      tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
--      rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
-+      tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
-+      rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "TX streams %d, RX streams: %d\n",
-@@ -601,9 +601,6 @@ static void ath9k_init_misc(struct ath9k
- {
-       struct ath_common *common = ath9k_hw_common(priv->ah);
--      common->tx_chainmask = priv->ah->caps.tx_chainmask;
--      common->rx_chainmask = priv->ah->caps.rx_chainmask;
--
-       memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
-       priv->ah->opmode = NL80211_IFTYPE_STATION;
---- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
-+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
-@@ -826,8 +826,7 @@ void ath9k_htc_ani_work(struct work_stru
-               if (longcal || shortcal)
-                       common->ani.caldone =
-                               ath9k_hw_calibrate(ah, ah->curchan,
--                                                 common->rx_chainmask,
--                                                 longcal);
-+                                                 ah->rxchainmask, longcal);
-               ath9k_htc_ps_restore(priv);
-       }
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -270,8 +270,8 @@ static void setup_ht_cap(struct ath_soft
-       /* set up supported mcs set */
-       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
--      tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
--      rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
-+      tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams);
-+      rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "TX streams %d, RX streams: %d\n",
-@@ -506,9 +506,6 @@ static void ath9k_init_misc(struct ath_s
-               sc->sc_flags |= SC_OP_RXAGGR;
-       }
--      common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
--      common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
--
-       ath9k_hw_set_diversity(sc->sc_ah, true);
-       sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
-@@ -645,10 +642,8 @@ static void ath9k_init_band_txpower(stru
- static void ath9k_init_txpower_limits(struct ath_softc *sc)
- {
-       struct ath_hw *ah = sc->sc_ah;
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath9k_channel *curchan = ah->curchan;
--      ah->txchainmask = common->tx_chainmask;
-       if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
-               ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
-       if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
diff --git a/package/mac80211/patches/581-ath9k_cleanup_txpower_handling.patch b/package/mac80211/patches/581-ath9k_cleanup_txpower_handling.patch
new file mode 100644 (file)
index 0000000..029ce3d
--- /dev/null
@@ -0,0 +1,627 @@
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -71,7 +71,6 @@ struct ath_regulatory {
+       char alpha2[2];
+       u16 country_code;
+       u16 max_power_level;
+-      u32 tp_scale;
+       u16 current_rd;
+       u16 current_rd_ext;
+       int16_t power_limit;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -3040,6 +3040,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(st
+               return (pBase->miscConfiguration >> 0x3) & 0x1;
+       case EEP_ANT_DIV_CTL1:
+               return eep->base_ext1.ant_div_control;
++      case EEP_ANTENNA_GAIN_5G:
++              return eep->modalHeader5G.antennaGain;
++      case EEP_ANTENNA_GAIN_2G:
++              return eep->modalHeader2G.antennaGain;
+       default:
+               return 0;
+       }
+@@ -4727,20 +4731,14 @@ static u16 ar9003_hw_get_max_edge_power(
+ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
+                                              struct ath9k_channel *chan,
+                                              u8 *pPwrArray, u16 cfgCtl,
+-                                             u8 twiceAntennaReduction,
+-                                             u8 twiceMaxRegulatoryPower,
++                                             u8 antenna_reduction,
+                                              u16 powerLimit)
+ {
+-      struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
+       u16 twiceMaxEdgePower = MAX_RATE_POWER;
+-      static const u16 tpScaleReductionTable[5] = {
+-              0, 3, 6, 9, MAX_RATE_POWER
+-      };
+       int i;
+-      int16_t  twiceLargestAntenna;
+-      u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
++      u16 scaledPower = 0, minCtlPower;
+       static const u16 ctlModesFor11a[] = {
+               CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+       };
+@@ -4758,28 +4756,7 @@ static void ar9003_hw_set_power_per_rate
+       bool is2ghz = IS_CHAN_2GHZ(chan);
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+-
+-      /* Compute TxPower reduction due to Antenna Gain */
+-      if (is2ghz)
+-              twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
+-      else
+-              twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
+-
+-      twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
+-                              twiceLargestAntenna, 0);
+-
+-      /*
+-       * scaledPower is the minimum of the user input power level
+-       * and the regulatory allowed power level
+-       */
+-      maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+-
+-      if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+-              maxRegAllowedPower -=
+-                      (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+-      }
+-
+-      scaledPower = min(powerLimit, maxRegAllowedPower);
++      scaledPower = powerLimit - antenna_reduction;
+       /*
+        * Reduce scaled Power by number of chains active to get
+@@ -4966,7 +4943,6 @@ static inline u8 mcsidx_to_tgtpwridx(uns
+ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
+                                       struct ath9k_channel *chan, u16 cfgCtl,
+                                       u8 twiceAntennaReduction,
+-                                      u8 twiceMaxRegulatoryPower,
+                                       u8 powerLimit, bool test)
+ {
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+@@ -5019,7 +4995,6 @@ static void ath9k_hw_ar9300_set_txpower(
+       ar9003_hw_set_power_per_rate_table(ah, chan,
+                                          targetPowerValT2, cfgCtl,
+                                          twiceAntennaReduction,
+-                                         twiceMaxRegulatoryPower,
+                                          powerLimit);
+       if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -429,7 +429,6 @@ static void ath9k_hw_init_defaults(struc
+       regulatory->country_code = CTRY_DEFAULT;
+       regulatory->power_limit = MAX_RATE_POWER;
+-      regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
+       ah->hw_version.magic = AR5416_MAGIC;
+       ah->hw_version.subvendorid = 0;
+@@ -1396,9 +1395,7 @@ static bool ath9k_hw_chip_reset(struct a
+ static bool ath9k_hw_channel_change(struct ath_hw *ah,
+                                   struct ath9k_channel *chan)
+ {
+-      struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ath_common *common = ath9k_hw_common(ah);
+-      struct ieee80211_channel *channel = chan->chan;
+       u32 qnum;
+       int r;
+@@ -1423,14 +1420,7 @@ static bool ath9k_hw_channel_change(stru
+               return false;
+       }
+       ath9k_hw_set_clockrate(ah);
+-
+-      ah->eep_ops->set_txpower(ah, chan,
+-                           ath9k_regd_get_ctl(regulatory, chan),
+-                           channel->max_antenna_gain * 2,
+-                           channel->max_power * 2,
+-                           min((u32) MAX_RATE_POWER,
+-                           (u32) regulatory->power_limit), false);
+-
++      ath9k_hw_apply_txpower(ah, chan);
+       ath9k_hw_rfbus_done(ah);
+       if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+@@ -2466,23 +2456,56 @@ bool ath9k_hw_disable(struct ath_hw *ah)
+ }
+ EXPORT_SYMBOL(ath9k_hw_disable);
++static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
++{
++      enum eeprom_param gain_param;
++
++      if (IS_CHAN_2GHZ(chan))
++              gain_param = EEP_ANTENNA_GAIN_2G;
++      else
++              gain_param = EEP_ANTENNA_GAIN_5G;
++
++      return ah->eep_ops->get_eeprom(ah, gain_param);
++}
++
++void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
++{
++      struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
++      struct ieee80211_channel *channel;
++      int chan_pwr, new_pwr, max_gain;
++      int ant_gain, ant_reduction = 0;
++
++      if (!chan)
++              return;
++
++      channel = chan->chan;
++      chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
++      new_pwr = min_t(int, chan_pwr, reg->power_limit);
++      max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
++
++      ant_gain = get_antenna_gain(ah, chan);
++      if (ant_gain > max_gain)
++              ant_reduction = ant_gain - max_gain;
++
++      ah->eep_ops->set_txpower(ah, chan,
++                               ath9k_regd_get_ctl(reg, chan),
++                               ant_reduction, new_pwr, false);
++}
++
+ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
+ {
+-      struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
++      struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       struct ieee80211_channel *channel = chan->chan;
+-      int reg_pwr = min_t(int, MAX_RATE_POWER, limit);
+-      int chan_pwr = channel->max_power * 2;
++      reg->power_limit = min_t(int, limit, MAX_RATE_POWER);
+       if (test)
+-              reg_pwr = chan_pwr = MAX_RATE_POWER;
++              channel->max_power = MAX_RATE_POWER / 2;
+-      regulatory->power_limit = reg_pwr;
++      ath9k_hw_apply_txpower(ah, chan);
+-      ah->eep_ops->set_txpower(ah, chan,
+-                               ath9k_regd_get_ctl(regulatory, chan),
+-                               channel->max_antenna_gain * 2,
+-                               chan_pwr, reg_pwr, test);
++      if (test)
++              channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
+ }
+ EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -389,14 +389,6 @@ enum ath9k_power_mode {
+       ATH9K_PM_UNDEFINED
+ };
+-enum ath9k_tp_scale {
+-      ATH9K_TP_SCALE_MAX = 0,
+-      ATH9K_TP_SCALE_50,
+-      ATH9K_TP_SCALE_25,
+-      ATH9K_TP_SCALE_12,
+-      ATH9K_TP_SCALE_MIN
+-};
+-
+ enum ser_reg_mode {
+       SER_REG_MODE_OFF = 0,
+       SER_REG_MODE_ON = 1,
+@@ -964,6 +956,7 @@ void ath9k_hw_htc_resetinit(struct ath_h
+ /* PHY */
+ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+                                  u32 *coef_mantissa, u32 *coef_exponent);
++void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
+ /*
+  * Code Specific to AR5008, AR9001 or AR9002,
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -350,6 +350,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct
+               return pModal->antdiv_ctl1;
+       case EEP_TXGAIN_TYPE:
+               return pBase->txGainType;
++      case EEP_ANTENNA_GAIN_2G:
++              return pModal->antennaGainCh[0];
+       default:
+               return 0;
+       }
+@@ -462,8 +464,7 @@ static void ath9k_hw_set_4k_power_per_ra
+                                                struct ath9k_channel *chan,
+                                                int16_t *ratesArray,
+                                                u16 cfgCtl,
+-                                               u16 AntennaReduction,
+-                                               u16 twiceMaxRegulatoryPower,
++                                               u16 antenna_reduction,
+                                                u16 powerLimit)
+ {
+ #define CMP_TEST_GRP \
+@@ -472,20 +473,16 @@ static void ath9k_hw_set_4k_power_per_ra
+       || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+           ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
+-      struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       int i;
+-      int16_t twiceLargestAntenna;
+       u16 twiceMinEdgePower;
+       u16 twiceMaxEdgePower = MAX_RATE_POWER;
+-      u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
++      u16 scaledPower = 0, minCtlPower;
+       u16 numCtlModes;
+       const u16 *pCtlMode;
+       u16 ctlMode, freq;
+       struct chan_centers centers;
+       struct cal_ctl_data_4k *rep;
+       struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+-      static const u16 tpScaleReductionTable[5] =
+-              { 0, 3, 6, 9, MAX_RATE_POWER };
+       struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+               0, { 0, 0, 0, 0}
+       };
+@@ -503,19 +500,7 @@ static void ath9k_hw_set_4k_power_per_ra
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+-      twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
+-      twiceLargestAntenna = (int16_t)min(AntennaReduction -
+-                                         twiceLargestAntenna, 0);
+-
+-      maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+-      if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+-              maxRegAllowedPower -=
+-                      (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+-      }
+-
+-      scaledPower = min(powerLimit, maxRegAllowedPower);
+-      scaledPower = max((u16)0, scaledPower);
+-
++      scaledPower = powerLimit - antenna_reduction;
+       numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+       pCtlMode = ctlModesFor11g;
+@@ -671,7 +656,6 @@ static void ath9k_hw_4k_set_txpower(stru
+                                   struct ath9k_channel *chan,
+                                   u16 cfgCtl,
+                                   u8 twiceAntennaReduction,
+-                                  u8 twiceMaxRegulatoryPower,
+                                   u8 powerLimit, bool test)
+ {
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+@@ -691,7 +675,6 @@ static void ath9k_hw_4k_set_txpower(stru
+       ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+                                            &ratesArray[0], cfgCtl,
+                                            twiceAntennaReduction,
+-                                           twiceMaxRegulatoryPower,
+                                            powerLimit);
+       ath9k_hw_set_4k_power_cal_table(ah, chan);
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -336,6 +336,9 @@ static u32 ath9k_hw_ar9287_get_eeprom(st
+                       return pBase->tempSensSlopePalOn;
+               else
+                       return 0;
++      case EEP_ANTENNA_GAIN_2G:
++              return max_t(u8, pModal->antennaGainCh[0],
++                               pModal->antennaGainCh[1]);
+       default:
+               return 0;
+       }
+@@ -554,8 +557,7 @@ static void ath9k_hw_set_ar9287_power_pe
+                                                    struct ath9k_channel *chan,
+                                                    int16_t *ratesArray,
+                                                    u16 cfgCtl,
+-                                                   u16 AntennaReduction,
+-                                                   u16 twiceMaxRegulatoryPower,
++                                                   u16 antenna_reduction,
+                                                    u16 powerLimit)
+ {
+ #define CMP_CTL \
+@@ -569,12 +571,8 @@ static void ath9k_hw_set_ar9287_power_pe
+ #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6
+ #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10
+-      struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       u16 twiceMaxEdgePower = MAX_RATE_POWER;
+-      static const u16 tpScaleReductionTable[5] =
+-              { 0, 3, 6, 9, MAX_RATE_POWER };
+       int i;
+-      int16_t twiceLargestAntenna;
+       struct cal_ctl_data_ar9287 *rep;
+       struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
+                                   targetPowerCck = {0, {0, 0, 0, 0} };
+@@ -582,7 +580,7 @@ static void ath9k_hw_set_ar9287_power_pe
+                                   targetPowerCckExt = {0, {0, 0, 0, 0} };
+       struct cal_target_power_ht targetPowerHt20,
+                                   targetPowerHt40 = {0, {0, 0, 0, 0} };
+-      u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
++      u16 scaledPower = 0, minCtlPower;
+       static const u16 ctlModesFor11g[] = {
+               CTL_11B, CTL_11G, CTL_2GHT20,
+               CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+@@ -597,24 +595,7 @@ static void ath9k_hw_set_ar9287_power_pe
+       tx_chainmask = ah->txchainmask;
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+-
+-      /* Compute TxPower reduction due to Antenna Gain */
+-      twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
+-                                pEepData->modalHeader.antennaGainCh[1]);
+-      twiceLargestAntenna = (int16_t)min((AntennaReduction) -
+-                                         twiceLargestAntenna, 0);
+-
+-      /*
+-       * scaledPower is the minimum of the user input power level
+-       * and the regulatory allowed power level.
+-       */
+-      maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+-
+-      if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
+-              maxRegAllowedPower -=
+-                      (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+-
+-      scaledPower = min(powerLimit, maxRegAllowedPower);
++      scaledPower = powerLimit - antenna_reduction;
+       /*
+        * Reduce scaled Power by number of chains active
+@@ -815,7 +796,6 @@ static void ath9k_hw_set_ar9287_power_pe
+ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
+                                       struct ath9k_channel *chan, u16 cfgCtl,
+                                       u8 twiceAntennaReduction,
+-                                      u8 twiceMaxRegulatoryPower,
+                                       u8 powerLimit, bool test)
+ {
+       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+@@ -834,7 +814,6 @@ static void ath9k_hw_ar9287_set_txpower(
+       ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
+                                                &ratesArray[0], cfgCtl,
+                                                twiceAntennaReduction,
+-                                               twiceMaxRegulatoryPower,
+                                                powerLimit);
+       ath9k_hw_set_ar9287_power_cal_table(ah, chan);
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -400,6 +400,7 @@ static u32 ath9k_hw_def_get_eeprom(struc
+       struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+       struct modal_eep_header *pModal = eep->modalHeader;
+       struct base_eep_header *pBase = &eep->baseEepHeader;
++      int band = 0;
+       switch (param) {
+       case EEP_NFTHRESH_5:
+@@ -467,6 +468,14 @@ static u32 ath9k_hw_def_get_eeprom(struc
+                       return pBase->pwr_table_offset;
+               else
+                       return AR5416_PWR_TABLE_OFFSET_DB;
++      case EEP_ANTENNA_GAIN_2G:
++              band = 1;
++              /* fall through */
++      case EEP_ANTENNA_GAIN_5G:
++              return max_t(u8, max_t(u8,
++                      pModal[band].antennaGainCh[0],
++                      pModal[band].antennaGainCh[1]),
++                      pModal[band].antennaGainCh[2]);
+       default:
+               return 0;
+       }
+@@ -986,21 +995,15 @@ static void ath9k_hw_set_def_power_per_r
+                                                 struct ath9k_channel *chan,
+                                                 int16_t *ratesArray,
+                                                 u16 cfgCtl,
+-                                                u16 AntennaReduction,
+-                                                u16 twiceMaxRegulatoryPower,
++                                                u16 antenna_reduction,
+                                                 u16 powerLimit)
+ {
+ #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
+ #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   9 /* 10*log10(3)*2 */
+-      struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+       u16 twiceMaxEdgePower = MAX_RATE_POWER;
+-      static const u16 tpScaleReductionTable[5] =
+-              { 0, 3, 6, 9, MAX_RATE_POWER };
+-
+       int i;
+-      int16_t twiceLargestAntenna;
+       struct cal_ctl_data *rep;
+       struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+               0, { 0, 0, 0, 0}
+@@ -1012,7 +1015,7 @@ static void ath9k_hw_set_def_power_per_r
+       struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+               0, {0, 0, 0, 0}
+       };
+-      u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
++      u16 scaledPower = 0, minCtlPower;
+       static const u16 ctlModesFor11a[] = {
+               CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+       };
+@@ -1031,27 +1034,7 @@ static void ath9k_hw_set_def_power_per_r
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+-      twiceLargestAntenna = max(
+-              pEepData->modalHeader
+-                      [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+-              pEepData->modalHeader
+-                      [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+-
+-      twiceLargestAntenna = max((u8)twiceLargestAntenna,
+-                                pEepData->modalHeader
+-                                [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+-
+-      twiceLargestAntenna = (int16_t)min(AntennaReduction -
+-                                         twiceLargestAntenna, 0);
+-
+-      maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+-
+-      if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+-              maxRegAllowedPower -=
+-                      (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+-      }
+-
+-      scaledPower = min(powerLimit, maxRegAllowedPower);
++      scaledPower = powerLimit - antenna_reduction;
+       switch (ar5416_get_ntxchains(tx_chainmask)) {
+       case 1:
+@@ -1256,7 +1239,6 @@ static void ath9k_hw_def_set_txpower(str
+                                   struct ath9k_channel *chan,
+                                   u16 cfgCtl,
+                                   u8 twiceAntennaReduction,
+-                                  u8 twiceMaxRegulatoryPower,
+                                   u8 powerLimit, bool test)
+ {
+ #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
+@@ -1278,7 +1260,6 @@ static void ath9k_hw_def_set_txpower(str
+       ath9k_hw_set_def_power_per_rate_table(ah, chan,
+                                              &ratesArray[0], cfgCtl,
+                                              twiceAntennaReduction,
+-                                             twiceMaxRegulatoryPower,
+                                              powerLimit);
+       ath9k_hw_set_def_power_cal_table(ah, chan);
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -763,10 +763,8 @@ static void ar5008_hw_set_channel_regs(s
+ static int ar5008_hw_process_ini(struct ath_hw *ah,
+                                struct ath9k_channel *chan)
+ {
+-      struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ath_common *common = ath9k_hw_common(ah);
+       int i, regWrites = 0;
+-      struct ieee80211_channel *channel = chan->chan;
+       u32 modesIndex, freqIndex;
+       switch (chan->chanmode) {
+@@ -903,14 +901,7 @@ static int ar5008_hw_process_ini(struct 
+       ar5008_hw_set_channel_regs(ah, chan);
+       ar5008_hw_init_chain_masks(ah);
+       ath9k_olc_init(ah);
+-
+-      /* Set TX power */
+-      ah->eep_ops->set_txpower(ah, chan,
+-                               ath9k_regd_get_ctl(regulatory, chan),
+-                               channel->max_antenna_gain * 2,
+-                               channel->max_power * 2,
+-                               min((u32) MAX_RATE_POWER,
+-                               (u32) regulatory->power_limit), false);
++      ath9k_hw_apply_txpower(ah, chan);
+       /* Write analog registers */
+       if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
+--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+@@ -19,7 +19,6 @@
+ void ar9003_paprd_enable(struct ath_hw *ah, bool val)
+ {
+-      struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+@@ -54,13 +53,7 @@ void ar9003_paprd_enable(struct ath_hw *
+       if (val) {
+               ah->paprd_table_write_done = true;
+-
+-              ah->eep_ops->set_txpower(ah, chan,
+-                              ath9k_regd_get_ctl(regulatory, chan),
+-                              chan->chan->max_antenna_gain * 2,
+-                              chan->chan->max_power * 2,
+-                              min((u32) MAX_RATE_POWER,
+-                              (u32) regulatory->power_limit), false);
++              ath9k_hw_apply_txpower(ah, chan);
+       }
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -628,9 +628,7 @@ static void ar9003_hw_prog_ini(struct at
+ static int ar9003_hw_process_ini(struct ath_hw *ah,
+                                struct ath9k_channel *chan)
+ {
+-      struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       unsigned int regWrites = 0, i;
+-      struct ieee80211_channel *channel = chan->chan;
+       u32 modesIndex;
+       switch (chan->chanmode) {
+@@ -683,14 +681,7 @@ static int ar9003_hw_process_ini(struct 
+       ar9003_hw_override_ini(ah);
+       ar9003_hw_set_channel_regs(ah, chan);
+       ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+-
+-      /* Set TX power */
+-      ah->eep_ops->set_txpower(ah, chan,
+-                               ath9k_regd_get_ctl(regulatory, chan),
+-                               channel->max_antenna_gain * 2,
+-                               channel->max_power * 2,
+-                               min((u32) MAX_RATE_POWER,
+-                               (u32) regulatory->power_limit), false);
++      ath9k_hw_apply_txpower(ah, chan);
+       return 0;
+ }
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -161,10 +161,12 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
+ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+                           u16 new_txpow, u16 *txpower)
+ {
+-      if (cur_txpow != new_txpow) {
++      struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
++
++      if (reg->power_limit != new_txpow) {
+               ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
+               /* read back in case value is clamped */
+-              *txpower = ath9k_hw_regulatory(ah)->power_limit;
++              *txpower = reg->max_power_level;
+       }
+ }
+ EXPORT_SYMBOL(ath9k_cmn_update_txpow);
+--- a/drivers/net/wireless/ath/ath9k/eeprom.h
++++ b/drivers/net/wireless/ath/ath9k/eeprom.h
+@@ -253,7 +253,9 @@ enum eeprom_param {
+       EEP_PAPRD,
+       EEP_MODAL_VER,
+       EEP_ANT_DIV_CTL1,
+-      EEP_CHAIN_MASK_REDUCE
++      EEP_CHAIN_MASK_REDUCE,
++      EEP_ANTENNA_GAIN_2G,
++      EEP_ANTENNA_GAIN_5G
+ };
+ enum ar5416_rates {
+@@ -657,8 +659,7 @@ struct eeprom_ops {
+       void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
+       void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
+                          u16 cfgCtl, u8 twiceAntennaReduction,
+-                         u8 twiceMaxRegulatoryPower, u8 powerLimit,
+-                         bool test);
++                         u8 powerLimit, bool test);
+       u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
+ };
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -626,7 +626,6 @@ static void ath9k_init_band_txpower(stru
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_channel *chan;
+       struct ath_hw *ah = sc->sc_ah;
+-      struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+       int i;
+       sband = &sc->sbands[band];
+@@ -635,7 +634,6 @@ static void ath9k_init_band_txpower(stru
+               ah->curchan = &ah->channels[chan->hw_value];
+               ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
+               ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
+-              chan->max_power = reg->max_power_level / 2;
+       }
+ }
diff --git a/package/mac80211/patches/581-ath9k_use_reset_work.patch b/package/mac80211/patches/581-ath9k_use_reset_work.patch
deleted file mode 100644 (file)
index 0be41b6..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -429,6 +429,7 @@ void ath9k_set_beaconing_status(struct a
- #define ATH_PAPRD_TIMEOUT     100 /* msecs */
-+void ath_reset_work(struct work_struct *work);
- void ath_hw_check(struct work_struct *work);
- void ath_hw_pll_work(struct work_struct *work);
- void ath_paprd_calibrate(struct work_struct *work);
-@@ -609,6 +610,7 @@ struct ath_softc {
-       struct mutex mutex;
-       struct work_struct paprd_work;
-       struct work_struct hw_check_work;
-+      struct work_struct hw_reset_work;
-       struct completion paprd_complete;
-       unsigned int hw_busy_count;
-@@ -655,7 +657,6 @@ struct ath_softc {
- };
- void ath9k_tasklet(unsigned long data);
--int ath_reset(struct ath_softc *sc, bool retry_tx);
- int ath_cabq_update(struct ath_softc *);
- static inline void ath_read_cachesize(struct ath_common *common, int *csz)
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -386,9 +386,7 @@ void ath_beacon_tasklet(unsigned long da
-                       ath_dbg(common, ATH_DBG_BSTUCK,
-                               "beacon is officially stuck\n");
-                       sc->sc_flags |= SC_OP_TSF_RESET;
--                      spin_lock(&sc->sc_pcu_lock);
--                      ath_reset(sc, true);
--                      spin_unlock(&sc->sc_pcu_lock);
-+                      ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
-               }
-               return;
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -776,6 +776,7 @@ int ath9k_init_device(u16 devid, struct 
-                       goto error_world;
-       }
-+      INIT_WORK(&sc->hw_reset_work, ath_reset_work);
-       INIT_WORK(&sc->hw_check_work, ath_hw_check);
-       INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
-       INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -236,6 +236,7 @@ static int ath_set_channel(struct ath_so
-       del_timer_sync(&common->ani.timer);
-       cancel_work_sync(&sc->paprd_work);
-       cancel_work_sync(&sc->hw_check_work);
-+      cancel_work_sync(&sc->hw_reset_work);
-       cancel_delayed_work_sync(&sc->tx_complete_work);
-       cancel_delayed_work_sync(&sc->hw_pll_work);
-@@ -595,74 +596,6 @@ static void ath_node_detach(struct ath_s
-               ath_tx_node_cleanup(sc, an);
- }
--void ath_hw_check(struct work_struct *work)
--{
--      struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
--      unsigned long flags;
--      int busy;
--
--      ath9k_ps_wakeup(sc);
--      if (ath9k_hw_check_alive(sc->sc_ah))
--              goto out;
--
--      spin_lock_irqsave(&common->cc_lock, flags);
--      busy = ath_update_survey_stats(sc);
--      spin_unlock_irqrestore(&common->cc_lock, flags);
--
--      ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
--              "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
--      if (busy >= 99) {
--              if (++sc->hw_busy_count >= 3) {
--                      spin_lock_bh(&sc->sc_pcu_lock);
--                      ath_reset(sc, true);
--                      spin_unlock_bh(&sc->sc_pcu_lock);
--              }
--      } else if (busy >= 0)
--              sc->hw_busy_count = 0;
--
--out:
--      ath9k_ps_restore(sc);
--}
--
--static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
--{
--      static int count;
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
--
--      if (pll_sqsum >= 0x40000) {
--              count++;
--              if (count == 3) {
--                      /* Rx is hung for more than 500ms. Reset it */
--                      ath_dbg(common, ATH_DBG_RESET,
--                              "Possible RX hang, resetting");
--                      spin_lock_bh(&sc->sc_pcu_lock);
--                      ath_reset(sc, true);
--                      spin_unlock_bh(&sc->sc_pcu_lock);
--                      count = 0;
--              }
--      } else
--              count = 0;
--}
--
--void ath_hw_pll_work(struct work_struct *work)
--{
--      struct ath_softc *sc = container_of(work, struct ath_softc,
--                                          hw_pll_work.work);
--      u32 pll_sqsum;
--
--      if (AR_SREV_9485(sc->sc_ah)) {
--
--              ath9k_ps_wakeup(sc);
--              pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
--              ath9k_ps_restore(sc);
--
--              ath_hw_pll_rx_hang_check(sc, pll_sqsum);
--
--              ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
--      }
--}
--
- void ath9k_tasklet(unsigned long data)
- {
-@@ -675,9 +608,7 @@ void ath9k_tasklet(unsigned long data)
-       if ((status & ATH9K_INT_FATAL) ||
-           (status & ATH9K_INT_BB_WATCHDOG)) {
--              spin_lock(&sc->sc_pcu_lock);
--              ath_reset(sc, true);
--              spin_unlock(&sc->sc_pcu_lock);
-+              ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
-               return;
-       }
-@@ -968,7 +899,7 @@ void ath_radio_disable(struct ath_softc 
-       ath9k_ps_restore(sc);
- }
--int ath_reset(struct ath_softc *sc, bool retry_tx)
-+static int ath_reset(struct ath_softc *sc, bool retry_tx)
- {
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-@@ -1035,6 +966,84 @@ int ath_reset(struct ath_softc *sc, bool
-       return r;
- }
-+void ath_reset_work(struct work_struct *work)
-+{
-+      struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
-+
-+      spin_lock_bh(&sc->sc_pcu_lock);
-+      ath_reset(sc, true);
-+      spin_unlock_bh(&sc->sc_pcu_lock);
-+}
-+
-+void ath_hw_check(struct work_struct *work)
-+{
-+      struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
-+      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+      unsigned long flags;
-+      int busy;
-+
-+      ath9k_ps_wakeup(sc);
-+      if (ath9k_hw_check_alive(sc->sc_ah))
-+              goto out;
-+
-+      spin_lock_irqsave(&common->cc_lock, flags);
-+      busy = ath_update_survey_stats(sc);
-+      spin_unlock_irqrestore(&common->cc_lock, flags);
-+
-+      ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
-+              "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
-+      if (busy >= 99) {
-+              if (++sc->hw_busy_count >= 3) {
-+                      spin_lock_bh(&sc->sc_pcu_lock);
-+                      ath_reset(sc, true);
-+                      spin_unlock_bh(&sc->sc_pcu_lock);
-+              }
-+
-+      } else if (busy >= 0)
-+              sc->hw_busy_count = 0;
-+
-+out:
-+      ath9k_ps_restore(sc);
-+}
-+
-+static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
-+{
-+      static int count;
-+      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+
-+      if (pll_sqsum >= 0x40000) {
-+              count++;
-+              if (count == 3) {
-+                      /* Rx is hung for more than 500ms. Reset it */
-+                      ath_dbg(common, ATH_DBG_RESET,
-+                              "Possible RX hang, resetting");
-+                      spin_lock_bh(&sc->sc_pcu_lock);
-+                      ath_reset(sc, true);
-+                      spin_unlock_bh(&sc->sc_pcu_lock);
-+                      count = 0;
-+              }
-+      } else
-+              count = 0;
-+}
-+
-+void ath_hw_pll_work(struct work_struct *work)
-+{
-+      struct ath_softc *sc = container_of(work, struct ath_softc,
-+                                          hw_pll_work.work);
-+      u32 pll_sqsum;
-+
-+      if (AR_SREV_9485(sc->sc_ah)) {
-+
-+              ath9k_ps_wakeup(sc);
-+              pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
-+              ath9k_ps_restore(sc);
-+
-+              ath_hw_pll_rx_hang_check(sc, pll_sqsum);
-+
-+              ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
-+      }
-+}
-+
- /**********************/
- /* mac80211 callbacks */
- /**********************/
-@@ -1227,6 +1236,7 @@ static void ath9k_stop(struct ieee80211_
-       cancel_delayed_work_sync(&sc->hw_pll_work);
-       cancel_work_sync(&sc->paprd_work);
-       cancel_work_sync(&sc->hw_check_work);
-+      cancel_work_sync(&sc->hw_reset_work);
-       if (sc->sc_flags & SC_OP_INVALID) {
-               ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -604,7 +604,7 @@ static void ath_tx_complete_aggr(struct 
-       rcu_read_unlock();
-       if (needreset)
--              ath_reset(sc, false);
-+              ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
- }
- static bool ath_lookup_legacy(struct ath_buf *bf)
-@@ -1357,7 +1357,7 @@ void ath_txq_schedule(struct ath_softc *
-       struct ath_atx_ac *ac, *ac_tmp, *last_ac;
-       struct ath_atx_tid *tid, *last_tid;
--      if (list_empty(&txq->axq_acq) ||
-+      if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
-           txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
-               return;
-@@ -2184,6 +2184,9 @@ static void ath_tx_processq(struct ath_s
-       spin_lock_bh(&txq->axq_lock);
-       for (;;) {
-+              if (work_pending(&sc->hw_reset_work))
-+                      break;
-+
-               if (list_empty(&txq->axq_q)) {
-                       txq->axq_link = NULL;
-                       if (sc->sc_flags & SC_OP_TXAGGR)
-@@ -2271,9 +2274,7 @@ static void ath_tx_complete_poll_work(st
-       if (needreset) {
-               ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
-                       "tx hung, resetting the chip\n");
--              spin_lock_bh(&sc->sc_pcu_lock);
--              ath_reset(sc, true);
--              spin_unlock_bh(&sc->sc_pcu_lock);
-+              ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
-       }
-       ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
-@@ -2306,6 +2307,9 @@ void ath_tx_edma_tasklet(struct ath_soft
-       int status;
-       for (;;) {
-+              if (work_pending(&sc->hw_reset_work))
-+                      break;
-+
-               status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
-               if (status == -EINPROGRESS)
-                       break;
diff --git a/package/mac80211/patches/582-ath9k_merge_reset_functions.patch b/package/mac80211/patches/582-ath9k_merge_reset_functions.patch
deleted file mode 100644 (file)
index 54d0eaf..0000000
+++ /dev/null
@@ -1,448 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -212,84 +212,57 @@ static int ath_update_survey_stats(struc
-       return ret;
- }
--/*
-- * Set/change channels.  If the channel is really being changed, it's done
-- * by reseting the chip.  To accomplish this we must first cleanup any pending
-- * DMA, then restart stuff.
--*/
--static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
--                  struct ath9k_channel *hchan)
-+static void __ath_cancel_work(struct ath_softc *sc)
- {
--      struct ath_hw *ah = sc->sc_ah;
--      struct ath_common *common = ath9k_hw_common(ah);
--      struct ieee80211_conf *conf = &common->hw->conf;
--      bool fastcc = true, stopped;
--      struct ieee80211_channel *channel = hw->conf.channel;
--      struct ath9k_hw_cal_data *caldata = NULL;
--      int r;
--
--      if (sc->sc_flags & SC_OP_INVALID)
--              return -EIO;
--
--      sc->hw_busy_count = 0;
--
--      del_timer_sync(&common->ani.timer);
-       cancel_work_sync(&sc->paprd_work);
-       cancel_work_sync(&sc->hw_check_work);
--      cancel_work_sync(&sc->hw_reset_work);
-       cancel_delayed_work_sync(&sc->tx_complete_work);
-       cancel_delayed_work_sync(&sc->hw_pll_work);
-+}
--      ath9k_ps_wakeup(sc);
-+static void ath_cancel_work(struct ath_softc *sc)
-+{
-+      __ath_cancel_work(sc);
-+      cancel_work_sync(&sc->hw_reset_work);
-+}
--      spin_lock_bh(&sc->sc_pcu_lock);
-+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
-+{
-+      struct ath_hw *ah = sc->sc_ah;
-+      struct ath_common *common = ath9k_hw_common(ah);
-+      bool ret;
--      /*
--       * This is only performed if the channel settings have
--       * actually changed.
--       *
--       * To switch channels clear any pending DMA operations;
--       * wait long enough for the RX fifo to drain, reset the
--       * hardware at the new frequency, and then re-enable
--       * the relevant bits of the h/w.
--       */
--      ath9k_hw_disable_interrupts(ah);
--      stopped = ath_drain_all_txq(sc, false);
-+      ieee80211_stop_queues(sc->hw);
--      if (!ath_stoprecv(sc))
--              stopped = false;
-+      sc->hw_busy_count = 0;
-+      del_timer_sync(&common->ani.timer);
--      if (!ath9k_hw_check_alive(ah))
--              stopped = false;
-+      ath9k_hw_disable_interrupts(ah);
--      /* XXX: do not flush receive queue here. We don't want
--       * to flush data frames already in queue because of
--       * changing channel. */
-+      ret = ath_drain_all_txq(sc, retry_tx);
--      if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
--              fastcc = false;
-+      if (!ath_stoprecv(sc))
-+              ret = false;
--      if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
--              caldata = &sc->caldata;
-+      if (!flush) {
-+              if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
-+                      ath_rx_tasklet(sc, 0, true);
-+              ath_rx_tasklet(sc, 0, false);
-+      } else {
-+              ath_flushrecv(sc);
-+      }
--      ath_dbg(common, ATH_DBG_CONFIG,
--              "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
--              sc->sc_ah->curchan->channel,
--              channel->center_freq, conf_is_ht40(conf),
--              fastcc);
-+      return ret;
-+}
--      r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
--      if (r) {
--              ath_err(common,
--                      "Unable to reset channel (%u MHz), reset status %d\n",
--                      channel->center_freq, r);
--              goto ps_restore;
--      }
-+static bool ath_complete_reset(struct ath_softc *sc, bool start)
-+{
-+      struct ath_hw *ah = sc->sc_ah;
-+      struct ath_common *common = ath9k_hw_common(ah);
-       if (ath_startrecv(sc) != 0) {
-               ath_err(common, "Unable to restart recv logic\n");
--              r = -EIO;
--              goto ps_restore;
-+              return false;
-       }
-       ath9k_cmn_update_txpow(ah, sc->curtxpow,
-@@ -297,21 +270,93 @@ static int ath_set_channel(struct ath_so
-       ath9k_hw_set_interrupts(ah, ah->imask);
-       ath9k_hw_enable_interrupts(ah);
--      if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
-+      if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
-               if (sc->sc_flags & SC_OP_BEACONS)
-                       ath_set_beacon(sc);
-+
-               ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
-               ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
-               if (!common->disable_ani)
-                       ath_start_ani(common);
-       }
-- ps_restore:
--      ieee80211_wake_queues(hw);
-+      ieee80211_wake_queues(sc->hw);
-+
-+      return true;
-+}
-+
-+static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
-+                            bool retry_tx)
-+{
-+      struct ath_hw *ah = sc->sc_ah;
-+      struct ath_common *common = ath9k_hw_common(ah);
-+      struct ath9k_hw_cal_data *caldata = NULL;
-+      bool fastcc = true;
-+      bool flush = false;
-+      int r;
-+
-+      __ath_cancel_work(sc);
-+
-+      spin_lock_bh(&sc->sc_pcu_lock);
-+      if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
-+              fastcc = false;
-+              caldata = &sc->caldata;
-+      }
-+
-+      if (!hchan) {
-+              fastcc = false;
-+              flush = true;
-+              hchan = ah->curchan;
-+      }
-+
-+      if (fastcc && !ath9k_hw_check_alive(ah))
-+              fastcc = false;
-+
-+      if (!ath_prepare_reset(sc, retry_tx, flush))
-+              fastcc = false;
-+
-+      ath_dbg(common, ATH_DBG_CONFIG,
-+              "Reset to %u MHz, HT40: %d fastcc: %d\n",
-+              hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
-+                                                        CHANNEL_HT40PLUS)),
-+              fastcc);
-+
-+      r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
-+      if (r) {
-+              ath_err(common,
-+                      "Unable to reset channel, reset status %d\n", r);
-+              goto out;
-+      }
-+
-+      if (!ath_complete_reset(sc, true))
-+              r = -EIO;
-+
-+out:
-       spin_unlock_bh(&sc->sc_pcu_lock);
-+      return r;
-+}
-+
-+
-+/*
-+ * Set/change channels.  If the channel is really being changed, it's done
-+ * by reseting the chip.  To accomplish this we must first cleanup any pending
-+ * DMA, then restart stuff.
-+*/
-+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
-+                  struct ath9k_channel *hchan)
-+{
-+      int r;
-+
-+      if (sc->sc_flags & SC_OP_INVALID)
-+              return -EIO;
-+
-+      ath9k_ps_wakeup(sc);
-+
-+      r = ath_reset_internal(sc, hchan, false);
-       ath9k_ps_restore(sc);
-+
-       return r;
- }
-@@ -824,28 +869,13 @@ static void ath_radio_enable(struct ath_
-                       channel->center_freq, r);
-       }
--      ath9k_cmn_update_txpow(ah, sc->curtxpow,
--                             sc->config.txpowlimit, &sc->curtxpow);
--      if (ath_startrecv(sc) != 0) {
--              ath_err(common, "Unable to restart recv logic\n");
--              goto out;
--      }
--      if (sc->sc_flags & SC_OP_BEACONS)
--              ath_set_beacon(sc);     /* restart beacons */
--
--      /* Re-Enable  interrupts */
--      ath9k_hw_set_interrupts(ah, ah->imask);
--      ath9k_hw_enable_interrupts(ah);
-+      ath_complete_reset(sc, true);
-       /* Enable LED */
-       ath9k_hw_cfg_output(ah, ah->led_pin,
-                           AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-       ath9k_hw_set_gpio(ah, ah->led_pin, 0);
--      ieee80211_wake_queues(hw);
--      ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
--
--out:
-       spin_unlock_bh(&sc->sc_pcu_lock);
-       ath9k_ps_restore(sc);
-@@ -858,11 +888,10 @@ void ath_radio_disable(struct ath_softc 
-       int r;
-       ath9k_ps_wakeup(sc);
--      cancel_delayed_work_sync(&sc->hw_pll_work);
--      spin_lock_bh(&sc->sc_pcu_lock);
-+      ath_cancel_work(sc);
--      ieee80211_stop_queues(hw);
-+      spin_lock_bh(&sc->sc_pcu_lock);
-       /*
-        * Keep the LED on when the radio is disabled
-@@ -873,13 +902,7 @@ void ath_radio_disable(struct ath_softc 
-               ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
-       }
--      /* Disable interrupts */
--      ath9k_hw_disable_interrupts(ah);
--
--      ath_drain_all_txq(sc, false);   /* clear pending tx frames */
--
--      ath_stoprecv(sc);               /* turn off frame recv */
--      ath_flushrecv(sc);              /* flush recv queue */
-+      ath_prepare_reset(sc, false, true);
-       if (!ah->curchan)
-               ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-@@ -901,48 +924,11 @@ void ath_radio_disable(struct ath_softc 
- static int ath_reset(struct ath_softc *sc, bool retry_tx)
- {
--      struct ath_hw *ah = sc->sc_ah;
--      struct ath_common *common = ath9k_hw_common(ah);
--      struct ieee80211_hw *hw = sc->hw;
-       int r;
--      sc->hw_busy_count = 0;
--
--      /* Stop ANI */
--
--      del_timer_sync(&common->ani.timer);
--
-       ath9k_ps_wakeup(sc);
--      ieee80211_stop_queues(hw);
--
--      ath9k_hw_disable_interrupts(ah);
--      ath_drain_all_txq(sc, retry_tx);
--
--      ath_stoprecv(sc);
--      ath_flushrecv(sc);
--
--      r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
--      if (r)
--              ath_err(common,
--                      "Unable to reset hardware; reset status %d\n", r);
--
--      if (ath_startrecv(sc) != 0)
--              ath_err(common, "Unable to start recv logic\n");
--
--      /*
--       * We may be doing a reset in response to a request
--       * that changes the channel so update any state that
--       * might change as a result.
--       */
--      ath9k_cmn_update_txpow(ah, sc->curtxpow,
--                             sc->config.txpowlimit, &sc->curtxpow);
--
--      if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
--              ath_set_beacon(sc);     /* restart beacons */
--
--      ath9k_hw_set_interrupts(ah, ah->imask);
--      ath9k_hw_enable_interrupts(ah);
-+      r = ath_reset_internal(sc, NULL, retry_tx);
-       if (retry_tx) {
-               int i;
-@@ -955,12 +941,6 @@ static int ath_reset(struct ath_softc *s
-               }
-       }
--      ieee80211_wake_queues(hw);
--
--      /* Start ANI */
--      if (!common->disable_ani)
--              ath_start_ani(common);
--
-       ath9k_ps_restore(sc);
-       return r;
-@@ -970,9 +950,7 @@ void ath_reset_work(struct work_struct *
- {
-       struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
--      spin_lock_bh(&sc->sc_pcu_lock);
-       ath_reset(sc, true);
--      spin_unlock_bh(&sc->sc_pcu_lock);
- }
- void ath_hw_check(struct work_struct *work)
-@@ -993,11 +971,8 @@ void ath_hw_check(struct work_struct *wo
-       ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
-               "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
-       if (busy >= 99) {
--              if (++sc->hw_busy_count >= 3) {
--                      spin_lock_bh(&sc->sc_pcu_lock);
--                      ath_reset(sc, true);
--                      spin_unlock_bh(&sc->sc_pcu_lock);
--              }
-+              if (++sc->hw_busy_count >= 3)
-+                      ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
-       } else if (busy >= 0)
-               sc->hw_busy_count = 0;
-@@ -1017,9 +992,7 @@ static void ath_hw_pll_rx_hang_check(str
-                       /* Rx is hung for more than 500ms. Reset it */
-                       ath_dbg(common, ATH_DBG_RESET,
-                               "Possible RX hang, resetting");
--                      spin_lock_bh(&sc->sc_pcu_lock);
--                      ath_reset(sc, true);
--                      spin_unlock_bh(&sc->sc_pcu_lock);
-+                      ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
-                       count = 0;
-               }
-       } else
-@@ -1090,28 +1063,6 @@ static int ath9k_start(struct ieee80211_
-               goto mutex_unlock;
-       }
--      /*
--       * This is needed only to setup initial state
--       * but it's best done after a reset.
--       */
--      ath9k_cmn_update_txpow(ah, sc->curtxpow,
--                      sc->config.txpowlimit, &sc->curtxpow);
--
--      /*
--       * Setup the hardware after reset:
--       * The receive engine is set going.
--       * Frame transmit is handled entirely
--       * in the frame output path; there's nothing to do
--       * here except setup the interrupt mask.
--       */
--      if (ath_startrecv(sc) != 0) {
--              ath_err(common, "Unable to start recv logic\n");
--              r = -EIO;
--              spin_unlock_bh(&sc->sc_pcu_lock);
--              goto mutex_unlock;
--      }
--      spin_unlock_bh(&sc->sc_pcu_lock);
--
-       /* Setup our intr mask. */
-       ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
-                   ATH9K_INT_RXORN | ATH9K_INT_FATAL |
-@@ -1134,12 +1085,14 @@ static int ath9k_start(struct ieee80211_
-       /* Disable BMISS interrupt when we're not associated */
-       ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
--      ath9k_hw_set_interrupts(ah, ah->imask);
--      ath9k_hw_enable_interrupts(ah);
--      ieee80211_wake_queues(hw);
-+      if (!ath_complete_reset(sc, false)) {
-+              r = -EIO;
-+              spin_unlock_bh(&sc->sc_pcu_lock);
-+              goto mutex_unlock;
-+      }
--      ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
-+      spin_unlock_bh(&sc->sc_pcu_lock);
-       if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
-           !ah->btcoex_hw.enabled) {
-@@ -1232,11 +1185,7 @@ static void ath9k_stop(struct ieee80211_
-       mutex_lock(&sc->mutex);
--      cancel_delayed_work_sync(&sc->tx_complete_work);
--      cancel_delayed_work_sync(&sc->hw_pll_work);
--      cancel_work_sync(&sc->paprd_work);
--      cancel_work_sync(&sc->hw_check_work);
--      cancel_work_sync(&sc->hw_reset_work);
-+      ath_cancel_work(sc);
-       if (sc->sc_flags & SC_OP_INVALID) {
-               ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
-@@ -2353,9 +2302,11 @@ static void ath9k_flush(struct ieee80211
-       ath9k_ps_wakeup(sc);
-       spin_lock_bh(&sc->sc_pcu_lock);
-       drain_txq = ath_drain_all_txq(sc, false);
-+      spin_unlock_bh(&sc->sc_pcu_lock);
-+
-       if (!drain_txq)
-               ath_reset(sc, false);
--      spin_unlock_bh(&sc->sc_pcu_lock);
-+
-       ath9k_ps_restore(sc);
-       ieee80211_wake_queues(hw);
diff --git a/package/mac80211/patches/582-ath9k_remove_current_rd_ext.patch b/package/mac80211/patches/582-ath9k_remove_current_rd_ext.patch
new file mode 100644 (file)
index 0000000..c2f61c2
--- /dev/null
@@ -0,0 +1,34 @@
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -72,7 +72,6 @@ struct ath_regulatory {
+       u16 country_code;
+       u16 max_power_level;
+       u16 current_rd;
+-      u16 current_rd_ext;
+       int16_t power_limit;
+       struct reg_dmn_pair_mapping *regpair;
+ };
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2047,11 +2047,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+       eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
+       regulatory->current_rd = eeval;
+-      eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
+-      if (AR_SREV_9285_12_OR_LATER(ah))
+-              eeval |= AR9285_RDEXT_DEFAULT;
+-      regulatory->current_rd_ext = eeval;
+-
+       if (ah->opmode != NL80211_IFTYPE_AP &&
+           ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
+               if (regulatory->current_rd == 0x64 ||
+--- a/drivers/net/wireless/ath/carl9170/main.c
++++ b/drivers/net/wireless/ath/carl9170/main.c
+@@ -1912,7 +1912,6 @@ static int carl9170_parse_eeprom(struct 
+               ar->hw->channel_change_time = 80 * 1000;
+       regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
+-      regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
+       /* second part of wiphy init */
+       SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
diff --git a/package/mac80211/patches/583-ath9k_antenna_control.patch b/package/mac80211/patches/583-ath9k_antenna_control.patch
deleted file mode 100644 (file)
index d69684d..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -652,9 +652,22 @@ static void ath9k_init_txpower_limits(st
-       ah->curchan = curchan;
- }
-+void ath9k_reload_chainmask_settings(struct ath_softc *sc)
-+{
-+      if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT))
-+              return;
-+
-+      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
-+              setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
-+      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
-+              setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
-+}
-+
-+
- void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
- {
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+      struct ath_hw *ah = sc->sc_ah;
-+      struct ath_common *common = ath9k_hw_common(ah);
-       hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-               IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-@@ -692,6 +705,16 @@ void ath9k_set_hw_capab(struct ath_softc
-       hw->sta_data_size = sizeof(struct ath_node);
-       hw->vif_data_size = sizeof(struct ath_vif);
-+      hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
-+      hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
-+
-+      /* single chain devices with rx diversity */
-+      if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
-+              hw->wiphy->available_antennas_rx = BIT(0) | BIT(1);
-+
-+      sc->ant_rx = hw->wiphy->available_antennas_rx;
-+      sc->ant_tx = hw->wiphy->available_antennas_tx;
-+
- #ifdef CONFIG_ATH9K_RATE_CONTROL
-       hw->rate_control_algorithm = "ath9k_rate_control";
- #endif
-@@ -703,12 +726,7 @@ void ath9k_set_hw_capab(struct ath_softc
-               hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-                       &sc->sbands[IEEE80211_BAND_5GHZ];
--      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
--              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
--                      setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
--              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
--                      setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
--      }
-+      ath9k_reload_chainmask_settings(sc);
-       SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
- }
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -654,6 +654,7 @@ struct ath_softc {
-       struct ath_descdma txsdma;
-       struct ath_ant_comb ant_comb;
-+      u8 ant_tx, ant_rx;
- };
- void ath9k_tasklet(unsigned long data);
-@@ -674,6 +675,7 @@ int ath9k_init_device(u16 devid, struct 
-                   const struct ath_bus_ops *bus_ops);
- void ath9k_deinit_device(struct ath_softc *sc);
- void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
-+void ath9k_reload_chainmask_settings(struct ath_softc *sc);
- void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
- bool ath9k_uses_beacons(int type);
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -280,6 +280,22 @@ static bool ath_complete_reset(struct at
-                       ath_start_ani(common);