From b139cef40ade2d9be8a8a883144b89ebef069666 Mon Sep 17 00:00:00 2001
From: nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Wed, 23 Mar 2011 20:16:58 +0000
Subject: ath9k: add a few de-bloating and optimization patches

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@26281 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../patches/560-ath9k_move_regops_struct.patch     | 109 ++++++++
 .../patches/561-ath9k_optimize_reg_rmw.patch       | 110 +++++++++
 .../mac80211/patches/562-ath9k_use_reg_rmw.patch   | 274 +++++++++++++++++++++
 .../patches/563-ath9k_reg_write_array_func.patch   | 150 +++++++++++
 .../564-ath9k_remove_total_queues_cap.patch        | 137 +++++++++++
 .../patches/565-ath9k_remove_ht_config.patch       |  33 +++
 .../mac80211/patches/566-ath9k_remove_regcap.patch |  36 +++
 .../patches/567-ath9k_remove_keycache_size.patch   |  59 +++++
 .../patches/568-ath9k_remove_enhancedpm.patch      |  21 ++
 .../569-ath9k_remove_tx_triglevel_max.patch        |  35 +++
 10 files changed, 964 insertions(+)
 create mode 100644 package/mac80211/patches/560-ath9k_move_regops_struct.patch
 create mode 100644 package/mac80211/patches/561-ath9k_optimize_reg_rmw.patch
 create mode 100644 package/mac80211/patches/562-ath9k_use_reg_rmw.patch
 create mode 100644 package/mac80211/patches/563-ath9k_reg_write_array_func.patch
 create mode 100644 package/mac80211/patches/564-ath9k_remove_total_queues_cap.patch
 create mode 100644 package/mac80211/patches/565-ath9k_remove_ht_config.patch
 create mode 100644 package/mac80211/patches/566-ath9k_remove_regcap.patch
 create mode 100644 package/mac80211/patches/567-ath9k_remove_keycache_size.patch
 create mode 100644 package/mac80211/patches/568-ath9k_remove_enhancedpm.patch
 create mode 100644 package/mac80211/patches/569-ath9k_remove_tx_triglevel_max.patch

