From 66a6f82ee3704c72b3c6ea268ac71eed883722a5 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Sun, 13 Mar 2011 18:38:37 +0000
Subject: mac80211: update to wireless-testing 2011-03-11

SVN-Revision: 26128
---
 .../patches/030-backport_93c86_eeprom.patch        |   6 +-
 .../mac80211/patches/050-fix_missing_include.patch |  10 -
 .../mac80211/patches/300-ath9k_gpio_settings.patch |   4 +-
 package/mac80211/patches/310-pending_work.patch    | 366 +++++++++++++++++++++
 .../401-ath9k-dont-register-leds-on-ar9100.patch   |  14 +-
 ...k-override-mac-address-from-platform-data.patch |   6 +-
 .../patches/409-ath9k_platform_settings.patch      |   8 +-
 .../patches/500-ath9k_eeprom_debugfs.patch         |   6 +-
 .../patches/510-ath9k_intr_mitigation_tweak.patch  |  13 +
 .../mac80211/patches/510-ath9k_led_cleanup.patch   | 303 -----------------
 .../patches/520-ath9k_intr_mitigation_tweak.patch  |  13 -
 .../patches/520-mac80211_drv_tim_override.patch    |  73 ++++
 .../patches/521-ath9k_fix_ap_ps_buffering.patch    | 311 +++++++++++++++++
 ...22-ath9k_remove_pending_frames_workaround.patch |  36 ++
 .../patches/530-mac80211_drv_tim_override.patch    |  73 ----
 .../530-mac80211_redirect_vlan_eap_frames.patch    |  67 ++++
 .../patches/531-ath9k_fix_ap_ps_buffering.patch    | 311 -----------------
 ...32-ath9k_remove_pending_frames_workaround.patch |  36 --
 .../patches/540-mac80211_add_rx_rate.patch         | 232 -------------
 .../550-ath9k_no_vif_promisc_handling.patch        |  13 -
 .../560-mac80211_minstrel_ht_sampling_fix.patch    |  50 ---
 .../patches/570-ath9k_fix_reg_bit_macros.patch     |  14 -
 .../mac80211/patches/571-ath9k_fix_dma_stop.patch  |  72 ----
 .../mac80211/patches/572-ath9k_fix_tx_flush.patch  | 141 --------
 .../mac80211/patches/573-ath9k_beacon_stop.patch   | 143 --------
 .../580-mac80211_redirect_vlan_eap_frames.patch    |  67 ----
 .../patches/581-mac80211_chantype_change_fix.patch |  12 -
 .../patches/590-ath9k_tid_cleanup_send_bar.patch   |  11 -
 .../700-mwl8k-missing-pci-id-for-WNR854T.patch     |   2 +-
 .../mac80211/patches/710-p54_rssi_crash_fix.patch  |  18 -
 .../720-mac80211-print-restart-warning.patch       |  14 -
 .../patches/721-mac80211-fix-scan-race.patch       | 141 --------
 32 files changed, 886 insertions(+), 1700 deletions(-)
 delete mode 100644 package/mac80211/patches/050-fix_missing_include.patch
 create mode 100644 package/mac80211/patches/310-pending_work.patch
 create mode 100644 package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
 delete mode 100644 package/mac80211/patches/510-ath9k_led_cleanup.patch
 delete mode 100644 package/mac80211/patches/520-ath9k_intr_mitigation_tweak.patch
 create mode 100644 package/mac80211/patches/520-mac80211_drv_tim_override.patch
 create mode 100644 package/mac80211/patches/521-ath9k_fix_ap_ps_buffering.patch
 create mode 100644 package/mac80211/patches/522-ath9k_remove_pending_frames_workaround.patch
 delete mode 100644 package/mac80211/patches/530-mac80211_drv_tim_override.patch
 create mode 100644 package/mac80211/patches/530-mac80211_redirect_vlan_eap_frames.patch
 delete mode 100644 package/mac80211/patches/531-ath9k_fix_ap_ps_buffering.patch
 delete mode 100644 package/mac80211/patches/532-ath9k_remove_pending_frames_workaround.patch
 delete mode 100644 package/mac80211/patches/540-mac80211_add_rx_rate.patch
 delete mode 100644 package/mac80211/patches/550-ath9k_no_vif_promisc_handling.patch
 delete mode 100644 package/mac80211/patches/560-mac80211_minstrel_ht_sampling_fix.patch
 delete mode 100644 package/mac80211/patches/570-ath9k_fix_reg_bit_macros.patch
 delete mode 100644 package/mac80211/patches/571-ath9k_fix_dma_stop.patch
 delete mode 100644 package/mac80211/patches/572-ath9k_fix_tx_flush.patch
 delete mode 100644 package/mac80211/patches/573-ath9k_beacon_stop.patch
 delete mode 100644 package/mac80211/patches/580-mac80211_redirect_vlan_eap_frames.patch
 delete mode 100644 package/mac80211/patches/581-mac80211_chantype_change_fix.patch
 delete mode 100644 package/mac80211/patches/590-ath9k_tid_cleanup_send_bar.patch
 delete mode 100644 package/mac80211/patches/710-p54_rssi_crash_fix.patch
 delete mode 100644 package/mac80211/patches/720-mac80211-print-restart-warning.patch
 delete mode 100644 package/mac80211/patches/721-mac80211-fix-scan-race.patch

(limited to 'package/mac80211/patches')

diff --git a/package/mac80211/patches/030-backport_93c86_eeprom.patch b/package/mac80211/patches/030-backport_93c86_eeprom.patch
index 0415e5f1fc..30ff85ed05 100644
--- a/package/mac80211/patches/030-backport_93c86_eeprom.patch
+++ b/package/mac80211/patches/030-backport_93c86_eeprom.patch
@@ -1,8 +1,8 @@
 --- a/include/linux/compat-2.6.36.h
 +++ b/include/linux/compat-2.6.36.h
