aboutsummaryrefslogtreecommitdiffstats
path: root/package/mac80211
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-03-23 20:16:58 +0000
committerFelix Fietkau <nbd@openwrt.org>2011-03-23 20:16:58 +0000
commit4cbdad0e9d56858de05423d36da2495ea41fdf48 (patch)
tree3c38843928033f69ab8088918870f0f6df062151 /package/mac80211
parent80239ff7b0b6774a4192c786b3a85d03a4a1d0b1 (diff)
downloadupstream-4cbdad0e9d56858de05423d36da2495ea41fdf48.tar.gz
upstream-4cbdad0e9d56858de05423d36da2495ea41fdf48.tar.bz2
upstream-4cbdad0e9d56858de05423d36da2495ea41fdf48.zip
ath9k: add a few de-bloating and optimization patches
SVN-Revision: 26281
Diffstat (limited to 'package/mac80211')
-rw-r--r--package/mac80211/patches/560-ath9k_move_regops_struct.patch109
-rw-r--r--package/mac80211/patches/561-ath9k_optimize_reg_rmw.patch110
-rw-r--r--package/mac80211/patches/562-ath9k_use_reg_rmw.patch274
-rw-r--r--package/mac80211/patches/563-ath9k_reg_write_array_func.patch150
-rw-r--r--package/mac80211/patches/564-ath9k_remove_total_queues_cap.patch137
-rw-r--r--package/mac80211/patches/565-ath9k_remove_ht_config.patch33
-rw-r--r--package/mac80211/patches/566-ath9k_remove_regcap.patch36
-rw-r--r--package/mac80211/patches/567-ath9k_remove_keycache_size.patch59
-rw-r--r--package/mac80211/patches/568-ath9k_remove_enhancedpm.patch21
-rw-r--r--package/mac80211/patches/569-ath9k_remove_tx_triglevel_max.patch35
10 files changed, 964 insertions, 0 deletions
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 0000000000..8e52df4517
--- /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 0000000000..c2254e565c
--- /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 0000000000..1400cf5517
--- /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 0000000000..1f627e37bd
--- /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 0000000000..0907f68a02
--- /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 0000000000..f211c6881f
--- /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 0000000000..4ba631632b
--- /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 0000000000..399afec4d6
--- /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 0000000000..97921c22fe
--- /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 0000000000..6e41cb59c3
--- /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))