diff --git a/package/mac80211/patches/560-ath9k_move_regops_struct.patch b/package/mac80211/patches/560-ath9k_move_regops_struct.patch
new file mode 100644
index 000000000..8e52df451
--- /dev/null
+++ b/package/mac80211/patches/560-ath9k_move_regops_struct.patch
@@ -0,0 +1,109 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -65,24 +65,24 @@
+ 
+ /* Register read/write primitives */
+ #define REG_WRITE(_ah, _reg, _val) \
+-	ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
++	(_ah)->reg_ops.write((_ah), (_val), (_reg))
+ 
+ #define REG_READ(_ah, _reg) \
+-	ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
++	(_ah)->reg_ops.read((_ah), (_reg))
+ 
+ #define REG_READ_MULTI(_ah, _addr, _val, _cnt)		\
+-	ath9k_hw_common(_ah)->ops->multi_read((_ah), (_addr), (_val), (_cnt))
++	(_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt))
+ 
+ #define ENABLE_REGWRITE_BUFFER(_ah)					\
+ 	do {								\
+-		if (ath9k_hw_common(_ah)->ops->enable_write_buffer)	\
+-			ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \
++		if ((_ah)->reg_ops.enable_write_buffer)	\
++			(_ah)->reg_ops.enable_write_buffer((_ah)); \
+ 	} while (0)
+ 
+ #define REGWRITE_BUFFER_FLUSH(_ah)					\
+ 	do {								\
+-		if (ath9k_hw_common(_ah)->ops->write_flush)		\
+-			ath9k_hw_common(_ah)->ops->write_flush((_ah));	\
++		if ((_ah)->reg_ops.write_flush)		\
++			(_ah)->reg_ops.write_flush((_ah));	\
+ 	} while (0)
+ 
+ #define SM(_v, _f)  (((_v) << _f##_S) & _f)
+@@ -659,6 +659,8 @@ struct ath_nf_limits {
+ #define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
+ 
+ struct ath_hw {
++	struct ath_ops reg_ops;
++
+ 	struct ieee80211_hw *hw;
+ 	struct ath_common common;
+ 	struct ath9k_hw_version hw_version;
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -430,14 +430,6 @@ static void ath9k_regwrite_flush(void *h
+ 	mutex_unlock(&priv->wmi->multi_write_mutex);
+ }
+ 
+-static const struct ath_ops ath9k_common_ops = {
+-	.read = ath9k_regread,
+-	.multi_read = ath9k_multi_regread,
+-	.write = ath9k_regwrite,
+-	.enable_write_buffer = ath9k_enable_regwrite_buffer,
+-	.write_flush = ath9k_regwrite_flush,
+-};
+-
+ static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
+ {
+ 	*csz = L1_CACHE_BYTES >> 2;
+@@ -658,10 +650,15 @@ static int ath9k_init_priv(struct ath9k_
+ 	ah->hw_version.subsysid = 0; /* FIXME */
+ 	ah->hw_version.usbdev = drv_info;
+ 	ah->ah_flags |= AH_USE_EEPROM;
++	ah->reg_ops.read = ath9k_regread;
++	ah->reg_ops.multi_read = ath9k_multi_regread;
++	ah->reg_ops.write = ath9k_regwrite;
++	ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer;
++	ah->reg_ops.write_flush = ath9k_regwrite_flush;
+ 	priv->ah = ah;
+ 
+ 	common = ath9k_hw_common(ah);
+-	common->ops = &ath9k_common_ops;
++	common->ops = &ah->reg_ops;
+ 	common->bus_ops = &ath9k_usb_bus_ops;
+ 	common->ah = ah;
+ 	common->hw = priv->hw;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -196,11 +196,6 @@ static unsigned int ath9k_ioread32(void 
+ 	return val;
+ }
+ 
+-static const struct ath_ops ath9k_common_ops = {
+-	.read = ath9k_ioread32,
+-	.write = ath9k_iowrite32,
+-};
+-
+ /**************************/
+ /*     Initialization     */
+ /**************************/
+@@ -551,6 +546,8 @@ static int ath9k_init_softc(u16 devid, s
+ 	ah->hw = sc->hw;
+ 	ah->hw_version.devid = devid;
+ 	ah->hw_version.subsysid = subsysid;
++	ah->reg_ops.read = ath9k_ioread32;
++	ah->reg_ops.write = ath9k_iowrite32;
+ 	sc->sc_ah = ah;
+ 
+ 	if (!pdata) {
+@@ -563,7 +560,7 @@ static int ath9k_init_softc(u16 devid, s
+ 	}
+ 
+ 	common = ath9k_hw_common(ah);
+-	common->ops = &ath9k_common_ops;
++	common->ops = &ah->reg_ops;
+ 	common->bus_ops = bus_ops;
+ 	common->ah = ah;
+ 	common->hw = sc->hw;
diff --git a/package/mac80211/patches/561-ath9k_optimize_reg_rmw.patch b/package/mac80211/patches/561-ath9k_optimize_reg_rmw.patch
new file mode 100644
index 000000000..c2254e565
--- /dev/null
+++ b/package/mac80211/patches/561-ath9k_optimize_reg_rmw.patch
@@ -0,0 +1,110 @@
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -430,6 +430,17 @@ static void ath9k_regwrite_flush(void *h
+ 	mutex_unlock(&priv->wmi->multi_write_mutex);
+ }
+ 
++static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
++{
++	u32 val;
++
++	val = ath9k_regread(hw_priv, reg_offset);
++	val &= ~clr;
++	val |= set;
++	ath9k_regwrite(hw_priv, val, reg_offset);
++	return val;
++}
++
+ static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
+ {
+ 	*csz = L1_CACHE_BYTES >> 2;
+@@ -655,6 +666,7 @@ static int ath9k_init_priv(struct ath9k_
+ 	ah->reg_ops.write = ath9k_regwrite;
+ 	ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer;
+ 	ah->reg_ops.write_flush = ath9k_regwrite_flush;
++	ah->reg_ops.rmw = ath9k_reg_rmw;
+ 	priv->ah = ah;
+ 
+ 	common = ath9k_hw_common(ah);
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -119,6 +119,7 @@ struct ath_ops {
+ 	void (*write)(void *, u32 val, u32 reg_offset);
+ 	void (*enable_write_buffer)(void *);
+ 	void (*write_flush) (void *);
++	u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr);
+ };
+ 
+ struct ath_common;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -196,6 +196,28 @@ static unsigned int ath9k_ioread32(void 
+ 	return val;
+ }
+ 
++static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
++{
++	struct ath_hw *ah = (struct ath_hw *) hw_priv;
++	struct ath_common *common = ath9k_hw_common(ah);
++	struct ath_softc *sc = (struct ath_softc *) common->priv;
++	unsigned long uninitialized_var(flags);
++	u32 val;
++
++	if (ah->config.serialize_regmode == SER_REG_MODE_ON)
++		spin_lock_irqsave(&sc->sc_serial_rw, flags);
++
++	val = ioread32(sc->mem + reg_offset);
++	val &= ~clr;
++	val |= set;
++	iowrite32(val, sc->mem + reg_offset);
++
++	if (ah->config.serialize_regmode == SER_REG_MODE_ON)
++		spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
++
++	return val;
++}
++
+ /**************************/
+ /*     Initialization     */
+ /**************************/
+@@ -548,6 +570,7 @@ static int ath9k_init_softc(u16 devid, s
+ 	ah->hw_version.subsysid = subsysid;
+ 	ah->reg_ops.read = ath9k_ioread32;
+ 	ah->reg_ops.write = ath9k_iowrite32;
++	ah->reg_ops.rmw = ath9k_reg_rmw;
+ 	sc->sc_ah = ah;
+ 
+ 	if (!pdata) {
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -73,6 +73,9 @@
+ #define REG_READ_MULTI(_ah, _addr, _val, _cnt)		\
+ 	(_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt))
+ 
++#define REG_RMW(_ah, _reg, _set, _clr) \
++	(_ah)->reg_ops.rmw((_ah), (_reg), (_set), (_clr))
++
+ #define ENABLE_REGWRITE_BUFFER(_ah)					\
+ 	do {								\
+ 		if ((_ah)->reg_ops.enable_write_buffer)	\
+@@ -87,17 +90,14 @@
+ 
+ #define SM(_v, _f)  (((_v) << _f##_S) & _f)
+ #define MS(_v, _f)  (((_v) & _f) >> _f##_S)
+-#define REG_RMW(_a, _r, _set, _clr)    \
+-	REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set))
+ #define REG_RMW_FIELD(_a, _r, _f, _v) \
+-	REG_WRITE(_a, _r, \
+-	(REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f))
++	REG_RMW(_a, _r, (((_v) << _f##_S) & _f), (_f))
+ #define REG_READ_FIELD(_a, _r, _f) \
+ 	(((REG_READ(_a, _r) & _f) >> _f##_S))
+ #define REG_SET_BIT(_a, _r, _f) \
+-	REG_WRITE(_a, _r, REG_READ(_a, _r) | (_f))
++	REG_RMW(_a, _r, (_f), 0)
+ #define REG_CLR_BIT(_a, _r, _f) \
+-	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f))
++	REG_RMW(_a, _r, 0, (_f))
+ 
+ #define DO_DELAY(x) do {					\
+ 		if (((++(x) % 64) == 0) &&			\
diff --git a/package/mac80211/patches/562-ath9k_use_reg_rmw.patch b/package/mac80211/patches/562-ath9k_use_reg_rmw.patch
new file mode 100644
index 000000000..1400cf551
--- /dev/null
+++ b/package/mac80211/patches/562-ath9k_use_reg_rmw.patch
@@ -0,0 +1,274 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -684,14 +684,14 @@ static void ath9k_hw_init_qos(struct ath
+ 
+ unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
+ {
+-		REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) & ~(PLL3_DO_MEAS_MASK)));
+-		udelay(100);
+-		REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) | PLL3_DO_MEAS_MASK));
++	REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
++	udelay(100);
++	REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
+ 
+-		while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0)
+-			udelay(100);
++	while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0)
++		udelay(100);
+ 
+-		return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3;
++	return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3;
+ }
+ EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc);
+ 
+@@ -841,8 +841,7 @@ void ath9k_hw_init_global_settings(struc
+ 		ah->misc_mode);
+ 
+ 	if (ah->misc_mode != 0)
+-		REG_WRITE(ah, AR_PCU_MISC,
+-			  REG_READ(ah, AR_PCU_MISC) | ah->misc_mode);
++		REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
+ 
+ 	if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
+ 		sifstime = 16;
+@@ -910,23 +909,19 @@ u32 ath9k_regd_get_ctl(struct ath_regula
+ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
+ {
+ 	struct ath_common *common = ath9k_hw_common(ah);
+-	u32 regval;
+ 
+ 	ENABLE_REGWRITE_BUFFER(ah);
+ 
+ 	/*
+ 	 * set AHB_MODE not to do cacheline prefetches
+ 	*/
+-	if (!AR_SREV_9300_20_OR_LATER(ah)) {
+-		regval = REG_READ(ah, AR_AHB_MODE);
+-		REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
+-	}
++	if (!AR_SREV_9300_20_OR_LATER(ah))
++		REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN);
+ 
+ 	/*
+ 	 * let mac dma reads be in 128 byte chunks
+ 	 */
+-	regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
+-	REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
++	REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK);
+ 
+ 	REGWRITE_BUFFER_FLUSH(ah);
+ 
+@@ -943,8 +938,7 @@ static inline void ath9k_hw_set_dma(stru
+ 	/*
+ 	 * let mac dma writes be in 128 byte chunks
+ 	 */
+-	regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
+-	REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
++	REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK);
+ 
+ 	/*
+ 	 * Setup receive FIFO threshold to hold off TX activities
+@@ -983,30 +977,27 @@ static inline void ath9k_hw_set_dma(stru
+ 
+ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
+ {
+-	u32 val;
++	u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC;
++	u32 set = AR_STA_ID1_KSRCH_MODE;
+ 
+-	val = REG_READ(ah, AR_STA_ID1);
+-	val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
+ 	switch (opmode) {
+-	case NL80211_IFTYPE_AP:
+-		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
+-			  | AR_STA_ID1_KSRCH_MODE);
+-		REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+-		break;
+ 	case NL80211_IFTYPE_ADHOC:
+ 	case NL80211_IFTYPE_MESH_POINT:
+-		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
+-			  | AR_STA_ID1_KSRCH_MODE);
++		set |= AR_STA_ID1_ADHOC;
+ 		REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+ 		break;
++	case NL80211_IFTYPE_AP:
++		set |= AR_STA_ID1_STA_AP;
++		/* fall through */
+ 	case NL80211_IFTYPE_STATION:
+-		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
++		REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+ 		break;
+ 	default:
+-		if (ah->is_monitoring)
+-			REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
++		if (!ah->is_monitoring)
++			set = 0;
+ 		break;
+ 	}
++	REG_RMW(ah, AR_STA_ID1, set, mask);
+ }
+ 
+ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+@@ -1032,10 +1023,8 @@ static bool ath9k_hw_set_reset(struct at
+ 	u32 tmpReg;
+ 
+ 	if (AR_SREV_9100(ah)) {
+-		u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK);
+-		val &= ~AR_RTC_DERIVED_CLK_PERIOD;
+-		val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD);
+-		REG_WRITE(ah, AR_RTC_DERIVED_CLK, val);
++		REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK,
++			      AR_RTC_DERIVED_CLK_PERIOD, 1);
+ 		(void)REG_READ(ah, AR_RTC_DERIVED_CLK);
+ 	}
+ 
+@@ -1460,8 +1449,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ 		ar9002_hw_enable_wep_aggregation(ah);
+ 	}
+ 
+-	REG_WRITE(ah, AR_STA_ID1,
+-		  REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
++	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
+ 
+ 	ath9k_hw_set_dma(ah);
+ 
+@@ -2213,11 +2201,9 @@ void ath9k_hw_setrxfilter(struct ath_hw 
+ 	REG_WRITE(ah, AR_PHY_ERR, phybits);
+ 
+ 	if (phybits)
+-		REG_WRITE(ah, AR_RXCFG,
+-			  REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
++		REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA);
+ 	else
+-		REG_WRITE(ah, AR_RXCFG,
+-			  REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
++		REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA);
+ 
+ 	REGWRITE_BUFFER_FLUSH(ah);
+ }
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -465,10 +465,9 @@ bool ath9k_hw_resettxqueue(struct ath_hw
+ 		REG_WRITE(ah, AR_QCBRCFG(q),
+ 			  SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
+ 			  SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
+-		REG_WRITE(ah, AR_QMISC(q),
+-			  REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
+-			  (qi->tqi_cbrOverflowLimit ?
+-			   AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
++		REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR |
++			    (qi->tqi_cbrOverflowLimit ?
++			     AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
+ 	}
+ 	if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
+ 		REG_WRITE(ah, AR_QRDYTIMECFG(q),
+@@ -481,40 +480,31 @@ bool ath9k_hw_resettxqueue(struct ath_hw
+ 		  (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
+ 
+ 	if (qi->tqi_burstTime
+-	    && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
+-		REG_WRITE(ah, AR_QMISC(q),
+-			  REG_READ(ah, AR_QMISC(q)) |
+-			  AR_Q_MISC_RDYTIME_EXP_POLICY);
++	    && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE))
++		REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY);
+ 
+-	}
+-
+-	if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
+-		REG_WRITE(ah, AR_DMISC(q),
+-			  REG_READ(ah, AR_DMISC(q)) |
+-			  AR_D_MISC_POST_FR_BKOFF_DIS);
+-	}
++	if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE)
++		REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
+ 
+ 	REGWRITE_BUFFER_FLUSH(ah);
+ 
+-	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
+-		REG_WRITE(ah, AR_DMISC(q),
+-			  REG_READ(ah, AR_DMISC(q)) |
+-			  AR_D_MISC_FRAG_BKOFF_EN);
+-	}
++	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
++		REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN);
++
+ 	switch (qi->tqi_type) {
+ 	case ATH9K_TX_QUEUE_BEACON:
+ 		ENABLE_REGWRITE_BUFFER(ah);
+ 
+-		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
+-			  | AR_Q_MISC_FSP_DBA_GATED
+-			  | AR_Q_MISC_BEACON_USE
+-			  | AR_Q_MISC_CBR_INCR_DIS1);
++		REG_SET_BIT(ah, AR_QMISC(q),
++			    AR_Q_MISC_FSP_DBA_GATED
++			    | AR_Q_MISC_BEACON_USE
++			    | AR_Q_MISC_CBR_INCR_DIS1);
+ 
+-		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
+-			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
++		REG_SET_BIT(ah, AR_DMISC(q),
++			    (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+ 			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
+-			  | AR_D_MISC_BEACON_USE
+-			  | AR_D_MISC_POST_FR_BKOFF_DIS);
++			    | AR_D_MISC_BEACON_USE
++			    | AR_D_MISC_POST_FR_BKOFF_DIS);
+ 
+ 		REGWRITE_BUFFER_FLUSH(ah);
+ 
+@@ -533,41 +523,38 @@ bool ath9k_hw_resettxqueue(struct ath_hw
+ 	case ATH9K_TX_QUEUE_CAB:
+ 		ENABLE_REGWRITE_BUFFER(ah);
+ 
+-		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
+-			  | AR_Q_MISC_FSP_DBA_GATED
+-			  | AR_Q_MISC_CBR_INCR_DIS1
+-			  | AR_Q_MISC_CBR_INCR_DIS0);
++		REG_SET_BIT(ah, AR_QMISC(q),
++			    AR_Q_MISC_FSP_DBA_GATED
++			    | AR_Q_MISC_CBR_INCR_DIS1
++			    | AR_Q_MISC_CBR_INCR_DIS0);
+ 		value = (qi->tqi_readyTime -
+ 			 (ah->config.sw_beacon_response_time -
+ 			  ah->config.dma_beacon_response_time) -
+ 			 ah->config.additional_swba_backoff) * 1024;
+ 		REG_WRITE(ah, AR_QRDYTIMECFG(q),
+ 			  value | AR_Q_RDYTIMECFG_EN);
+-		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
+-			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
++		REG_SET_BIT(ah, AR_DMISC(q),
++			    (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+ 			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
+ 
+ 		REGWRITE_BUFFER_FLUSH(ah);
+ 
+ 		break;
+ 	case ATH9K_TX_QUEUE_PSPOLL:
+-		REG_WRITE(ah, AR_QMISC(q),
+-			  REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
++		REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_CBR_INCR_DIS1);
+ 		break;
+ 	case ATH9K_TX_QUEUE_UAPSD:
+-		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
+-			  AR_D_MISC_POST_FR_BKOFF_DIS);
++		REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ 
+ 	if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
+-		REG_WRITE(ah, AR_DMISC(q),
+-			  REG_READ(ah, AR_DMISC(q)) |
+-			  SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+-			     AR_D_MISC_ARB_LOCKOUT_CNTRL) |
+-			  AR_D_MISC_POST_FR_BKOFF_DIS);
++		REG_SET_BIT(ah, AR_DMISC(q),
++			    SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
++			       AR_D_MISC_ARB_LOCKOUT_CNTRL) |
++			    AR_D_MISC_POST_FR_BKOFF_DIS);
+ 	}
+ 
+ 	if (AR_SREV_9300_20_OR_LATER(ah))
diff --git a/package/mac80211/patches/563-ath9k_reg_write_array_func.patch b/package/mac80211/patches/563-ath9k_reg_write_array_func.patch
new file mode 100644
index 000000000..1f627e37b
--- /dev/null
+++ b/package/mac80211/patches/563-ath9k_reg_write_array_func.patch
@@ -0,0 +1,150 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -131,6 +131,20 @@ bool ath9k_hw_wait(struct ath_hw *ah, u3
+ }
+ EXPORT_SYMBOL(ath9k_hw_wait);
+ 
++void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
++			  int column, unsigned int *writecnt)
++{
++	int r;
++
++	ENABLE_REGWRITE_BUFFER(ah);
++	for (r = 0; r < array->ia_rows; r++) {
++		REG_WRITE(ah, INI_RA(array, r, 0),
++			  INI_RA(array, r, column));
++		DO_DELAY(*writecnt);
++	}
++	REGWRITE_BUFFER_FLUSH(ah);
++}
++
+ u32 ath9k_hw_reverse_bits(u32 val, u32 n)
+ {
+ 	u32 retval;
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -106,16 +106,8 @@
+ 			udelay(1);				\
+ 	} while (0)
+ 
+-#define REG_WRITE_ARRAY(iniarray, column, regWr) do {                   \
+-		int r;							\
+-		ENABLE_REGWRITE_BUFFER(ah);				\
+-		for (r = 0; r < ((iniarray)->ia_rows); r++) {		\
+-			REG_WRITE(ah, INI_RA((iniarray), (r), 0),	\
+-				  INI_RA((iniarray), r, (column)));	\
+-			DO_DELAY(regWr);				\
+-		}							\
+-		REGWRITE_BUFFER_FLUSH(ah);				\
+-	} while (0)
++#define REG_WRITE_ARRAY(iniarray, column, regWr) \
++	ath9k_hw_write_array(ah, iniarray, column, &(regWr))
+ 
+ #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
+ #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
+@@ -915,6 +907,8 @@ void ath9k_hw_antdiv_comb_conf_set(struc
+ 
+ /* General Operation */
+ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
++void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
++			  int column, unsigned int *writecnt);
+ u32 ath9k_hw_reverse_bits(u32 val, u32 n);
+ bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high);
+ u16 ath9k_hw_computetxtime(struct ath_hw *ah,
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -44,6 +44,34 @@ static const int m1ThreshExt_off = 127;
+ static const int m2ThreshExt_off = 127;
+ 
+ 
++static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array,
++				 int col)
++{
++	int i;
++
++	for (i = 0; i < array->ia_rows; i++)
++		bank[i] = INI_RA(array, i, col);
++}
++
++
++#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \
++	ar5008_write_rf_array(ah, iniarray, regData, &(regWr))
++
++static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array,
++				  u32 *data, unsigned int *writecnt)
++{
++	int r;
++
++	ENABLE_REGWRITE_BUFFER(ah);
++
++	for (r = 0; r < array->ia_rows; r++) {
++		REG_WRITE(ah, INI_RA(array, r, 0), data[r]);
++		DO_DELAY(*writecnt);
++	}
++
++	REGWRITE_BUFFER_FLUSH(ah);
++}
++
+ /**
+  * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters
+  * @rfbuf:
+@@ -530,16 +558,16 @@ static bool ar5008_hw_set_rf_regs(struct
+ 	eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
+ 
+ 	/* Setup Bank 0 Write */
+-	RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1);
++	ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1);
+ 
+ 	/* Setup Bank 1 Write */
+-	RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1);
++	ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1);
+ 
+ 	/* Setup Bank 2 Write */
+-	RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1);
++	ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1);
+ 
+ 	/* Setup Bank 6 Write */
+-	RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3,
++	ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3,
+ 		      modesIndex);
+ 	{
+ 		int i;
+@@ -569,7 +597,7 @@ static bool ar5008_hw_set_rf_regs(struct
+ 	}
+ 
+ 	/* Setup Bank 7 Setup */
+-	RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1);
++	ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1);
+ 
+ 	/* Write Analog registers */
+ 	REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
+--- a/drivers/net/wireless/ath/ath9k/phy.h
++++ b/drivers/net/wireless/ath/ath9k/phy.h
+@@ -38,27 +38,11 @@
+ #define AR_PHY_CLC_Q0        0x0000ffd0
+ #define AR_PHY_CLC_Q0_S      5
+ 
+-#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do {               \
+-		int r;							\
+-		ENABLE_REGWRITE_BUFFER(ah);				\
+-		for (r = 0; r < ((iniarray)->ia_rows); r++) {		\
+-			REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \
+-			DO_DELAY(regWr);				\
+-		}							\
+-		REGWRITE_BUFFER_FLUSH(ah);				\
+-	} while (0)
+-
+ #define ANTSWAP_AB 0x0001
+ #define REDUCE_CHAIN_0 0x00000050
+ #define REDUCE_CHAIN_1 0x00000051
+ #define AR_PHY_CHIP_ID 0x9818
+ 
+-#define RF_BANK_SETUP(_bank, _iniarray, _col) do {			\
+-		int i;							\
+-		for (i = 0; i < (_iniarray)->ia_rows; i++)		\
+-			(_bank)[i] = INI_RA((_iniarray), i, _col);;	\
+-	} while (0)
+-
+ #define	AR_PHY_TIMING11_SPUR_FREQ_SD		0x3FF00000
+ #define	AR_PHY_TIMING11_SPUR_FREQ_SD_S		20
+ 
diff --git a/package/mac80211/patches/564-ath9k_remove_total_queues_cap.patch b/package/mac80211/patches/564-ath9k_remove_total_queues_cap.patch
new file mode 100644
index 000000000..0907f68a0
--- /dev/null
+++ b/package/mac80211/patches/564-ath9k_remove_total_queues_cap.patch
@@ -0,0 +1,137 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1446,7 +1446,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ 	REGWRITE_BUFFER_FLUSH(ah);
+ 
+ 	ah->intr_txqs = 0;
+-	for (i = 0; i < ah->caps.total_queues; i++)
++	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ 		ath9k_hw_resettxqueue(ah, i);
+ 
+ 	ath9k_hw_init_interrupt_masks(ah, ah->opmode);
+@@ -1894,12 +1894,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+ 	else
+ 		pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+ 
+-	if (capField & AR_EEPROM_EEPCAP_MAXQCU)
+-		pCap->total_queues =
+-			MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
+-	else
+-		pCap->total_queues = ATH9K_NUM_TX_QUEUES;
+-
+ 	if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
+ 		pCap->keycache_size =
+ 			1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -191,7 +191,6 @@ enum ath9k_hw_caps {
+ 
+ struct ath9k_hw_capabilities {
+ 	u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
+-	u16 total_queues;
+ 	u16 keycache_size;
+ 	u16 low_5ghz_chan, high_5ghz_chan;
+ 	u16 low_2ghz_chan, high_2ghz_chan;
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -209,15 +209,8 @@ bool ath9k_hw_set_txq_props(struct ath_h
+ {
+ 	u32 cw;
+ 	struct ath_common *common = ath9k_hw_common(ah);
+-	struct ath9k_hw_capabilities *pCap = &ah->caps;
+ 	struct ath9k_tx_queue_info *qi;
+ 
+-	if (q >= pCap->total_queues) {
+-		ath_dbg(common, ATH_DBG_QUEUE,
+-			"Set TXQ properties, invalid queue: %u\n", q);
+-		return false;
+-	}
+-
+ 	qi = &ah->txq[q];
+ 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ 		ath_dbg(common, ATH_DBG_QUEUE,
+@@ -280,15 +273,8 @@ bool ath9k_hw_get_txq_props(struct ath_h
+ 			    struct ath9k_tx_queue_info *qinfo)
+ {
+ 	struct ath_common *common = ath9k_hw_common(ah);
+-	struct ath9k_hw_capabilities *pCap = &ah->caps;
+ 	struct ath9k_tx_queue_info *qi;
+ 
+-	if (q >= pCap->total_queues) {
+-		ath_dbg(common, ATH_DBG_QUEUE,
+-			"Get TXQ properties, invalid queue: %u\n", q);
+-		return false;
+-	}
+-
+ 	qi = &ah->txq[q];
+ 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ 		ath_dbg(common, ATH_DBG_QUEUE,
+@@ -320,28 +306,27 @@ int ath9k_hw_setuptxqueue(struct ath_hw 
+ {
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	struct ath9k_tx_queue_info *qi;
+-	struct ath9k_hw_capabilities *pCap = &ah->caps;
+ 	int q;
+ 
+ 	switch (type) {
+ 	case ATH9K_TX_QUEUE_BEACON:
+-		q = pCap->total_queues - 1;
++		q = ATH9K_NUM_TX_QUEUES - 1;
+ 		break;
+ 	case ATH9K_TX_QUEUE_CAB:
+-		q = pCap->total_queues - 2;
++		q = ATH9K_NUM_TX_QUEUES - 2;
+ 		break;
+ 	case ATH9K_TX_QUEUE_PSPOLL:
+ 		q = 1;
+ 		break;
+ 	case ATH9K_TX_QUEUE_UAPSD:
+-		q = pCap->total_queues - 3;
++		q = ATH9K_NUM_TX_QUEUES - 3;
+ 		break;
+ 	case ATH9K_TX_QUEUE_DATA:
+-		for (q = 0; q < pCap->total_queues; q++)
++		for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
+ 			if (ah->txq[q].tqi_type ==
+ 			    ATH9K_TX_QUEUE_INACTIVE)
+ 				break;
+-		if (q == pCap->total_queues) {
++		if (q == ATH9K_NUM_TX_QUEUES) {
+ 			ath_err(common, "No available TX queue\n");
+ 			return -1;
+ 		}
+@@ -382,15 +367,9 @@ EXPORT_SYMBOL(ath9k_hw_setuptxqueue);
+ 
+ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
+ {
+-	struct ath9k_hw_capabilities *pCap = &ah->caps;
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	struct ath9k_tx_queue_info *qi;
+ 
+-	if (q >= pCap->total_queues) {
+-		ath_dbg(common, ATH_DBG_QUEUE,
+-			"Release TXQ, invalid queue: %u\n", q);
+-		return false;
+-	}
+ 	qi = &ah->txq[q];
+ 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ 		ath_dbg(common, ATH_DBG_QUEUE,
+@@ -414,18 +393,11 @@ EXPORT_SYMBOL(ath9k_hw_releasetxqueue);
+ 
+ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
+ {
+-	struct ath9k_hw_capabilities *pCap = &ah->caps;
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	struct ath9k_channel *chan = ah->curchan;
+ 	struct ath9k_tx_queue_info *qi;
+ 	u32 cwMin, chanCwMin, value;
+ 
+-	if (q >= pCap->total_queues) {
+-		ath_dbg(common, ATH_DBG_QUEUE,
+-			"Reset TXQ, invalid queue: %u\n", q);
+-		return false;
+-	}
+-
+ 	qi = &ah->txq[q];
+ 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ 		ath_dbg(common, ATH_DBG_QUEUE,
diff --git a/package/mac80211/patches/565-ath9k_remove_ht_config.patch b/package/mac80211/patches/565-ath9k_remove_ht_config.patch
new file mode 100644
index 000000000..f211c6881
--- /dev/null
+++ b/package/mac80211/patches/565-ath9k_remove_ht_config.patch
@@ -0,0 +1,33 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -379,11 +379,6 @@ static void ath9k_hw_init_config(struct 
+ 		ah->config.spurchans[i][1] = AR_NO_SPUR;
+ 	}
+ 
+-	if (ah->hw_version.devid != AR2427_DEVID_PCIE)
+-		ah->config.ht_enable = 1;
+-	else
+-		ah->config.ht_enable = 0;
+-
+ 	/* PAPRD needs some more work to be enabled */
+ 	ah->config.paprd_disable = 1;
+ 
+@@ -1889,7 +1884,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+ 
+ 	common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
+ 
+-	if (ah->config.ht_enable)
++	if (ah->hw_version.devid != AR2427_DEVID_PCIE)
+ 		pCap->hw_caps |= ATH9K_HW_CAP_HT;
+ 	else
+ 		pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -222,7 +222,6 @@ struct ath9k_ops_config {
+ 	u8 pcie_clock_req;
+ 	u32 pcie_waen;
+ 	u8 analog_shiftreg;
+-	u8 ht_enable;
+ 	u8 paprd_disable;
+ 	u32 ofdm_trig_low;
+ 	u32 ofdm_trig_high;
diff --git a/package/mac80211/patches/566-ath9k_remove_regcap.patch b/package/mac80211/patches/566-ath9k_remove_regcap.patch
new file mode 100644
index 000000000..4ba631632
--- /dev/null
+++ b/package/mac80211/patches/566-ath9k_remove_regcap.patch
@@ -0,0 +1,36 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1941,23 +1941,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+ 	else
+ 		pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
+ 
+-	if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) {
+-		pCap->reg_cap =
+-			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+-			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
+-			AR_EEPROM_EEREGCAP_EN_KK_U2 |
+-			AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
+-	} else {
+-		pCap->reg_cap =
+-			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+-			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
+-	}
+-
+-	/* Advertise midband for AR5416 with FCC midband set in eeprom */
+-	if (regulatory->current_rd_ext & (1 << REG_EXT_FCC_MIDBAND) &&
+-	    AR_SREV_5416(ah))
+-		pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
+-
+ 	if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) {
+ 		btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO;
+ 		btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -200,7 +200,6 @@ struct ath9k_hw_capabilities {
+ 	u8 max_txchains;
+ 	u8 max_rxchains;
+ 	u16 tx_triglevel_max;
+-	u16 reg_cap;
+ 	u8 num_gpio_pins;
+ 	u8 rx_hp_qdepth;
+ 	u8 rx_lp_qdepth;
diff --git a/package/mac80211/patches/567-ath9k_remove_keycache_size.patch b/package/mac80211/patches/567-ath9k_remove_keycache_size.patch
new file mode 100644
index 000000000..399afec4d
--- /dev/null
+++ b/package/mac80211/patches/567-ath9k_remove_keycache_size.patch
@@ -0,0 +1,59 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -407,13 +407,7 @@ void ath9k_init_crypto(struct ath_softc 
+ 	int i = 0;
+ 
+ 	/* Get the hardware key cache size. */
+-	common->keymax = sc->sc_ah->caps.keycache_size;
+-	if (common->keymax > ATH_KEYMAX) {
+-		ath_dbg(common, ATH_DBG_ANY,
+-			"Warning, using only %u entries in %u key cache\n",
+-			ATH_KEYMAX, common->keymax);
+-		common->keymax = ATH_KEYMAX;
+-	}
++	common->keymax = AR_KEYTABLE_SIZE;
+ 
+ 	/*
+ 	 * Reset the key cache since some parts do not
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -564,13 +564,7 @@ static void ath9k_init_crypto(struct ath
+ 	int i = 0;
+ 
+ 	/* Get the hardware key cache size. */
+-	common->keymax = priv->ah->caps.keycache_size;
+-	if (common->keymax > ATH_KEYMAX) {
+-		ath_dbg(common, ATH_DBG_ANY,
+-			"Warning, using only %u entries in %u key cache\n",
+-			ATH_KEYMAX, common->keymax);
+-		common->keymax = ATH_KEYMAX;
+-	}
++	common->keymax = AR_KEYTABLE_SIZE;
+ 
+ 	if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+ 		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1889,12 +1889,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+ 	else
+ 		pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+ 
+-	if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
+-		pCap->keycache_size =
+-			1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
+-	else
+-		pCap->keycache_size = AR_KEYTABLE_SIZE;
+-
+ 	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+ 		pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1;
+ 	else
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -191,7 +191,6 @@ enum ath9k_hw_caps {
+ 
+ struct ath9k_hw_capabilities {
+ 	u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
+-	u16 keycache_size;
+ 	u16 low_5ghz_chan, high_5ghz_chan;
+ 	u16 low_2ghz_chan, high_2ghz_chan;
+ 	u16 rts_aggr_limit;
diff --git a/package/mac80211/patches/568-ath9k_remove_enhancedpm.patch b/package/mac80211/patches/568-ath9k_remove_enhancedpm.patch
new file mode 100644
index 000000000..97921c22f
--- /dev/null
+++ b/package/mac80211/patches/568-ath9k_remove_enhancedpm.patch
@@ -0,0 +1,21 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1912,8 +1912,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+ 		pCap->rts_aggr_limit = (8 * 1024);
+ 	}
+ 
+-	pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
+-
+ #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+ 	ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
+ 	if (ah->rfsilent & EEP_RFSILENT_ENABLED) {
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -174,7 +174,6 @@ enum ath9k_hw_caps {
+ 	ATH9K_HW_CAP_HT                         = BIT(0),
+ 	ATH9K_HW_CAP_RFSILENT                   = BIT(1),
+ 	ATH9K_HW_CAP_CST                        = BIT(2),
+-	ATH9K_HW_CAP_ENHANCEDPM                 = BIT(3),
+ 	ATH9K_HW_CAP_AUTOSLEEP                  = BIT(4),
+ 	ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(5),
+ 	ATH9K_HW_CAP_EDMA			= BIT(6),
diff --git a/package/mac80211/patches/569-ath9k_remove_tx_triglevel_max.patch b/package/mac80211/patches/569-ath9k_remove_tx_triglevel_max.patch
new file mode 100644
index 000000000..6e41cb59c
--- /dev/null
+++ b/package/mac80211/patches/569-ath9k_remove_tx_triglevel_max.patch
@@ -0,0 +1,35 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -197,7 +197,6 @@ struct ath9k_hw_capabilities {
+ 	u8 rx_chainmask;
+ 	u8 max_txchains;
+ 	u8 max_rxchains;
+-	u16 tx_triglevel_max;
+ 	u8 num_gpio_pins;
+ 	u8 rx_hp_qdepth;
+ 	u8 rx_lp_qdepth;
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -2059,7 +2059,7 @@ static void ath_tx_rc_status(struct ath_
+ 		if (ieee80211_is_data(hdr->frame_control) &&
+ 		    (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
+ 		                     ATH9K_TX_DELIM_UNDERRUN)) &&
+-		    ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max)
++		    ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
+ 			tx_info->status.rates[tx_rateindex].count =
+ 				hw->max_rate_tries;
+ 	}
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1889,11 +1889,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+ 	else
+ 		pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+ 
+-	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+-		pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1;
+-	else
+-		pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
+-
+ 	if (AR_SREV_9271(ah))
+ 		pCap->num_gpio_pins = AR9271_NUM_GPIO;
+ 	else if (AR_DEVID_7010(ah))
-- 
cgit v1.2.3