-@@ -102,6 +102,8 @@ int no_printk(const char *s, ...) { retu
- #define alloc_workqueue(name, flags, max_active) __create_workqueue(name, flags, max_active, 0)
- #endif
+@@ -104,6 +104,8 @@ int no_printk(const char *s, ...) { retu
+ 
+ #define PCI_EEPROM_WIDTH_93C86   8
  
 +#define PCI_EEPROM_WIDTH_93C86   8
 +
diff --git a/package/mac80211/patches/050-fix_missing_include.patch b/package/mac80211/patches/050-fix_missing_include.patch
deleted file mode 100644
index 458ff4d864..0000000000
--- a/package/mac80211/patches/050-fix_missing_include.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/compat/compat-2.6.39.c
-+++ b/compat/compat-2.6.39.c
-@@ -10,6 +10,7 @@
- 
- #include <linux/compat.h>
- #include <linux/tty.h>
-+#include <linux/sched.h>
- 
- /*
-  *		Termios Helper Methods
diff --git a/package/mac80211/patches/300-ath9k_gpio_settings.patch b/package/mac80211/patches/300-ath9k_gpio_settings.patch
index e38b572e5a..af2057759e 100644
--- a/package/mac80211/patches/300-ath9k_gpio_settings.patch
+++ b/package/mac80211/patches/300-ath9k_gpio_settings.patch
@@ -1,7 +1,7 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1091,6 +1091,12 @@ int ath9k_init_debug(struct ath_hw *ah)
- 			sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca))
+@@ -1145,6 +1145,12 @@ int ath9k_init_debug(struct ath_hw *ah)
+ 			sc, &fops_regdump))
  		goto err;
  
 +	debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
diff --git a/package/mac80211/patches/310-pending_work.patch b/package/mac80211/patches/310-pending_work.patch
new file mode 100644
index 0000000000..57dcecaf10
--- /dev/null
+++ b/package/mac80211/patches/310-pending_work.patch
@@ -0,0 +1,366 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -189,7 +189,6 @@ struct ath_txq {
+ 	u32 axq_ampdu_depth;
+ 	bool stopped;
+ 	bool axq_tx_inprogress;
+-	bool txq_flush_inprogress;
+ 	struct list_head axq_acq;
+ 	struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
+ 	struct list_head txq_fifo_pending;
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -373,6 +373,7 @@ void ath_beacon_tasklet(unsigned long da
+ 			ath_dbg(common, ATH_DBG_BSTUCK,
+ 				"missed %u consecutive beacons\n",
+ 				sc->beacon.bmisscnt);
++			ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
+ 			ath9k_hw_bstuck_nfcal(ah);
+ 		} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
+ 			ath_dbg(common, ATH_DBG_BSTUCK,
+@@ -450,16 +451,6 @@ void ath_beacon_tasklet(unsigned long da
+ 		sc->beacon.updateslot = OK;
+ 	}
+ 	if (bfaddr != 0) {
+-		/*
+-		 * Stop any current dma and put the new frame(s) on the queue.
+-		 * This should never fail since we check above that no frames
+-		 * are still pending on the queue.
+-		 */
+-		if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
+-			ath_err(common, "beacon queue %u did not stop?\n",
+-				sc->beacon.beaconq);
+-		}
+-
+ 		/* NB: cabq traffic should already be queued and primed */
+ 		ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
+ 		ath9k_hw_txstart(ah, sc->beacon.beaconq);
+@@ -780,7 +771,7 @@ void ath9k_set_beaconing_status(struct a
+ 		ah->imask &= ~ATH9K_INT_SWBA;
+ 		ath9k_hw_set_interrupts(ah, ah->imask);
+ 		tasklet_kill(&sc->bcon_tasklet);
+-		ath9k_hw_stoptxdma(ah, sc->beacon.beaconq);
++		ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
+ 	}
+ 	ath9k_ps_restore(sc);
+ }
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -95,9 +95,9 @@
+ #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_WRITE(_a, _r, REG_READ(_a, _r) | (_f))
+ #define REG_CLR_BIT(_a, _r, _f) \
+-	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
++	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f))
+ 
+ #define DO_DELAY(x) do {			\
+ 		if ((++(x) % 64) == 0)          \
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -143,84 +143,59 @@ bool ath9k_hw_updatetxtriglevel(struct a
+ }
+ EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
+ 
+-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
++void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
+ {
+-#define ATH9K_TX_STOP_DMA_TIMEOUT	4000    /* usec */
+-#define ATH9K_TIME_QUANTUM		100     /* usec */
+-	struct ath_common *common = ath9k_hw_common(ah);
+-	struct ath9k_hw_capabilities *pCap = &ah->caps;
+-	struct ath9k_tx_queue_info *qi;
+-	u32 tsfLow, j, wait;
+-	u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
++	int i, q;
+ 
+-	if (q >= pCap->total_queues) {
+-		ath_dbg(common, ATH_DBG_QUEUE,
+-			"Stopping TX DMA, invalid queue: %u\n", q);
+-		return false;
+-	}
++	REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
+ 
+-	qi = &ah->txq[q];
+-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+-		ath_dbg(common, ATH_DBG_QUEUE,
+-			"Stopping TX DMA, inactive queue: %u\n", q);
+-		return false;
+-	}
++	REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
++	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
++	REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
+ 
+-	REG_WRITE(ah, AR_Q_TXD, 1 << q);
++	for (q = 0; q < AR_NUM_QCU; q++) {
++		for (i = 0; i < 1000; i++) {
++			if (i)
++				udelay(5);
+ 
+-	for (wait = wait_time; wait != 0; wait--) {
+-		if (ath9k_hw_numtxpending(ah, q) == 0)
+-			break;
+-		udelay(ATH9K_TIME_QUANTUM);
++			if (!ath9k_hw_numtxpending(ah, q))
++				break;
++		}
+ 	}
+ 
+-	if (ath9k_hw_numtxpending(ah, q)) {
+-		ath_dbg(common, ATH_DBG_QUEUE,
+-			"%s: Num of pending TX Frames %d on Q %d\n",
+-			__func__, ath9k_hw_numtxpending(ah, q), q);
+-
+-		for (j = 0; j < 2; j++) {
+-			tsfLow = REG_READ(ah, AR_TSF_L32);
+-			REG_WRITE(ah, AR_QUIET2,
+-				  SM(10, AR_QUIET2_QUIET_DUR));
+-			REG_WRITE(ah, AR_QUIET_PERIOD, 100);
+-			REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
+-			REG_SET_BIT(ah, AR_TIMER_MODE,
+-				       AR_QUIET_TIMER_EN);
+-
+-			if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
+-				break;
++	REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
++	REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
++	REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
+ 
+-			ath_dbg(common, ATH_DBG_QUEUE,
+-				"TSF has moved while trying to set quiet time TSF: 0x%08x\n",
+-				tsfLow);
+-		}
++	REG_WRITE(ah, AR_Q_TXD, 0);
++}
++EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
+ 
+-		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
++bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
++{
++#define ATH9K_TX_STOP_DMA_TIMEOUT	1000    /* usec */
++#define ATH9K_TIME_QUANTUM		100     /* usec */
++	int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
++	int wait;
+ 
+-		udelay(200);
+-		REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
++	REG_WRITE(ah, AR_Q_TXD, 1 << q);
+ 
+-		wait = wait_time;
+-		while (ath9k_hw_numtxpending(ah, q)) {
+-			if ((--wait) == 0) {
+-				ath_err(common,
+-					"Failed to stop TX DMA in 100 msec after killing last frame\n");
+-				break;
+-			}
++	for (wait = wait_time; wait != 0; wait--) {
++		if (wait != wait_time)
+ 			udelay(ATH9K_TIME_QUANTUM);
+-		}
+ 
+-		REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
++		if (ath9k_hw_numtxpending(ah, q) == 0)
++			break;
+ 	}
+ 
+ 	REG_WRITE(ah, AR_Q_TXD, 0);
++
+ 	return wait != 0;
+ 
+ #undef ATH9K_TX_STOP_DMA_TIMEOUT
+ #undef ATH9K_TIME_QUANTUM
+ }
+-EXPORT_SYMBOL(ath9k_hw_stoptxdma);
++EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
+ 
+ void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
+ {
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -676,7 +676,8 @@ void ath9k_hw_txstart(struct ath_hw *ah,
+ 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_stoptxdma(struct ath_hw *ah, u32 q);
++bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
++void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
+ void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
+ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
+ 			    const struct ath9k_tx_queue_info *qinfo);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -2128,56 +2128,42 @@ static void ath9k_set_coverage_class(str
+ 
+ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
+ {
+-#define ATH_FLUSH_TIMEOUT	60 /* ms */
+ 	struct ath_softc *sc = hw->priv;
+-	struct ath_txq *txq = NULL;
+-	struct ath_hw *ah = sc->sc_ah;
+-	struct ath_common *common = ath9k_hw_common(ah);
+-	int i, j, npend = 0;
++	int timeout = 200; /* ms */
++	int i, j;
+ 
++	ath9k_ps_wakeup(sc);
+ 	mutex_lock(&sc->mutex);
+ 
+ 	cancel_delayed_work_sync(&sc->tx_complete_work);
+ 
+-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+-		if (!ATH_TXQ_SETUP(sc, i))
+-			continue;
+-		txq = &sc->tx.txq[i];
+-
+-		if (!drop) {
+-			for (j = 0; j < ATH_FLUSH_TIMEOUT; j++) {
+-				if (!ath9k_has_pending_frames(sc, txq))
+-					break;
+-				usleep_range(1000, 2000);
+-			}
+-		}
++	if (drop)
++		timeout = 1;
++
++	for (j = 0; j < timeout; j++) {
++		int npend = 0;
++
++		if (j)
++			usleep_range(1000, 2000);
+ 
+-		if (drop || ath9k_has_pending_frames(sc, txq)) {
+-			ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n",
+-				txq->axq_qnum);
+-			spin_lock_bh(&txq->axq_lock);
+-			txq->txq_flush_inprogress = true;
+-			spin_unlock_bh(&txq->axq_lock);
+-
+-			ath9k_ps_wakeup(sc);
+-			ath9k_hw_stoptxdma(ah, txq->axq_qnum);
+-			npend = ath9k_hw_numtxpending(ah, txq->axq_qnum);
+-			ath9k_ps_restore(sc);
+-			if (npend)
+-				break;
++		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
++			if (!ATH_TXQ_SETUP(sc, i))
++				continue;
+ 
+-			ath_draintxq(sc, txq, false);
+-			txq->txq_flush_inprogress = false;
++			npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
+ 		}
++
++		if (!npend)
++		    goto out;
+ 	}
+ 
+-	if (npend) {
++	if (!ath_drain_all_txq(sc, false))
+ 		ath_reset(sc, false);
+-		txq->txq_flush_inprogress = false;
+-	}
+ 
++out:
+ 	ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
+ 	mutex_unlock(&sc->mutex);
++	ath9k_ps_restore(sc);
+ }
+ 
+ struct ieee80211_ops ath9k_ops = {
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -166,7 +166,7 @@ static void ath_tx_flush_tid(struct ath_
+ 		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, 0);
++			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
+ 		} else {
+ 			ath_tx_send_normal(sc, txq, NULL, &bf_head);
+ 		}
+@@ -1194,16 +1194,14 @@ bool ath_drain_all_txq(struct ath_softc 
+ 	if (sc->sc_flags & SC_OP_INVALID)
+ 		return true;
+ 
+-	/* Stop beacon queue */
+-	ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
++	ath9k_hw_abort_tx_dma(ah);
+ 
+-	/* Stop data queues */
++	/* Check if any queue remains active */
+ 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+-		if (ATH_TXQ_SETUP(sc, i)) {
+-			txq = &sc->tx.txq[i];
+-			ath9k_hw_stoptxdma(ah, txq->axq_qnum);
+-			npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
+-		}
++		if (!ATH_TXQ_SETUP(sc, i))
++			continue;
++
++		npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
+ 	}
+ 
+ 	if (npend)
+@@ -2014,8 +2012,7 @@ static void ath_tx_processq(struct ath_s
+ 		spin_lock_bh(&txq->axq_lock);
+ 		if (list_empty(&txq->axq_q)) {
+ 			txq->axq_link = NULL;
+-			if (sc->sc_flags & SC_OP_TXAGGR &&
+-			    !txq->txq_flush_inprogress)
++			if (sc->sc_flags & SC_OP_TXAGGR)
+ 				ath_txq_schedule(sc, txq);
+ 			spin_unlock_bh(&txq->axq_lock);
+ 			break;
+@@ -2096,7 +2093,7 @@ static void ath_tx_processq(struct ath_s
+ 
+ 		spin_lock_bh(&txq->axq_lock);
+ 
+-		if (sc->sc_flags & SC_OP_TXAGGR && !txq->txq_flush_inprogress)
++		if (sc->sc_flags & SC_OP_TXAGGR)
+ 			ath_txq_schedule(sc, txq);
+ 		spin_unlock_bh(&txq->axq_lock);
+ 	}
+@@ -2267,18 +2264,17 @@ void ath_tx_edma_tasklet(struct ath_soft
+ 
+ 		spin_lock_bh(&txq->axq_lock);
+ 
+-		if (!txq->txq_flush_inprogress) {
+-			if (!list_empty(&txq->txq_fifo_pending)) {
+-				INIT_LIST_HEAD(&bf_head);
+-				bf = list_first_entry(&txq->txq_fifo_pending,
+-						      struct ath_buf, list);
+-				list_cut_position(&bf_head,
+-						  &txq->txq_fifo_pending,
+-						  &bf->bf_lastbf->list);
+-				ath_tx_txqaddbuf(sc, txq, &bf_head);
+-			} else if (sc->sc_flags & SC_OP_TXAGGR)
+-				ath_txq_schedule(sc, txq);
+-		}
++		if (!list_empty(&txq->txq_fifo_pending)) {
++			INIT_LIST_HEAD(&bf_head);
++			bf = list_first_entry(&txq->txq_fifo_pending,
++					      struct ath_buf, list);
++			list_cut_position(&bf_head,
++					  &txq->txq_fifo_pending,
++					  &bf->bf_lastbf->list);
++			ath_tx_txqaddbuf(sc, txq, &bf_head);
++		} else if (sc->sc_flags & SC_OP_TXAGGR)
++			ath_txq_schedule(sc, txq);
++
+ 		spin_unlock_bh(&txq->axq_lock);
+ 	}
+ }
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -77,6 +77,9 @@ bool ieee80211_set_channel_type(struct i
+ 		switch (tmp->vif.bss_conf.channel_type) {
+ 		case NL80211_CHAN_NO_HT:
+ 		case NL80211_CHAN_HT20:
++			if (superchan > tmp->vif.bss_conf.channel_type)
++				break;
++
+ 			superchan = tmp->vif.bss_conf.channel_type;
+ 			break;
+ 		case NL80211_CHAN_HT40PLUS:
diff --git a/package/mac80211/patches/401-ath9k-dont-register-leds-on-ar9100.patch b/package/mac80211/patches/401-ath9k-dont-register-leds-on-ar9100.patch
index 166c133a61..22299020a0 100644
--- a/package/mac80211/patches/401-ath9k-dont-register-leds-on-ar9100.patch
+++ b/package/mac80211/patches/401-ath9k-dont-register-leds-on-ar9100.patch
@@ -1,17 +1,7 @@
 --- a/drivers/net/wireless/ath/ath9k/gpio.c
 +++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -120,6 +120,9 @@ static void ath_unregister_led(struct at
- 
- void ath_deinit_leds(struct ath_softc *sc)
+@@ -41,6 +41,9 @@ void ath_init_leds(struct ath_softc *sc)
  {
-+	if (AR_SREV_9100(sc->sc_ah))
-+		return;
-+
- 	ath_unregister_led(&sc->assoc_led);
- 	sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
- 	ath_unregister_led(&sc->tx_led);
-@@ -133,6 +136,9 @@ void ath_init_leds(struct ath_softc *sc)
- 	char *trigger;
  	int ret;
  
 +	if (AR_SREV_9100(sc->sc_ah))
@@ -19,4 +9,4 @@
 +
  	if (AR_SREV_9287(sc->sc_ah))
  		sc->sc_ah->led_pin = ATH_LED_PIN_9287;
- 	else
+ 	else if (AR_SREV_9485(sc->sc_ah))
diff --git a/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch b/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch
index c92245641f..6326649fc2 100644
--- a/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch
+++ b/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch
@@ -18,7 +18,7 @@
  
  #include "ath9k.h"
  
-@@ -522,6 +523,7 @@ static void ath9k_init_misc(struct ath_s
+@@ -537,6 +538,7 @@ static void ath9k_init_misc(struct ath_s
  static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
  			    const struct ath_bus_ops *bus_ops)
  {
@@ -26,7 +26,7 @@
  	struct ath_hw *ah = NULL;
  	struct ath_common *common;
  	int ret = 0, i;
-@@ -536,7 +538,7 @@ static int ath9k_init_softc(u16 devid, s
+@@ -551,7 +553,7 @@ static int ath9k_init_softc(u16 devid, s
  	ah->hw_version.subsysid = subsysid;
  	sc->sc_ah = ah;
  
@@ -35,7 +35,7 @@
  		ah->ah_flags |= AH_USE_EEPROM;
  
  	common = ath9k_hw_common(ah);
-@@ -572,6 +574,9 @@ static int ath9k_init_softc(u16 devid, s
+@@ -587,6 +589,9 @@ static int ath9k_init_softc(u16 devid, s
  	if (ret)
  		goto err_hw;
  
diff --git a/package/mac80211/patches/409-ath9k_platform_settings.patch b/package/mac80211/patches/409-ath9k_platform_settings.patch
index 23a5887a1d..6ce43b6005 100644
--- a/package/mac80211/patches/409-ath9k_platform_settings.patch
+++ b/package/mac80211/patches/409-ath9k_platform_settings.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -538,8 +538,14 @@ static int ath9k_init_softc(u16 devid, s
+@@ -553,8 +553,14 @@ static int ath9k_init_softc(u16 devid, s
  	ah->hw_version.subsysid = subsysid;
  	sc->sc_ah = ah;
  
@@ -29,17 +29,21 @@
  
 --- a/drivers/net/wireless/ath/ath9k/gpio.c
 +++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -139,10 +139,12 @@ void ath_init_leds(struct ath_softc *sc)
+@@ -44,12 +44,14 @@ void ath_init_leds(struct ath_softc *sc)
  	if (AR_SREV_9100(sc->sc_ah))
  		return;
  
 -	if (AR_SREV_9287(sc->sc_ah))
 -		sc->sc_ah->led_pin = ATH_LED_PIN_9287;
+-	else if (AR_SREV_9485(sc->sc_ah))
+-		sc->sc_ah->led_pin = ATH_LED_PIN_9485;
 -	else
 -		sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
 +	if (sc->sc_ah->led_pin < 0) {
 +		if (AR_SREV_9287(sc->sc_ah))
 +			sc->sc_ah->led_pin = ATH_LED_PIN_9287;
++		else if (AR_SREV_9485(sc->sc_ah))
++			sc->sc_ah->led_pin = ATH_LED_PIN_9485;
 +		else
 +			sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
 +	}
diff --git a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
index 700cf70114..0bb7082ef5 100644
--- a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
+++ b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
@@ -1,7 +1,7 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1027,6 +1027,53 @@ static const struct file_operations fops
- 	.llseek = default_llseek,
+@@ -1077,6 +1077,53 @@ static const struct file_operations fops
+ 	.llseek = default_llseek,/* read accesses f_pos */
  };
  
 +static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
@@ -54,7 +54,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
  	struct ath_common *common = ath9k_hw_common(ah);
-@@ -1097,6 +1144,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1151,6 +1198,10 @@ 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);
  
diff --git a/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
new file mode 100644
index 0000000000..301af3c22b
--- /dev/null
+++ b/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
@@ -0,0 +1,13 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1466,8 +1466,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ 	REG_WRITE(ah, AR_OBS, 8);
+ 
+ 	if (ah->config.rx_intr_mitigation) {
+-		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
+-		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
++		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 250);
++		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 500);
+ 	}
+ 
+ 	if (ah->config.tx_intr_mitigation) {
diff --git a/package/mac80211/patches/510-ath9k_led_cleanup.patch b/package/mac80211/patches/510-ath9k_led_cleanup.patch
deleted file mode 100644
index 352bee15fd..0000000000
--- a/package/mac80211/patches/510-ath9k_led_cleanup.patch
+++ /dev/null
@@ -1,303 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -449,26 +449,20 @@ void ath9k_btcoex_timer_pause(struct ath
- 
- #define ATH_LED_PIN_DEF 		1
- #define ATH_LED_PIN_9287		8
--#define ATH_LED_ON_DURATION_IDLE	350	/* in msecs */
--#define ATH_LED_OFF_DURATION_IDLE	250	/* in msecs */
--
--enum ath_led_type {
--	ATH_LED_RADIO,
--	ATH_LED_ASSOC,
--	ATH_LED_TX,
--	ATH_LED_RX
--};
--
--struct ath_led {
--	struct ath_softc *sc;
--	struct led_classdev led_cdev;
--	enum ath_led_type led_type;
--	char name[32];
--	bool registered;
--};
- 
-+#ifdef CONFIG_MAC80211_LEDS
- void ath_init_leds(struct ath_softc *sc);
- void ath_deinit_leds(struct ath_softc *sc);
-+#else
-+static inline void ath_init_leds(struct ath_softc *sc)
-+{
-+}
-+
-+static inline void ath_deinit_leds(struct ath_softc *sc)
-+{
-+}
-+#endif
-+
- 
- /* Antenna diversity/combining */
- #define ATH_ANT_RX_CURRENT_SHIFT 4
-@@ -620,15 +614,11 @@ struct ath_softc {
- 	struct ath_beacon beacon;
- 	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
- 
--	struct ath_led radio_led;
--	struct ath_led assoc_led;
--	struct ath_led tx_led;
--	struct ath_led rx_led;
--	struct delayed_work ath_led_blink_work;
--	int led_on_duration;
--	int led_off_duration;
--	int led_on_cnt;
--	int led_off_cnt;
-+#ifdef CONFIG_MAC80211_LEDS
-+	bool led_registered;
-+	char led_name[32];
-+	struct led_classdev led_cdev;
-+#endif
- 
- 	struct ath9k_hw_cal_data caldata;
- 	int last_rssi;
---- a/drivers/net/wireless/ath/ath9k/gpio.c
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -20,120 +20,25 @@
- /*	 LED functions		*/
- /********************************/
- 
--static void ath_led_blink_work(struct work_struct *work)
--{
--	struct ath_softc *sc = container_of(work, struct ath_softc,
--					    ath_led_blink_work.work);
--
--	if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
--		return;
--
--	if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
--	    (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
--		ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
--	else
--		ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
--				  (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
--
--	ieee80211_queue_delayed_work(sc->hw,
--				     &sc->ath_led_blink_work,
--				     (sc->sc_flags & SC_OP_LED_ON) ?
--					msecs_to_jiffies(sc->led_off_duration) :
--					msecs_to_jiffies(sc->led_on_duration));
--
--	sc->led_on_duration = sc->led_on_cnt ?
--			max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
--			ATH_LED_ON_DURATION_IDLE;
--	sc->led_off_duration = sc->led_off_cnt ?
--			max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
--			ATH_LED_OFF_DURATION_IDLE;
--	sc->led_on_cnt = sc->led_off_cnt = 0;
--	if (sc->sc_flags & SC_OP_LED_ON)
--		sc->sc_flags &= ~SC_OP_LED_ON;
--	else
--		sc->sc_flags |= SC_OP_LED_ON;
--}
--
-+#ifdef CONFIG_MAC80211_LEDS
- static void ath_led_brightness(struct led_classdev *led_cdev,
- 			       enum led_brightness brightness)
- {
--	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
--	struct ath_softc *sc = led->sc;
--
--	switch (brightness) {
--	case LED_OFF:
--		if (led->led_type == ATH_LED_ASSOC ||
--		    led->led_type == ATH_LED_RADIO) {
--			ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
--				(led->led_type == ATH_LED_RADIO));
--			sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
--			if (led->led_type == ATH_LED_RADIO)
--				sc->sc_flags &= ~SC_OP_LED_ON;
--		} else {
--			sc->led_off_cnt++;
--		}
--		break;
--	case LED_FULL:
--		if (led->led_type == ATH_LED_ASSOC) {
--			sc->sc_flags |= SC_OP_LED_ASSOCIATED;
--			if (led_blink)
--				ieee80211_queue_delayed_work(sc->hw,
--						     &sc->ath_led_blink_work, 0);
--		} else if (led->led_type == ATH_LED_RADIO) {
--			ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
--			sc->sc_flags |= SC_OP_LED_ON;
--		} else {
--			sc->led_on_cnt++;
--		}
--		break;
--	default:
--		break;
--	}
--}
--
--static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
--			    char *trigger)
--{
--	int ret;
--
--	led->sc = sc;
--	led->led_cdev.name = led->name;
--	led->led_cdev.default_trigger = trigger;
--	led->led_cdev.brightness_set = ath_led_brightness;
--
--	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
--	if (ret)
--		ath_err(ath9k_hw_common(sc->sc_ah),
--			"Failed to register led:%s", led->name);
--	else
--		led->registered = 1;
--	return ret;
--}
--
--static void ath_unregister_led(struct ath_led *led)
--{
--	if (led->registered) {
--		led_classdev_unregister(&led->led_cdev);
--		led->registered = 0;
--	}
-+	struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
-+	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF));
- }
- 
- void ath_deinit_leds(struct ath_softc *sc)
- {
--	if (AR_SREV_9100(sc->sc_ah))
-+	if (!sc->led_registered)
- 		return;
- 
--	ath_unregister_led(&sc->assoc_led);
--	sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
--	ath_unregister_led(&sc->tx_led);
--	ath_unregister_led(&sc->rx_led);
--	ath_unregister_led(&sc->radio_led);
--	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
-+	ath_led_brightness(&sc->led_cdev, LED_OFF);
-+	led_classdev_unregister(&sc->led_cdev);
- }
- 
- void ath_init_leds(struct ath_softc *sc)
- {
--	char *trigger;
- 	int ret;
- 
- 	if (AR_SREV_9100(sc->sc_ah))
-@@ -152,48 +57,22 @@ void ath_init_leds(struct ath_softc *sc)
- 	/* LED off, active low */
- 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
- 
--	if (led_blink)
--		INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
-+	if (!led_blink)
-+		sc->led_cdev.default_trigger =
-+			ieee80211_get_radio_led_name(sc->hw);
-+
-+	snprintf(sc->led_name, sizeof(sc->led_name),
-+		"ath9k-%s", wiphy_name(sc->hw->wiphy));
-+	sc->led_cdev.name = sc->led_name;
-+	sc->led_cdev.brightness_set = ath_led_brightness;
-+
-+	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
-+	if (ret < 0)
-+		return;
- 
--	trigger = ieee80211_get_radio_led_name(sc->hw);
--	snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
--		"ath9k-%s::radio", wiphy_name(sc->hw->wiphy));
--	ret = ath_register_led(sc, &sc->radio_led, trigger);
--	sc->radio_led.led_type = ATH_LED_RADIO;
--	if (ret)
--		goto fail;
--
--	trigger = ieee80211_get_assoc_led_name(sc->hw);
--	snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
--		"ath9k-%s::assoc", wiphy_name(sc->hw->wiphy));
--	ret = ath_register_led(sc, &sc->assoc_led, trigger);
--	sc->assoc_led.led_type = ATH_LED_ASSOC;
--	if (ret)
--		goto fail;
--
--	trigger = ieee80211_get_tx_led_name(sc->hw);
--	snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
--		"ath9k-%s::tx", wiphy_name(sc->hw->wiphy));
--	ret = ath_register_led(sc, &sc->tx_led, trigger);
--	sc->tx_led.led_type = ATH_LED_TX;
--	if (ret)
--		goto fail;
--
--	trigger = ieee80211_get_rx_led_name(sc->hw);
--	snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
--		"ath9k-%s::rx", wiphy_name(sc->hw->wiphy));
--	ret = ath_register_led(sc, &sc->rx_led, trigger);
--	sc->rx_led.led_type = ATH_LED_RX;
--	if (ret)
--		goto fail;
--
--	return;
--
--fail:
--	if (led_blink)
--		cancel_delayed_work_sync(&sc->ath_led_blink_work);
--	ath_deinit_leds(sc);
-+	sc->led_registered = true;
- }
-+#endif
- 
- /*******************/
- /*	Rfkill	   */
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1216,9 +1216,6 @@ static void ath9k_stop(struct ieee80211_
- 
- 	mutex_lock(&sc->mutex);
- 
--	if (led_blink)
--		cancel_delayed_work_sync(&sc->ath_led_blink_work);
--
- 	cancel_delayed_work_sync(&sc->tx_complete_work);
- 	cancel_delayed_work_sync(&sc->hw_pll_work);
- 	cancel_work_sync(&sc->paprd_work);
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -141,6 +141,21 @@ static struct ieee80211_rate ath9k_legac
- 	RATE(540, 0x0c, 0),
- };
- 
-+#ifdef CONFIG_MAC80211_LEDS
-+static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = {
-+	{ .throughput = 0 * 1024, .blink_time = 334 },
-+	{ .throughput = 1 * 1024, .blink_time = 260 },
-+	{ .throughput = 5 * 1024, .blink_time = 220 },
-+	{ .throughput = 10 * 1024, .blink_time = 190 },
-+	{ .throughput = 20 * 1024, .blink_time = 170 },
-+	{ .throughput = 50 * 1024, .blink_time = 150 },
-+	{ .throughput = 70 * 1024, .blink_time = 130 },
-+	{ .throughput = 100 * 1024, .blink_time = 110 },
-+	{ .throughput = 200 * 1024, .blink_time = 80 },
-+	{ .throughput = 300 * 1024, .blink_time = 50 },
-+};
-+#endif
-+
- static void ath9k_deinit_softc(struct ath_softc *sc);
- 
- /*
-@@ -742,6 +757,13 @@ int ath9k_init_device(u16 devid, struct 
- 
- 	ath9k_init_txpower_limits(sc);
- 
-+#ifdef CONFIG_MAC80211_LEDS
-+	/* must be initialized before ieee80211_register_hw */
-+	sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
-+		IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
-+		ARRAY_SIZE(ath9k_tpt_blink));
-+#endif
-+
- 	/* Register with mac80211 */
- 	error = ieee80211_register_hw(hw);
- 	if (error)
diff --git a/package/mac80211/patches/520-ath9k_intr_mitigation_tweak.patch b/package/mac80211/patches/520-ath9k_intr_mitigation_tweak.patch
deleted file mode 100644
index 301af3c22b..0000000000
--- a/package/mac80211/patches/520-ath9k_intr_mitigation_tweak.patch
+++ /dev/null
@@ -1,13 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1466,8 +1466,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
- 	REG_WRITE(ah, AR_OBS, 8);
- 
- 	if (ah->config.rx_intr_mitigation) {
--		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
--		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
-+		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 250);
-+		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 500);
- 	}
- 
- 	if (ah->config.tx_intr_mitigation) {
diff --git a/package/mac80211/patches/520-mac80211_drv_tim_override.patch b/package/mac80211/patches/520-mac80211_drv_tim_override.patch
new file mode 100644
index 0000000000..535e35927e
--- /dev/null
+++ b/package/mac80211/patches/520-mac80211_drv_tim_override.patch
@@ -0,0 +1,73 @@
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -2216,6 +2216,18 @@ static inline int ieee80211_sta_ps_trans
+ #define IEEE80211_TX_STATUS_HEADROOM	13
+ 
+ /**
++ * ieee80211_sta_set_tim - set the TIM bit for a sleeping station
++ *
++ * If a driver buffers frames for a powersave station instead of passing
++ * them back to mac80211 for retransmission, the station needs to be told
++ * to wake up using the TIM bitmap in the beacon.
++ *
++ * This function sets the station's TIM bit - it will be cleared when the
++ * station wakes up.
++ */
++void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
++
++/**
+  * ieee80211_tx_status - transmit status callback
+  *
+  * Call this function for all transmitted frames after they have been
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -608,7 +608,8 @@ static bool sta_info_cleanup_expire_buff
+ #endif
+ 		dev_kfree_skb(skb);
+ 
+-		if (skb_queue_empty(&sta->ps_tx_buf))
++		if (skb_queue_empty(&sta->ps_tx_buf) &&
++		    !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF))
+ 			sta_info_clear_tim_bit(sta);
+ 	}
+ 
+@@ -899,6 +900,7 @@ void ieee80211_sta_ps_deliver_wakeup(str
+ 	struct ieee80211_local *local = sdata->local;
+ 	int sent, buffered;
+ 
++	clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
+ 	if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
+ 		drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
+ 
+@@ -991,3 +993,12 @@ void ieee80211_sta_block_awake(struct ie
+ 		ieee80211_queue_work(hw, &sta->drv_unblock_wk);
+ }
+ EXPORT_SYMBOL(ieee80211_sta_block_awake);
++
++void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta)
++{
++	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
++
++	set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
++	sta_info_set_tim_bit(sta);
++}
++EXPORT_SYMBOL(ieee80211_sta_set_tim);
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -43,6 +43,8 @@
+  *	be in the queues
+  * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping
+  *	station in power-save mode, reply when the driver unblocks.
++ * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
++ *	buffers. Automatically cleared on station wake-up.
+  */
+ enum ieee80211_sta_info_flags {
+ 	WLAN_STA_AUTH		= 1<<0,
+@@ -58,6 +60,7 @@ enum ieee80211_sta_info_flags {
+ 	WLAN_STA_BLOCK_BA	= 1<<11,
+ 	WLAN_STA_PS_DRIVER	= 1<<12,
+ 	WLAN_STA_PSPOLL		= 1<<13,
++	WLAN_STA_PS_DRIVER_BUF	= 1<<14,
+ };
+ 
+ #define STA_TID_NUM 16
diff --git a/package/mac80211/patches/521-ath9k_fix_ap_ps_buffering.patch b/package/mac80211/patches/521-ath9k_fix_ap_ps_buffering.patch
new file mode 100644
index 0000000000..87cc2654b5
--- /dev/null
+++ b/package/mac80211/patches/521-ath9k_fix_ap_ps_buffering.patch
@@ -0,0 +1,311 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -202,6 +202,7 @@ struct ath_atx_ac {
+ 	int sched;
+ 	struct list_head list;
+ 	struct list_head tid_q;
++	bool clear_ps_filter;
+ };
+ 
+ struct ath_frame_info {
+@@ -259,6 +260,8 @@ struct ath_node {
+ 	struct ath_atx_ac ac[WME_NUM_AC];
+ 	u16 maxampdu;
+ 	u8 mpdudensity;
++
++	bool sleeping;
+ };
+ 
+ #define AGGR_CLEANUP         BIT(1)
+@@ -340,6 +343,9 @@ int ath_tx_aggr_start(struct ath_softc *
+ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+ 
++void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
++bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an);
++
+ /********/
+ /* VIFs */
+ /********/
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1791,6 +1791,27 @@ static int ath9k_sta_remove(struct ieee8
+ 	return 0;
+ }
+ 
++static void ath9k_sta_notify(struct ieee80211_hw *hw,
++			 struct ieee80211_vif *vif,
++			 enum sta_notify_cmd cmd,
++			 struct ieee80211_sta *sta)
++{
++	struct ath_softc *sc = hw->priv;
++	struct ath_node *an = (struct ath_node *) sta->drv_priv;
++
++	switch (cmd) {
++	case STA_NOTIFY_SLEEP:
++		an->sleeping = true;
++		if (ath_tx_aggr_sleep(sc, an))
++			ieee80211_sta_set_tim(sta);
++		break;
++	case STA_NOTIFY_AWAKE:
++		an->sleeping = false;
++		ath_tx_aggr_wakeup(sc, an);
++		break;
++	}
++}
++
+ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+ 			 const struct ieee80211_tx_queue_params *params)
+ {
+@@ -2177,6 +2198,7 @@ struct ieee80211_ops ath9k_ops = {
+ 	.configure_filter   = ath9k_configure_filter,
+ 	.sta_add	    = ath9k_sta_add,
+ 	.sta_remove	    = ath9k_sta_remove,
++	.sta_notify         = ath9k_sta_notify,
+ 	.conf_tx 	    = ath9k_conf_tx,
+ 	.bss_info_changed   = ath9k_bss_info_changed,
+ 	.set_key            = ath9k_set_key,
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct 
+ 	struct ath_frame_info *fi;
+ 	int nframes;
+ 	u8 tidno;
++	bool clear_filter;
+ 
+ 	skb = bf->bf_mpdu;
+ 	hdr = (struct ieee80211_hdr *)skb->data;
+@@ -442,7 +443,11 @@ static void ath_tx_complete_aggr(struct 
+ 			acked_cnt++;
+ 		} else {
+ 			if (!(tid->state & AGGR_CLEANUP) && retry) {
+-				if (fi->retries < ATH_MAX_SW_RETRIES) {
++				if (ts->ts_status & ATH9K_TXERR_FILT) {
++					if (!an->sleeping)
++						clear_filter = true;
++					txpending = 1;
++				} else if (fi->retries < ATH_MAX_SW_RETRIES) {
+ 					ath_tx_set_retry(sc, txq, bf->bf_mpdu);
+ 					txpending = 1;
+ 				} else {
+@@ -496,6 +501,7 @@ static void ath_tx_complete_aggr(struct 
+ 				!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;
+@@ -546,7 +552,12 @@ static void ath_tx_complete_aggr(struct 
+ 
+ 	/* prepend un-acked frames to the beginning of the pending frame queue */
+ 	if (!list_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);
+ 		ath_tx_queue_tid(txq, tid);
+ 		spin_unlock_bh(&txq->axq_lock);
+@@ -816,6 +827,11 @@ 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);
+ 
++		if (tid->ac->clear_ps_filter) {
++			tid->ac->clear_ps_filter = false;
++			ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
++		}
++
+ 		/* if only one frame, send as non-aggregate */
+ 		if (bf == bf->bf_lastbf) {
+ 			fi = get_frame_info(bf->bf_mpdu);
+@@ -896,6 +912,67 @@ void ath_tx_aggr_stop(struct ath_softc *
+ 	ath_tx_flush_tid(sc, txtid);
+ }
+ 
++bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
++{
++	struct ath_atx_tid *tid;
++	struct ath_atx_ac *ac;
++	struct ath_txq *txq;
++	bool buffered = false;
++	int tidno;
++
++	for (tidno = 0, tid = &an->tid[tidno];
++	     tidno < WME_NUM_TID; tidno++, tid++) {
++
++		if (!tid->sched)
++			continue;
++
++		ac = tid->ac;
++		txq = ac->txq;
++
++		spin_lock_bh(&txq->axq_lock);
++
++		if (!list_empty(&tid->buf_q))
++			buffered = true;
++
++		tid->sched = false;
++		list_del(&tid->list);
++
++		if (ac->sched) {
++			ac->sched = false;
++			list_del(&ac->list);
++		}
++
++		spin_unlock_bh(&txq->axq_lock);
++	}
++
++	return buffered;
++}
++
++void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
++{
++	struct ath_atx_tid *tid;
++	struct ath_atx_ac *ac;
++	struct ath_txq *txq;
++	int tidno;
++
++	for (tidno = 0, tid = &an->tid[tidno];
++	     tidno < WME_NUM_TID; tidno++, tid++) {
++
++		ac = tid->ac;
++		txq = ac->txq;
++
++		spin_lock_bh(&txq->axq_lock);
++		ac->clear_ps_filter = true;
++
++		if (!list_empty(&tid->buf_q) && !tid->paused) {
++			ath_tx_queue_tid(txq, tid);
++			ath_txq_schedule(sc, txq);
++		}
++
++		spin_unlock_bh(&txq->axq_lock);
++	}
++}
++
+ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+ {
+ 	struct ath_atx_tid *txtid;
+@@ -1491,7 +1568,6 @@ static int setup_tx_flags(struct sk_buff
+ 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ 	int flags = 0;
+ 
+-	flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
+ 	flags |= ATH9K_TXDESC_INTREQ;
+ 
+ 	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
+@@ -1754,6 +1830,9 @@ static void ath_tx_start_dma(struct ath_
+ 		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, &bf_head);
+ 	}
+ 
+--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
+@@ -128,6 +128,11 @@ static inline void ath9k_hw_set11n_virtu
+ 	ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf);
+ }
+ 
++static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
++{
++	ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
++}
++
+ /* Private hardware call ops */
+ 
+ /* PHY ops */
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -642,6 +642,7 @@ struct ath_hw_ops {
+ 				     u32 burstDuration);
+ 	void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds,
+ 				       u32 vmf);
++	void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
+ };
+ 
+ struct ath_nf_limits {
+--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+@@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(stru
+ 		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+ 		| SM(txPower, AR_XmitPower)
+ 		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+-		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+ 		| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+ 		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
+ 
+@@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(stru
+ 	}
+ }
+ 
++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,
+@@ -460,4 +469,5 @@ void ar9002_hw_attach_mac_ops(struct ath
+ 	ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
+ 	ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
+ 	ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag;
++	ops->set_clrdmask = ar9002_hw_set_clrdmask;
+ }
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(stru
+ 		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+ 		| SM(txpower, AR_XmitPower)
+ 		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+-		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+ 		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+ 		| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
+ 
+@@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(stru
+ 	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,
+@@ -522,6 +531,7 @@ void ar9003_hw_attach_mac_ops(struct ath
+ 	ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
+ 	ops->set11n_burstduration = ar9003_hw_set11n_burstduration;
+ 	ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag;
++	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/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -239,7 +239,6 @@ struct ath_desc {
+ 	void *ds_vdata;
+ } __packed __aligned(4);
+ 
+-#define ATH9K_TXDESC_CLRDMASK		0x0001
+ #define ATH9K_TXDESC_NOACK		0x0002
+ #define ATH9K_TXDESC_RTSENA		0x0004
+ #define ATH9K_TXDESC_CTSENA		0x0008
diff --git a/package/mac80211/patches/522-ath9k_remove_pending_frames_workaround.patch b/package/mac80211/patches/522-ath9k_remove_pending_frames_workaround.patch
new file mode 100644
index 0000000000..e368bce64b
--- /dev/null
+++ b/package/mac80211/patches/522-ath9k_remove_pending_frames_workaround.patch
@@ -0,0 +1,36 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -2223,33 +2223,6 @@ static void ath_tx_complete_poll_work(st
+ 				} else {
+ 					txq->axq_tx_inprogress = true;
+ 				}
+-			} else {
+-				/* If the queue has pending buffers, then it
+-				 * should be doing tx work (and have axq_depth).
+-				 * Shouldn't get to this state I think..but
+-				 * we do.
+-				 */
+-				if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) &&
+-				    (txq->pending_frames > 0 ||
+-				     !list_empty(&txq->axq_acq) ||
+-				     txq->stopped)) {
+-					ath_err(ath9k_hw_common(sc->sc_ah),
+-						"txq: %p axq_qnum: %u,"
+-						" mac80211_qnum: %i"
+-						" axq_link: %p"
+-						" pending frames: %i"
+-						" axq_acq empty: %i"
+-						" stopped: %i"
+-						" axq_depth: 0  Attempting to"
+-						" restart tx logic.\n",
+-						txq, txq->axq_qnum,
+-						txq->mac80211_qnum,
+-						txq->axq_link,
+-						txq->pending_frames,
+-						list_empty(&txq->axq_acq),
+-						txq->stopped);
+-					ath_txq_schedule(sc, txq);
+-				}
+ 			}
+ 			spin_unlock_bh(&txq->axq_lock);
+ 		}
diff --git a/package/mac80211/patches/530-mac80211_drv_tim_override.patch b/package/mac80211/patches/530-mac80211_drv_tim_override.patch
deleted file mode 100644
index 198f658a61..0000000000
--- a/package/mac80211/patches/530-mac80211_drv_tim_override.patch
+++ /dev/null
@@ -1,73 +0,0 @@
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -2209,6 +2209,18 @@ static inline int ieee80211_sta_ps_trans
- #define IEEE80211_TX_STATUS_HEADROOM	13
- 
- /**
-+ * ieee80211_sta_set_tim - set the TIM bit for a sleeping station
-+ *
-+ * If a driver buffers frames for a powersave station instead of passing
-+ * them back to mac80211 for retransmission, the station needs to be told
-+ * to wake up using the TIM bitmap in the beacon.
-+ *
-+ * This function sets the station's TIM bit - it will be cleared when the
-+ * station wakes up.
-+ */
-+void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
-+
-+/**
-  * ieee80211_tx_status - transmit status callback
-  *
-  * Call this function for all transmitted frames after they have been
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -608,7 +608,8 @@ static bool sta_info_cleanup_expire_buff
- #endif
- 		dev_kfree_skb(skb);
- 
--		if (skb_queue_empty(&sta->ps_tx_buf))
-+		if (skb_queue_empty(&sta->ps_tx_buf) &&
-+		    !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF))
- 			sta_info_clear_tim_bit(sta);
- 	}
- 
-@@ -899,6 +900,7 @@ void ieee80211_sta_ps_deliver_wakeup(str
- 	struct ieee80211_local *local = sdata->local;
- 	int sent, buffered;
- 
-+	clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
- 	if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
- 		drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
- 
-@@ -991,3 +993,12 @@ void ieee80211_sta_block_awake(struct ie
- 		ieee80211_queue_work(hw, &sta->drv_unblock_wk);
- }
- EXPORT_SYMBOL(ieee80211_sta_block_awake);
-+
-+void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta)
-+{
-+	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
-+
-+	set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
-+	sta_info_set_tim_bit(sta);
-+}
-+EXPORT_SYMBOL(ieee80211_sta_set_tim);
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -43,6 +43,8 @@
-  *	be in the queues
-  * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping
-  *	station in power-save mode, reply when the driver unblocks.
-+ * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
-+ *	buffers. Automatically cleared on station wake-up.
-  */
- enum ieee80211_sta_info_flags {
- 	WLAN_STA_AUTH		= 1<<0,
-@@ -58,6 +60,7 @@ enum ieee80211_sta_info_flags {
- 	WLAN_STA_BLOCK_BA	= 1<<11,
- 	WLAN_STA_PS_DRIVER	= 1<<12,
- 	WLAN_STA_PSPOLL		= 1<<13,
-+	WLAN_STA_PS_DRIVER_BUF	= 1<<14,
- };
- 
- #define STA_TID_NUM 16
diff --git a/package/mac80211/patches/530-mac80211_redirect_vlan_eap_frames.patch b/package/mac80211/patches/530-mac80211_redirect_vlan_eap_frames.patch
new file mode 100644
index 0000000000..03a4fe5d37
--- /dev/null
+++ b/package/mac80211/patches/530-mac80211_redirect_vlan_eap_frames.patch
@@ -0,0 +1,67 @@
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1582,7 +1582,7 @@ ieee80211_drop_unencrypted_mgmt(struct i
+ }
+ 
+ static int
+-__ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
++__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
+ {
+ 	struct ieee80211_sub_if_data *sdata = rx->sdata;
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+@@ -1590,6 +1590,7 @@ __ieee80211_data_to_8023(struct ieee8021
+ 	struct ethhdr *ehdr;
+ 	int ret;
+ 
++	*port_control = false;
+ 	if (ieee80211_has_a4(hdr->frame_control) &&
+ 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
+ 		return -1;
+@@ -1608,11 +1609,14 @@ __ieee80211_data_to_8023(struct ieee8021
+ 		return -1;
+ 
+ 	ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
+-	if (ret < 0 || !check_port_control)
++	if (ret < 0)
+ 		return ret;
+ 
+ 	ehdr = (struct ethhdr *) rx->skb->data;
+-	if (ehdr->h_proto != rx->sdata->control_port_protocol)
++	if (ehdr->h_proto == rx->sdata->control_port_protocol)
++		*port_control = true;
++
++	if (check_port_control && !*port_control)
+ 		return -1;
+ 
+ 	return 0;
+@@ -1913,6 +1917,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_
+ 	struct net_device *dev = sdata->dev;
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+ 	__le16 fc = hdr->frame_control;
++	bool port_control;
+ 	int err;
+ 
+ 	if (unlikely(!ieee80211_is_data(hdr->frame_control)))
+@@ -1929,13 +1934,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_
+ 	    sdata->vif.type == NL80211_IFTYPE_AP)
+ 		return RX_DROP_MONITOR;
+ 
+-	err = __ieee80211_data_to_8023(rx);
++	err = __ieee80211_data_to_8023(rx, &port_control);
+ 	if (unlikely(err))
+ 		return RX_DROP_UNUSABLE;
+ 
+ 	if (!ieee80211_frame_allowed(rx, fc))
+ 		return RX_DROP_MONITOR;
+ 
++	if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
++	    unlikely(port_control) && sdata->bss) {
++		sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
++				     u.ap);
++		dev = sdata->dev;
++		rx->sdata = sdata;
++	}
++
+ 	rx->skb->dev = dev;
+ 
+ 	dev->stats.rx_packets++;
diff --git a/package/mac80211/patches/531-ath9k_fix_ap_ps_buffering.patch b/package/mac80211/patches/531-ath9k_fix_ap_ps_buffering.patch
deleted file mode 100644
index ff58c26d7a..0000000000
--- a/package/mac80211/patches/531-ath9k_fix_ap_ps_buffering.patch
+++ /dev/null
@@ -1,311 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -203,6 +203,7 @@ struct ath_atx_ac {
- 	int sched;
- 	struct list_head list;
- 	struct list_head tid_q;
-+	bool clear_ps_filter;
- };
- 
- struct ath_frame_info {
-@@ -260,6 +261,8 @@ struct ath_node {
- 	struct ath_atx_ac ac[WME_NUM_AC];
- 	u16 maxampdu;
- 	u8 mpdudensity;
-+
-+	bool sleeping;
- };
- 
- #define AGGR_CLEANUP         BIT(1)
-@@ -341,6 +344,9 @@ int ath_tx_aggr_start(struct ath_softc *
- void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
- void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
- 
-+void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
-+bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an);
-+
- /********/
- /* VIFs */
- /********/
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1791,6 +1791,27 @@ static int ath9k_sta_remove(struct ieee8
- 	return 0;
- }
- 
-+static void ath9k_sta_notify(struct ieee80211_hw *hw,
-+			 struct ieee80211_vif *vif,
-+			 enum sta_notify_cmd cmd,
-+			 struct ieee80211_sta *sta)
-+{
-+	struct ath_softc *sc = hw->priv;
-+	struct ath_node *an = (struct ath_node *) sta->drv_priv;
-+
-+	switch (cmd) {
-+	case STA_NOTIFY_SLEEP:
-+		an->sleeping = true;
-+		if (ath_tx_aggr_sleep(sc, an))
-+			ieee80211_sta_set_tim(sta);
-+		break;
-+	case STA_NOTIFY_AWAKE:
-+		an->sleeping = false;
-+		ath_tx_aggr_wakeup(sc, an);
-+		break;
-+	}
-+}
-+
- static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
- 			 const struct ieee80211_tx_queue_params *params)
- {
-@@ -2191,6 +2212,7 @@ struct ieee80211_ops ath9k_ops = {
- 	.configure_filter   = ath9k_configure_filter,
- 	.sta_add	    = ath9k_sta_add,
- 	.sta_remove	    = ath9k_sta_remove,
-+	.sta_notify         = ath9k_sta_notify,
- 	.conf_tx 	    = ath9k_conf_tx,
- 	.bss_info_changed   = ath9k_bss_info_changed,
- 	.set_key            = ath9k_set_key,
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct 
- 	struct ath_frame_info *fi;
- 	int nframes;
- 	u8 tidno;
-+	bool clear_filter;
- 
- 	skb = bf->bf_mpdu;
- 	hdr = (struct ieee80211_hdr *)skb->data;
-@@ -442,7 +443,11 @@ static void ath_tx_complete_aggr(struct 
- 			acked_cnt++;
- 		} else {
- 			if (!(tid->state & AGGR_CLEANUP) && retry) {
--				if (fi->retries < ATH_MAX_SW_RETRIES) {
-+				if (ts->ts_status & ATH9K_TXERR_FILT) {
-+					if (!an->sleeping)
-+						clear_filter = true;
-+					txpending = 1;
-+				} else if (fi->retries < ATH_MAX_SW_RETRIES) {
- 					ath_tx_set_retry(sc, txq, bf->bf_mpdu);
- 					txpending = 1;
- 				} else {
-@@ -496,6 +501,7 @@ static void ath_tx_complete_aggr(struct 
- 				!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;
-@@ -546,7 +552,12 @@ static void ath_tx_complete_aggr(struct 
- 
- 	/* prepend un-acked frames to the beginning of the pending frame queue */
- 	if (!list_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);
- 		ath_tx_queue_tid(txq, tid);
- 		spin_unlock_bh(&txq->axq_lock);
-@@ -816,6 +827,11 @@ 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);
- 
-+		if (tid->ac->clear_ps_filter) {
-+			tid->ac->clear_ps_filter = false;
-+			ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
-+		}
-+
- 		/* if only one frame, send as non-aggregate */
- 		if (bf == bf->bf_lastbf) {
- 			fi = get_frame_info(bf->bf_mpdu);
-@@ -896,6 +912,67 @@ void ath_tx_aggr_stop(struct ath_softc *
- 	ath_tx_flush_tid(sc, txtid);
- }
- 
-+bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
-+{
-+	struct ath_atx_tid *tid;
-+	struct ath_atx_ac *ac;
-+	struct ath_txq *txq;
-+	bool buffered = false;
-+	int tidno;
-+
-+	for (tidno = 0, tid = &an->tid[tidno];
-+	     tidno < WME_NUM_TID; tidno++, tid++) {
-+
-+		if (!tid->sched)
-+			continue;
-+
-+		ac = tid->ac;
-+		txq = ac->txq;
-+
-+		spin_lock_bh(&txq->axq_lock);
-+
-+		if (!list_empty(&tid->buf_q))
-+			buffered = true;
-+
-+		tid->sched = false;
-+		list_del(&tid->list);
-+
-+		if (ac->sched) {
-+			ac->sched = false;
-+			list_del(&ac->list);
-+		}
-+
-+		spin_unlock_bh(&txq->axq_lock);
-+	}
-+
-+	return buffered;
-+}
-+
-+void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
-+{
-+	struct ath_atx_tid *tid;
-+	struct ath_atx_ac *ac;
-+	struct ath_txq *txq;
-+	int tidno;
-+
-+	for (tidno = 0, tid = &an->tid[tidno];
-+	     tidno < WME_NUM_TID; tidno++, tid++) {
-+
-+		ac = tid->ac;
-+		txq = ac->txq;
-+
-+		spin_lock_bh(&txq->axq_lock);
-+		ac->clear_ps_filter = true;
-+
-+		if (!list_empty(&tid->buf_q) && !tid->paused) {
-+			ath_tx_queue_tid(txq, tid);
-+			ath_txq_schedule(sc, txq);
-+		}
-+
-+		spin_unlock_bh(&txq->axq_lock);
-+	}
-+}
-+
- void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
- {
- 	struct ath_atx_tid *txtid;
-@@ -1493,7 +1570,6 @@ static int setup_tx_flags(struct sk_buff
- 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- 	int flags = 0;
- 
--	flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
- 	flags |= ATH9K_TXDESC_INTREQ;
- 
- 	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
-@@ -1756,6 +1832,9 @@ static void ath_tx_start_dma(struct ath_
- 		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, &bf_head);
- 	}
- 
---- a/drivers/net/wireless/ath/ath9k/hw-ops.h
-+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
-@@ -128,6 +128,11 @@ static inline void ath9k_hw_set11n_virtu
- 	ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf);
- }
- 
-+static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-+{
-+	ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
-+}
-+
- /* Private hardware call ops */
- 
- /* PHY ops */
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -642,6 +642,7 @@ struct ath_hw_ops {
- 				     u32 burstDuration);
- 	void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds,
- 				       u32 vmf);
-+	void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
- };
- 
- struct ath_nf_limits {
---- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
-@@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(stru
- 		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- 		| SM(txPower, AR_XmitPower)
- 		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
--		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
- 		| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
- 		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
- 
-@@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(stru
- 	}
- }
- 
-+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,
-@@ -460,4 +469,5 @@ void ar9002_hw_attach_mac_ops(struct ath
- 	ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
- 	ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
- 	ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag;
-+	ops->set_clrdmask = ar9002_hw_set_clrdmask;
- }
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(stru
- 		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- 		| SM(txpower, AR_XmitPower)
- 		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
--		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
- 		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
- 		| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
- 
-@@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(stru
- 	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,
-@@ -522,6 +531,7 @@ void ar9003_hw_attach_mac_ops(struct ath
- 	ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
- 	ops->set11n_burstduration = ar9003_hw_set11n_burstduration;
- 	ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag;
-+	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/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -239,7 +239,6 @@ struct ath_desc {
- 	void *ds_vdata;
- } __packed __aligned(4);
- 
--#define ATH9K_TXDESC_CLRDMASK		0x0001
- #define ATH9K_TXDESC_NOACK		0x0002
- #define ATH9K_TXDESC_RTSENA		0x0004
- #define ATH9K_TXDESC_CTSENA		0x0008
diff --git a/package/mac80211/patches/532-ath9k_remove_pending_frames_workaround.patch b/package/mac80211/patches/532-ath9k_remove_pending_frames_workaround.patch
deleted file mode 100644
index f7341e2a10..0000000000
--- a/package/mac80211/patches/532-ath9k_remove_pending_frames_workaround.patch
+++ /dev/null
@@ -1,36 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -2226,33 +2226,6 @@ static void ath_tx_complete_poll_work(st
- 				} else {
- 					txq->axq_tx_inprogress = true;
- 				}
--			} else {
--				/* If the queue has pending buffers, then it
--				 * should be doing tx work (and have axq_depth).
--				 * Shouldn't get to this state I think..but
--				 * we do.
--				 */
--				if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) &&
--				    (txq->pending_frames > 0 ||
--				     !list_empty(&txq->axq_acq) ||
--				     txq->stopped)) {
--					ath_err(ath9k_hw_common(sc->sc_ah),
--						"txq: %p axq_qnum: %u,"
--						" mac80211_qnum: %i"
--						" axq_link: %p"
--						" pending frames: %i"
--						" axq_acq empty: %i"
--						" stopped: %i"
--						" axq_depth: 0  Attempting to"
--						" restart tx logic.\n",
--						txq, txq->axq_qnum,
--						txq->mac80211_qnum,
--						txq->axq_link,
--						txq->pending_frames,
--						list_empty(&txq->axq_acq),
--						txq->stopped);
--					ath_txq_schedule(sc, txq);
--				}
- 			}
- 			spin_unlock_bh(&txq->axq_lock);
- 		}
diff --git a/package/mac80211/patches/540-mac80211_add_rx_rate.patch b/package/mac80211/patches/540-mac80211_add_rx_rate.patch
deleted file mode 100644
index d365f35245..0000000000
--- a/package/mac80211/patches/540-mac80211_add_rx_rate.patch
+++ /dev/null
@@ -1,232 +0,0 @@
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -414,7 +414,7 @@ struct station_parameters {
-  * @STATION_INFO_PLID: @plid filled
-  * @STATION_INFO_PLINK_STATE: @plink_state filled
-  * @STATION_INFO_SIGNAL: @signal filled
-- * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
-+ * @STATION_INFO_TX_BITRATE: @txrate fields are filled
-  *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
-  * @STATION_INFO_RX_PACKETS: @rx_packets filled
-  * @STATION_INFO_TX_PACKETS: @tx_packets filled
-@@ -422,6 +422,7 @@ struct station_parameters {
-  * @STATION_INFO_TX_FAILED: @tx_failed filled
-  * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
-  * @STATION_INFO_SIGNAL_AVG: @signal_avg filled
-+ * @STATION_INFO_RX_BITRATE: @rxrate fields are filled
-  */
- enum station_info_flags {
- 	STATION_INFO_INACTIVE_TIME	= 1<<0,
-@@ -438,6 +439,7 @@ enum station_info_flags {
- 	STATION_INFO_TX_FAILED		= 1<<11,
- 	STATION_INFO_RX_DROP_MISC	= 1<<12,
- 	STATION_INFO_SIGNAL_AVG		= 1<<13,
-+	STATION_INFO_RX_BITRATE		= 1<<14,
- };
- 
- /**
-@@ -507,6 +509,7 @@ struct station_info {
- 	s8 signal;
- 	s8 signal_avg;
- 	struct rate_info txrate;
-+	struct rate_info rxrate;
- 	u32 rx_packets;
- 	u32 tx_packets;
- 	u32 tx_retries;
---- a/include/linux/nl80211.h
-+++ b/include/linux/nl80211.h
-@@ -1243,6 +1243,8 @@ enum nl80211_rate_info {
-  * @NL80211_STA_INFO_LLID: the station's mesh LLID
-  * @NL80211_STA_INFO_PLID: the station's mesh PLID
-  * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station
-+ * @NL80211_STA_INFO_RX_BITRATE: last unicast rx rate, nested attribute
-+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
-  * @__NL80211_STA_INFO_AFTER_LAST: internal
-  * @NL80211_STA_INFO_MAX: highest possible station info attribute
-  */
-@@ -1261,6 +1263,7 @@ enum nl80211_sta_info {
- 	NL80211_STA_INFO_TX_RETRIES,
- 	NL80211_STA_INFO_TX_FAILED,
- 	NL80211_STA_INFO_SIGNAL_AVG,
-+	NL80211_STA_INFO_RX_BITRATE,
- 
- 	/* keep last */
- 	__NL80211_STA_INFO_AFTER_LAST,
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -1968,13 +1968,41 @@ static int parse_station_flags(struct ge
- 	return 0;
- }
- 
-+static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
-+				 int attr)
-+{
-+	struct nlattr *rate;
-+	u16 bitrate;
-+
-+	rate = nla_nest_start(msg, attr);
-+	if (!rate)
-+		goto nla_put_failure;
-+
-+	/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
-+	bitrate = cfg80211_calculate_bitrate(info);
-+	if (bitrate > 0)
-+		NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
-+
-+	if (info->flags & RATE_INFO_FLAGS_MCS)
-+		NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs);
-+	if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
-+		NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
-+	if (info->flags & RATE_INFO_FLAGS_SHORT_GI)
-+		NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
-+
-+	nla_nest_end(msg, rate);
-+	return true;
-+
-+nla_put_failure:
-+	return false;
-+}
-+
- static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
- 				int flags, struct net_device *dev,
- 				const u8 *mac_addr, struct station_info *sinfo)
- {
- 	void *hdr;
--	struct nlattr *sinfoattr, *txrate;
--	u16 bitrate;
-+	struct nlattr *sinfoattr;
- 
- 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
- 	if (!hdr)
-@@ -2013,24 +2041,14 @@ static int nl80211_send_station(struct s
- 		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
- 			   sinfo->signal_avg);
- 	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
--		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
--		if (!txrate)
-+		if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
-+					  NL80211_STA_INFO_TX_BITRATE))
-+			goto nla_put_failure;
-+	}
-+	if (sinfo->filled & STATION_INFO_RX_BITRATE) {
-+		if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
-+					  NL80211_STA_INFO_RX_BITRATE))
- 			goto nla_put_failure;
--
--		/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
--		bitrate = cfg80211_calculate_bitrate(&sinfo->txrate);
--		if (bitrate > 0)
--			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
--
--		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
--			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
--				    sinfo->txrate.mcs);
--		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
--			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
--		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
--			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
--
--		nla_nest_end(msg, txrate);
- 	}
- 	if (sinfo->filled & STATION_INFO_RX_PACKETS)
- 		NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -212,6 +212,8 @@ enum plink_state {
-  * @rate_ctrl_priv: rate control private per-STA pointer
-  * @last_tx_rate: rate used for last transmit, to report to userspace as
-  *	"the" transmit rate
-+ * @last_rx_rate_idx: rx status rate index of the last data packet
-+ * @last_rx_rate_flag: rx status flag of the last data packet
-  * @lock: used for locking all fields that require locking, see comments
-  *	in the header file.
-  * @flaglock: spinlock for flags accesses
-@@ -314,6 +316,8 @@ struct sta_info {
- 	unsigned long tx_bytes;
- 	unsigned long tx_fragments;
- 	struct ieee80211_tx_rate last_tx_rate;
-+	int last_rx_rate_idx;
-+	int last_rx_rate_flag;
- 	u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
- 
- 	/*
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -1156,14 +1156,23 @@ ieee80211_rx_h_sta_process(struct ieee80
- 	if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
- 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
- 						NL80211_IFTYPE_ADHOC);
--		if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0)
-+		if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0) {
- 			sta->last_rx = jiffies;
-+			if (ieee80211_is_data(hdr->frame_control)) {
-+				sta->last_rx_rate_idx = status->rate_idx;
-+				sta->last_rx_rate_flag = status->flag;
-+			}
-+		}
- 	} else if (!is_multicast_ether_addr(hdr->addr1)) {
- 		/*
- 		 * Mesh beacons will update last_rx when if they are found to
- 		 * match the current local configuration when processed.
- 		 */
- 		sta->last_rx = jiffies;
-+		if (ieee80211_is_data(hdr->frame_control)) {
-+			sta->last_rx_rate_idx = status->rate_idx;
-+			sta->last_rx_rate_flag = status->flag;
-+		}
- 	}
- 
- 	if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -316,6 +316,17 @@ static int ieee80211_config_default_mgmt
- 	return 0;
- }
- 
-+static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx)
-+{
-+	if (!(rate->flags & RATE_INFO_FLAGS_MCS)) {
-+		struct ieee80211_supported_band *sband;
-+		sband = sta->local->hw.wiphy->bands[
-+				sta->local->hw.conf.channel->band];
-+		rate->legacy = sband->bitrates[idx].bitrate;
-+	} else
-+		rate->mcs = idx;
-+}
-+
- static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
- {
- 	struct ieee80211_sub_if_data *sdata = sta->sdata;
-@@ -330,6 +341,7 @@ static void sta_set_sinfo(struct sta_inf
- 			STATION_INFO_TX_RETRIES |
- 			STATION_INFO_TX_FAILED |
- 			STATION_INFO_TX_BITRATE |
-+			STATION_INFO_RX_BITRATE |
- 			STATION_INFO_RX_DROP_MISC;
- 
- 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
-@@ -355,15 +367,16 @@ static void sta_set_sinfo(struct sta_inf
- 		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
- 	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
- 		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
-+	rate_idx_to_bitrate(&sinfo->txrate, sta, sta->last_tx_rate.idx);
- 
--	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
--		struct ieee80211_supported_band *sband;
--		sband = sta->local->hw.wiphy->bands[
--				sta->local->hw.conf.channel->band];
--		sinfo->txrate.legacy =
--			sband->bitrates[sta->last_tx_rate.idx].bitrate;
--	} else
--		sinfo->txrate.mcs = sta->last_tx_rate.idx;
-+	sinfo->rxrate.flags = 0;
-+	if (sta->last_rx_rate_flag & RX_FLAG_HT)
-+		sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS;
-+	if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
-+		sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
-+	if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
-+		sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
-+	rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx);
- 
- 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
- #ifdef CONFIG_MAC80211_MESH
diff --git a/package/mac80211/patches/550-ath9k_no_vif_promisc_handling.patch b/package/mac80211/patches/550-ath9k_no_vif_promisc_handling.patch
deleted file mode 100644
index c3a9663266..0000000000
--- a/package/mac80211/patches/550-ath9k_no_vif_promisc_handling.patch
+++ /dev/null
@@ -1,13 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -413,9 +413,7 @@ u32 ath_calcrxfilter(struct ath_softc *s
- 	 * mode interface or when in monitor mode. AP mode does not need this
- 	 * since it receives all in-BSS frames anyway.
- 	 */
--	if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
--	     (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
--	    (sc->sc_ah->is_monitoring))
-+	if (sc->sc_ah->is_monitoring)
- 		rfilt |= ATH9K_RX_FILTER_PROM;
- 
- 	if (sc->rx.rxfilter & FIF_CONTROL)
diff --git a/package/mac80211/patches/560-mac80211_minstrel_ht_sampling_fix.patch b/package/mac80211/patches/560-mac80211_minstrel_ht_sampling_fix.patch
deleted file mode 100644
index 011f87ad31..0000000000
--- a/package/mac80211/patches/560-mac80211_minstrel_ht_sampling_fix.patch
+++ /dev/null
@@ -1,50 +0,0 @@
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -415,10 +415,8 @@ minstrel_ht_tx_status(void *priv, struct
- 		mi->sample_count--;
- 	}
- 
--	if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
-+	if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
- 		mi->sample_packets += info->status.ampdu_len;
--		minstrel_next_sample_idx(mi);
--	}
- 
- 	for (i = 0; !last; i++) {
- 		last = (i == IEEE80211_TX_MAX_RATES - 1) ||
-@@ -553,13 +551,14 @@ minstrel_get_sample_rate(struct minstrel
- 	sample_idx = sample_table[mg->column][mg->index];
- 	mr = &mg->rates[sample_idx];
- 	sample_idx += mi->sample_group * MCS_GROUP_RATES;
-+	minstrel_next_sample_idx(mi);
- 
- 	/*
- 	 * When not using MRR, do not sample if the probability is already
- 	 * higher than 95% to avoid wasting airtime
- 	 */
- 	if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100)))
--		goto next;
-+		return -1;
- 
- 	/*
- 	 * Make sure that lower rates get sampled only occasionally,
-@@ -568,17 +567,13 @@ minstrel_get_sample_rate(struct minstrel
- 	if (minstrel_get_duration(sample_idx) >
- 	    minstrel_get_duration(mi->max_tp_rate)) {
- 		if (mr->sample_skipped < 20)
--			goto next;
-+			return -1;
- 
- 		if (mi->sample_slow++ > 2)
--			goto next;
-+			return -1;
- 	}
- 
- 	return sample_idx;
--
--next:
--	minstrel_next_sample_idx(mi);
--	return -1;
- }
- 
- static void
diff --git a/package/mac80211/patches/570-ath9k_fix_reg_bit_macros.patch b/package/mac80211/patches/570-ath9k_fix_reg_bit_macros.patch
deleted file mode 100644
index 7d961d2c2f..0000000000
--- a/package/mac80211/patches/570-ath9k_fix_reg_bit_macros.patch
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -95,9 +95,9 @@
- #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_WRITE(_a, _r, REG_READ(_a, _r) | (_f))
- #define REG_CLR_BIT(_a, _r, _f) \
--	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
-+	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f))
- 
- #define DO_DELAY(x) do {			\
- 		if ((++(x) % 64) == 0)          \
diff --git a/package/mac80211/patches/571-ath9k_fix_dma_stop.patch b/package/mac80211/patches/571-ath9k_fix_dma_stop.patch
deleted file mode 100644
index 9f7cfa82ec..0000000000
--- a/package/mac80211/patches/571-ath9k_fix_dma_stop.patch
+++ /dev/null
@@ -1,72 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -1271,16 +1271,14 @@ bool ath_drain_all_txq(struct ath_softc 
- 	if (sc->sc_flags & SC_OP_INVALID)
- 		return true;
- 
--	/* Stop beacon queue */
--	ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-+	ath9k_hw_abort_tx_dma(ah);
- 
--	/* Stop data queues */
-+	/* Check if any queue remains active */
- 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
--		if (ATH_TXQ_SETUP(sc, i)) {
--			txq = &sc->tx.txq[i];
--			ath9k_hw_stoptxdma(ah, txq->axq_qnum);
--			npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
--		}
-+		if (!ATH_TXQ_SETUP(sc, i))
-+			continue;
-+
-+		npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
- 	}
- 
- 	if (npend)
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -143,6 +143,34 @@ bool ath9k_hw_updatetxtriglevel(struct a
- }
- EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
- 
-+void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
-+{
-+	int i, q;
-+
-+	REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
-+
-+	REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
-+	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
-+	REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
-+
-+	for (q = 0; q < AR_NUM_QCU; q++) {
-+		for (i = 0; i < 1000; i++) {
-+			if (i)
-+				udelay(5);
-+
-+			if (!ath9k_hw_numtxpending(ah, q))
-+				break;
-+		}
-+	}
-+
-+	REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
-+	REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
-+	REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
-+
-+	REG_WRITE(ah, AR_Q_TXD, 0);
-+}
-+EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
-+
- bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
- {
- #define ATH9K_TX_STOP_DMA_TIMEOUT	4000    /* usec */
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -676,6 +676,7 @@ void ath9k_hw_cleartxdesc(struct ath_hw 
- u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
- bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
- bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
-+void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
- void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
- bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
- 			    const struct ath9k_tx_queue_info *qinfo);
diff --git a/package/mac80211/patches/572-ath9k_fix_tx_flush.patch b/package/mac80211/patches/572-ath9k_fix_tx_flush.patch
deleted file mode 100644
index 630abc6fdc..0000000000
--- a/package/mac80211/patches/572-ath9k_fix_tx_flush.patch
+++ /dev/null
@@ -1,141 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -2149,56 +2149,42 @@ static void ath9k_set_coverage_class(str
- 
- static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
- {
--#define ATH_FLUSH_TIMEOUT	60 /* ms */
- 	struct ath_softc *sc = hw->priv;
--	struct ath_txq *txq = NULL;
--	struct ath_hw *ah = sc->sc_ah;
--	struct ath_common *common = ath9k_hw_common(ah);
--	int i, j, npend = 0;
-+	int timeout = 200; /* ms */
-+	int i, j;
- 
-+	ath9k_ps_wakeup(sc);
- 	mutex_lock(&sc->mutex);
- 
- 	cancel_delayed_work_sync(&sc->tx_complete_work);
- 
--	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
--		if (!ATH_TXQ_SETUP(sc, i))
--			continue;
--		txq = &sc->tx.txq[i];
--
--		if (!drop) {
--			for (j = 0; j < ATH_FLUSH_TIMEOUT; j++) {
--				if (!ath9k_has_pending_frames(sc, txq))
--					break;
--				usleep_range(1000, 2000);
--			}
--		}
-+	if (drop)
-+		timeout = 1;
-+
-+	for (j = 0; j < timeout; j++) {
-+		int npend = 0;
-+
-+		if (j)
-+			usleep_range(1000, 2000);
- 
--		if (drop || ath9k_has_pending_frames(sc, txq)) {
--			ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n",
--				txq->axq_qnum);
--			spin_lock_bh(&txq->axq_lock);
--			txq->txq_flush_inprogress = true;
--			spin_unlock_bh(&txq->axq_lock);
--
--			ath9k_ps_wakeup(sc);
--			ath9k_hw_stoptxdma(ah, txq->axq_qnum);
--			npend = ath9k_hw_numtxpending(ah, txq->axq_qnum);
--			ath9k_ps_restore(sc);
--			if (npend)
--				break;
-+		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-+			if (!ATH_TXQ_SETUP(sc, i))
-+				continue;
- 
--			ath_draintxq(sc, txq, false);
--			txq->txq_flush_inprogress = false;
-+			npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
- 		}
-+
-+		if (!npend)
-+		    goto out;
- 	}
- 
--	if (npend) {
-+	if (!ath_drain_all_txq(sc, false))
- 		ath_reset(sc, false);
--		txq->txq_flush_inprogress = false;
--	}
- 
-+out:
- 	ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
- 	mutex_unlock(&sc->mutex);
-+	ath9k_ps_restore(sc);
- }
- 
- struct ieee80211_ops ath9k_ops = {
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -189,7 +189,6 @@ struct ath_txq {
- 	u32 axq_ampdu_depth;
- 	bool stopped;
- 	bool axq_tx_inprogress;
--	bool txq_flush_inprogress;
- 	struct list_head axq_acq;
- 	struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
- 	struct list_head txq_fifo_pending;
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -2091,8 +2091,7 @@ static void ath_tx_processq(struct ath_s
- 		spin_lock_bh(&txq->axq_lock);
- 		if (list_empty(&txq->axq_q)) {
- 			txq->axq_link = NULL;
--			if (sc->sc_flags & SC_OP_TXAGGR &&
--			    !txq->txq_flush_inprogress)
-+			if (sc->sc_flags & SC_OP_TXAGGR)
- 				ath_txq_schedule(sc, txq);
- 			spin_unlock_bh(&txq->axq_lock);
- 			break;
-@@ -2173,7 +2172,7 @@ static void ath_tx_processq(struct ath_s
- 
- 		spin_lock_bh(&txq->axq_lock);
- 
--		if (sc->sc_flags & SC_OP_TXAGGR && !txq->txq_flush_inprogress)
-+		if (sc->sc_flags & SC_OP_TXAGGR)
- 			ath_txq_schedule(sc, txq);
- 		spin_unlock_bh(&txq->axq_lock);
- 	}
-@@ -2317,18 +2316,17 @@ void ath_tx_edma_tasklet(struct ath_soft
- 
- 		spin_lock_bh(&txq->axq_lock);
- 
--		if (!txq->txq_flush_inprogress) {
--			if (!list_empty(&txq->txq_fifo_pending)) {
--				INIT_LIST_HEAD(&bf_head);
--				bf = list_first_entry(&txq->txq_fifo_pending,
--						      struct ath_buf, list);
--				list_cut_position(&bf_head,
--						  &txq->txq_fifo_pending,
--						  &bf->bf_lastbf->list);
--				ath_tx_txqaddbuf(sc, txq, &bf_head);
--			} else if (sc->sc_flags & SC_OP_TXAGGR)
--				ath_txq_schedule(sc, txq);
--		}
-+		if (!list_empty(&txq->txq_fifo_pending)) {
-+			INIT_LIST_HEAD(&bf_head);
-+			bf = list_first_entry(&txq->txq_fifo_pending,
-+					      struct ath_buf, list);
-+			list_cut_position(&bf_head,
-+					  &txq->txq_fifo_pending,
-+					  &bf->bf_lastbf->list);
-+			ath_tx_txqaddbuf(sc, txq, &bf_head);
-+		} else if (sc->sc_flags & SC_OP_TXAGGR)
-+			ath_txq_schedule(sc, txq);
-+
- 		spin_unlock_bh(&txq->axq_lock);
- 	}
- }
diff --git a/package/mac80211/patches/573-ath9k_beacon_stop.patch b/package/mac80211/patches/573-ath9k_beacon_stop.patch
deleted file mode 100644
index 5574d17168..0000000000
--- a/package/mac80211/patches/573-ath9k_beacon_stop.patch
+++ /dev/null
@@ -1,143 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -171,84 +171,31 @@ void ath9k_hw_abort_tx_dma(struct ath_hw
- }
- EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
- 
--bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
-+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
- {
--#define ATH9K_TX_STOP_DMA_TIMEOUT	4000    /* usec */
-+#define ATH9K_TX_STOP_DMA_TIMEOUT	1000    /* usec */
- #define ATH9K_TIME_QUANTUM		100     /* usec */
--	struct ath_common *common = ath9k_hw_common(ah);
--	struct ath9k_hw_capabilities *pCap = &ah->caps;
--	struct ath9k_tx_queue_info *qi;
--	u32 tsfLow, j, wait;
--	u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
--
--	if (q >= pCap->total_queues) {
--		ath_dbg(common, ATH_DBG_QUEUE,
--			"Stopping TX DMA, 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,
--			"Stopping TX DMA, inactive queue: %u\n", q);
--		return false;
--	}
-+	int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
-+	int wait;
- 
- 	REG_WRITE(ah, AR_Q_TXD, 1 << q);
- 
- 	for (wait = wait_time; wait != 0; wait--) {
--		if (ath9k_hw_numtxpending(ah, q) == 0)
--			break;
--		udelay(ATH9K_TIME_QUANTUM);
--	}
--
--	if (ath9k_hw_numtxpending(ah, q)) {
--		ath_dbg(common, ATH_DBG_QUEUE,
--			"%s: Num of pending TX Frames %d on Q %d\n",
--			__func__, ath9k_hw_numtxpending(ah, q), q);
--
--		for (j = 0; j < 2; j++) {
--			tsfLow = REG_READ(ah, AR_TSF_L32);
--			REG_WRITE(ah, AR_QUIET2,
--				  SM(10, AR_QUIET2_QUIET_DUR));
--			REG_WRITE(ah, AR_QUIET_PERIOD, 100);
--			REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
--			REG_SET_BIT(ah, AR_TIMER_MODE,
--				       AR_QUIET_TIMER_EN);
--
--			if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
--				break;
--
--			ath_dbg(common, ATH_DBG_QUEUE,
--				"TSF has moved while trying to set quiet time TSF: 0x%08x\n",
--				tsfLow);
--		}
--
--		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
--
--		udelay(200);
--		REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
--
--		wait = wait_time;
--		while (ath9k_hw_numtxpending(ah, q)) {
--			if ((--wait) == 0) {
--				ath_err(common,
--					"Failed to stop TX DMA in 100 msec after killing last frame\n");
--				break;
--			}
-+		if (wait != wait_time)
- 			udelay(ATH9K_TIME_QUANTUM);
--		}
- 
--		REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
-+		if (ath9k_hw_numtxpending(ah, q) == 0)
-+			break;
- 	}
- 
- 	REG_WRITE(ah, AR_Q_TXD, 0);
-+
- 	return wait != 0;
- 
- #undef ATH9K_TX_STOP_DMA_TIMEOUT
- #undef ATH9K_TIME_QUANTUM
- }
--EXPORT_SYMBOL(ath9k_hw_stoptxdma);
-+EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
- 
- void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
- {
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -675,7 +675,7 @@ void ath9k_hw_txstart(struct ath_hw *ah,
- 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_stoptxdma(struct ath_hw *ah, u32 q);
-+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
- void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
- void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
- bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -373,6 +373,7 @@ void ath_beacon_tasklet(unsigned long da
- 			ath_dbg(common, ATH_DBG_BSTUCK,
- 				"missed %u consecutive beacons\n",
- 				sc->beacon.bmisscnt);
-+			ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
- 			ath9k_hw_bstuck_nfcal(ah);
- 		} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
- 			ath_dbg(common, ATH_DBG_BSTUCK,
-@@ -450,16 +451,6 @@ void ath_beacon_tasklet(unsigned long da
- 		sc->beacon.updateslot = OK;
- 	}
- 	if (bfaddr != 0) {
--		/*
--		 * Stop any current dma and put the new frame(s) on the queue.
--		 * This should never fail since we check above that no frames
--		 * are still pending on the queue.
--		 */
--		if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
--			ath_err(common, "beacon queue %u did not stop?\n",
--				sc->beacon.beaconq);
--		}
--
- 		/* NB: cabq traffic should already be queued and primed */
- 		ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
- 		ath9k_hw_txstart(ah, sc->beacon.beaconq);
-@@ -780,7 +771,7 @@ void ath9k_set_beaconing_status(struct a
- 		ah->imask &= ~ATH9K_INT_SWBA;
- 		ath9k_hw_set_interrupts(ah, ah->imask);
- 		tasklet_kill(&sc->bcon_tasklet);
--		ath9k_hw_stoptxdma(ah, sc->beacon.beaconq);
-+		ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
- 	}
- 	ath9k_ps_restore(sc);
- }
diff --git a/package/mac80211/patches/580-mac80211_redirect_vlan_eap_frames.patch b/package/mac80211/patches/580-mac80211_redirect_vlan_eap_frames.patch
deleted file mode 100644
index 03a4fe5d37..0000000000
--- a/package/mac80211/patches/580-mac80211_redirect_vlan_eap_frames.patch
+++ /dev/null
@@ -1,67 +0,0 @@
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -1582,7 +1582,7 @@ ieee80211_drop_unencrypted_mgmt(struct i
- }
- 
- static int
--__ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
-+__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
- {
- 	struct ieee80211_sub_if_data *sdata = rx->sdata;
- 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-@@ -1590,6 +1590,7 @@ __ieee80211_data_to_8023(struct ieee8021
- 	struct ethhdr *ehdr;
- 	int ret;
- 
-+	*port_control = false;
- 	if (ieee80211_has_a4(hdr->frame_control) &&
- 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
- 		return -1;
-@@ -1608,11 +1609,14 @@ __ieee80211_data_to_8023(struct ieee8021
- 		return -1;
- 
- 	ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
--	if (ret < 0 || !check_port_control)
-+	if (ret < 0)
- 		return ret;
- 
- 	ehdr = (struct ethhdr *) rx->skb->data;
--	if (ehdr->h_proto != rx->sdata->control_port_protocol)
-+	if (ehdr->h_proto == rx->sdata->control_port_protocol)
-+		*port_control = true;
-+
-+	if (check_port_control && !*port_control)
- 		return -1;
- 
- 	return 0;
-@@ -1913,6 +1917,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_
- 	struct net_device *dev = sdata->dev;
- 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
- 	__le16 fc = hdr->frame_control;
-+	bool port_control;
- 	int err;
- 
- 	if (unlikely(!ieee80211_is_data(hdr->frame_control)))
-@@ -1929,13 +1934,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_
- 	    sdata->vif.type == NL80211_IFTYPE_AP)
- 		return RX_DROP_MONITOR;
- 
--	err = __ieee80211_data_to_8023(rx);
-+	err = __ieee80211_data_to_8023(rx, &port_control);
- 	if (unlikely(err))
- 		return RX_DROP_UNUSABLE;
- 
- 	if (!ieee80211_frame_allowed(rx, fc))
- 		return RX_DROP_MONITOR;
- 
-+	if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-+	    unlikely(port_control) && sdata->bss) {
-+		sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
-+				     u.ap);
-+		dev = sdata->dev;
-+		rx->sdata = sdata;
-+	}
-+
- 	rx->skb->dev = dev;
- 
- 	dev->stats.rx_packets++;
diff --git a/package/mac80211/patches/581-mac80211_chantype_change_fix.patch b/package/mac80211/patches/581-mac80211_chantype_change_fix.patch
deleted file mode 100644
index b855d1d809..0000000000
--- a/package/mac80211/patches/581-mac80211_chantype_change_fix.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -77,6 +77,9 @@ bool ieee80211_set_channel_type(struct i
- 		switch (tmp->vif.bss_conf.channel_type) {
- 		case NL80211_CHAN_NO_HT:
- 		case NL80211_CHAN_HT20:
-+			if (superchan > tmp->vif.bss_conf.channel_type)
-+				break;
-+
- 			superchan = tmp->vif.bss_conf.channel_type;
- 			break;
- 		case NL80211_CHAN_HT40PLUS:
diff --git a/package/mac80211/patches/590-ath9k_tid_cleanup_send_bar.patch b/package/mac80211/patches/590-ath9k_tid_cleanup_send_bar.patch
deleted file mode 100644
index 0f58485914..0000000000
--- a/package/mac80211/patches/590-ath9k_tid_cleanup_send_bar.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -166,7 +166,7 @@ static void ath_tx_flush_tid(struct ath_
- 		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, 0);
-+			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
- 		} else {
- 			ath_tx_send_normal(sc, txq, NULL, &bf_head);
- 		}
diff --git a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
index c60d51a21f..ebc7c6bee9 100644
--- a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
+++ b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/mwl8k.c
 +++ b/drivers/net/wireless/mwl8k.c
-@@ -4502,6 +4502,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+@@ -4500,6 +4500,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
  MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
  
  static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
diff --git a/package/mac80211/patches/710-p54_rssi_crash_fix.patch b/package/mac80211/patches/710-p54_rssi_crash_fix.patch
deleted file mode 100644
index 73089cda55..0000000000
--- a/package/mac80211/patches/710-p54_rssi_crash_fix.patch
+++ /dev/null
@@ -1,18 +0,0 @@
---- a/drivers/net/wireless/p54/eeprom.c
-+++ b/drivers/net/wireless/p54/eeprom.c
-@@ -524,10 +524,13 @@ err_data:
- 
- struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *priv, const u16 freq)
- {
--	struct p54_rssi_db_entry *entry = (void *)(priv->rssi_db->data +
--						   priv->rssi_db->offset);
-+	struct p54_rssi_db_entry *entry;
- 	int i, found = -1;
- 
-+	if (!priv->rssi_db)
-+		return &p54_rssi_default;
-+
-+	entry = (void *)(priv->rssi_db->data + priv->rssi_db->offset);
- 	for (i = 0; i < priv->rssi_db->entries; i++) {
- 		if (!same_band(freq, entry[i].freq))
- 			continue;
diff --git a/package/mac80211/patches/720-mac80211-print-restart-warning.patch b/package/mac80211/patches/720-mac80211-print-restart-warning.patch
deleted file mode 100644
index 7a28598533..0000000000
--- a/package/mac80211/patches/720-mac80211-print-restart-warning.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-Index: compat-wireless-2011-02-25/net/mac80211/main.c
-===================================================================
---- compat-wireless-2011-02-25.orig/net/mac80211/main.c	2011-03-07 12:58:14.996968980 +0100
-+++ compat-wireless-2011-02-25/net/mac80211/main.c	2011-03-07 13:03:26.732273903 +0100
-@@ -384,6 +384,9 @@ void ieee80211_restart_hw(struct ieee802
- 
- 	trace_api_restart_hw(local);
- 
-+	wiphy_info(hw->wiphy,
-+		   "Hardware restart was requested\n");
-+
- 	/* use this reason, ieee80211_reconfig will unblock it */
- 	ieee80211_stop_queues_by_reason(hw,
- 		IEEE80211_QUEUE_STOP_REASON_SUSPEND);
diff --git a/package/mac80211/patches/721-mac80211-fix-scan-race.patch b/package/mac80211/patches/721-mac80211-fix-scan-race.patch
deleted file mode 100644
index efc01b1761..0000000000
--- a/package/mac80211/patches/721-mac80211-fix-scan-race.patch
+++ /dev/null
@@ -1,141 +0,0 @@
-Index: compat-wireless-2011-02-25/net/mac80211/scan.c
-===================================================================
---- compat-wireless-2011-02-25.orig/net/mac80211/scan.c	2011-03-07 14:43:55.695666042 +0100
-+++ compat-wireless-2011-02-25/net/mac80211/scan.c	2011-03-07 14:43:57.594439631 +0100
-@@ -258,10 +258,12 @@ static bool ieee80211_prep_hw_scan(struc
- 	return true;
- }
- 
--static bool __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
-+static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
- 				       bool was_hw_scan)
- {
- 	struct ieee80211_local *local = hw_to_local(hw);
-+	bool on_oper_chan;
-+	bool enable_beacons = false;
- 
- 	lockdep_assert_held(&local->mtx);
- 
-@@ -275,12 +277,12 @@ static bool __ieee80211_scan_completed(s
- 		aborted = true;
- 
- 	if (WARN_ON(!local->scan_req))
--		return false;
-+		return;
- 
- 	if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
- 		int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);
- 		if (rc == 0)
--			return false;
-+			return;
- 	}
- 
- 	kfree(local->hw_scan_req);
-@@ -294,26 +296,13 @@ static bool __ieee80211_scan_completed(s
- 	local->scanning = 0;
- 	local->scan_channel = NULL;
- 
--	return true;
--}
--
--static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw,
--					      bool was_hw_scan)
--{
--	struct ieee80211_local *local = hw_to_local(hw);
--	bool on_oper_chan;
--	bool enable_beacons = false;
--
--	mutex_lock(&local->mtx);
- 	on_oper_chan = ieee80211_cfg_on_oper_channel(local);
- 
- 	WARN_ON(local->scanning & (SCAN_SW_SCANNING | SCAN_HW_SCANNING));
- 
--	if (was_hw_scan || !on_oper_chan) {
--		if (WARN_ON(local->scan_channel))
--			local->scan_channel = NULL;
-+	if (was_hw_scan || !on_oper_chan)
- 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
--	} else
-+	else
- 		/* Set power back to normal operating levels. */
- 		ieee80211_hw_config(local, 0);
- 
-@@ -331,7 +320,6 @@ static void __ieee80211_scan_completed_f
- 	}
- 
- 	ieee80211_recalc_idle(local);
--	mutex_unlock(&local->mtx);
- 
- 	ieee80211_mlme_notify_scan_completed(local);
- 	ieee80211_ibss_notify_scan_completed(local);
-@@ -686,12 +674,14 @@ void ieee80211_scan_work(struct work_str
- {
- 	struct ieee80211_local *local =
- 		container_of(work, struct ieee80211_local, scan_work.work);
--	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
-+	struct ieee80211_sub_if_data *sdata;
- 	unsigned long next_delay = 0;
--	bool aborted, hw_scan, finish;
-+	bool aborted, hw_scan;
- 
- 	mutex_lock(&local->mtx);
- 
-+	sdata = local->scan_sdata;
-+
- 	if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
- 		aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
- 		goto out_complete;
-@@ -755,17 +745,11 @@ void ieee80211_scan_work(struct work_str
- 	} while (next_delay == 0);
- 
- 	ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
--	mutex_unlock(&local->mtx);
--	return;
-+	goto out;
- 
- out_complete:
- 	hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
--	finish = __ieee80211_scan_completed(&local->hw, aborted, hw_scan);
--	mutex_unlock(&local->mtx);
--	if (finish)
--		__ieee80211_scan_completed_finish(&local->hw, hw_scan);
--	return;
--
-+	__ieee80211_scan_completed(&local->hw, aborted, hw_scan);
- out:
- 	mutex_unlock(&local->mtx);
- }
-@@ -835,7 +819,6 @@ int ieee80211_request_internal_scan(stru
- void ieee80211_scan_cancel(struct ieee80211_local *local)
- {
- 	bool abortscan;
--	bool finish = false;
- 
- 	/*
- 	 * We are only canceling software scan, or deferred scan that was not
-@@ -855,14 +838,17 @@ void ieee80211_scan_cancel(struct ieee80
- 
- 	mutex_lock(&local->mtx);
- 	abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning);
--	if (abortscan)
--		finish = __ieee80211_scan_completed(&local->hw, true, false);
--	mutex_unlock(&local->mtx);
--
- 	if (abortscan) {
--		/* The scan is canceled, but stop work from being pending */
--		cancel_delayed_work_sync(&local->scan_work);
-+		/*
-+		 * The scan is canceled, but stop work from being pending.
-+		 *
-+		 * If the work is currently running, it must be blocked on
-+		 * the mutex, but we'll set scan_sdata = NULL and it'll
-+		 * simply exit once it acquires the mutex.
-+		 */
-+		cancel_delayed_work(&local->scan_work);
-+		/* and clean up */
-+		__ieee80211_scan_completed(&local->hw, true, false);
- 	}
--	if (finish)
--		__ieee80211_scan_completed_finish(&local->hw, false);
-+	mutex_unlock(&local->mtx);
- }
-- 
cgit v1.2.3