diff --git a/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch b/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch
index 40aca6dd0345c7a46376bff66282763d63bfb1e0..475d32943bb68aa60a264e7c461d9dec17167880 100644
--- a/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch
+++ b/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch
@@ -293,7 +293,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  		atomic_dec(&ps->num_sta_ps);
  	}
  
-+	if (sta->txq) {
++	if (sta->txqi) {
 +		for (i = 0; i < IEEE80211_NUM_TIDS; i++)
 +			ieee80211_flush_tx_queue(local, sta->sta.txq[i]);
 +	}
@@ -305,7 +305,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  
  	sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
  
-+	kfree(sta->txq);
++	kfree(sta->txqi);
  	kfree(rcu_dereference_raw(sta->sta.rates));
  	kfree(sta);
  }
@@ -339,7 +339,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 +		if (!txq_data)
 +			goto free;
 +
-+		sta->txq = txq_data;
++		sta->txqi = txq_data;
 +		for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
 +			struct txq_info *txq = txq_data + i * size;
 +			ieee80211_init_tx_queue(sdata, sta, txq, i);
@@ -367,20 +367,130 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  	return sta;
 +
 +free_txq:
-+	kfree(sta->txq);
++	kfree(sta->txqi);
 +free:
 +	kfree(sta);
 +	return NULL;
  }
  
  static int sta_info_insert_check(struct sta_info *sta)
+@@ -640,6 +667,8 @@ static void __sta_info_recalc_tim(struct
+ 
+ 		indicate_tim |=
+ 			sta->driver_buffered_tids & tids;
++		indicate_tim |=
++			sta->txq_buffered_tids & tids;
+ 	}
+ 
+  done:
+@@ -1071,7 +1100,7 @@ void ieee80211_sta_ps_deliver_wakeup(str
+ 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+ 	struct ieee80211_local *local = sdata->local;
+ 	struct sk_buff_head pending;
+-	int filtered = 0, buffered = 0, ac;
++	int filtered = 0, buffered = 0, ac, i;
+ 	unsigned long flags;
+ 	struct ps_data *ps;
+ 
+@@ -1090,10 +1119,25 @@ void ieee80211_sta_ps_deliver_wakeup(str
+ 
+ 	BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
+ 	sta->driver_buffered_tids = 0;
++	sta->txq_buffered_tids = 0;
+ 
+ 	if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
+ 		drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
+ 
++	if (sta->txqi) {
++		for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
++			struct txq_info *txqi;
++
++			txqi = container_of(sta->sta.txq[i], struct txq_info,
++					    txq);
++
++			if (!skb_queue_len(&txqi->queue))
++				continue;
++
++			drv_wake_tx_queue(local, txqi);
++		}
++	}
++
+ 	skb_queue_head_init(&pending);
+ 
+ 	/* sync with ieee80211_tx_h_unicast_ps_buf */
+@@ -1254,7 +1298,7 @@ ieee80211_sta_ps_deliver_response(struct
+ 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+ 	struct ieee80211_local *local = sdata->local;
+ 	bool more_data = false;
+-	int ac;
++	int ac, tid;
+ 	unsigned long driver_release_tids = 0;
+ 	struct sk_buff_head frames;
+ 
+@@ -1275,8 +1319,10 @@ ieee80211_sta_ps_deliver_response(struct
+ 		/* if we already have frames from software, then we can't also
+ 		 * release from hardware queues
+ 		 */
+-		if (skb_queue_empty(&frames))
++		if (skb_queue_empty(&frames)) {
+ 			driver_release_tids |= sta->driver_buffered_tids & tids;
++			driver_release_tids |= sta->txq_buffered_tids & tids;
++		}
+ 
+ 		if (driver_release_tids) {
+ 			/* If the driver has data on more than one TID then
+@@ -1447,6 +1493,8 @@ ieee80211_sta_ps_deliver_response(struct
+ 
+ 		sta_info_recalc_tim(sta);
+ 	} else {
++		unsigned long tids = sta->txq_buffered_tids & driver_release_tids;
++
+ 		/*
+ 		 * We need to release a frame that is buffered somewhere in the
+ 		 * driver ... it'll have to handle that.
+@@ -1466,8 +1514,25 @@ ieee80211_sta_ps_deliver_response(struct
+ 		 * that the TID(s) became empty before returning here from the
+ 		 * release function.
+ 		 * Either way, however, when the driver tells us that the TID(s)
+-		 * became empty we'll do the TIM recalculation.
++		 * became empty or we find that a txq became empty, we'll do the
++		 * TIM recalculation.
+ 		 */
++
++		if (!sta->txqi)
++			return;
++
++		for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
++			struct txq_info *txqi;
++
++			txqi = container_of(sta->sta.txq[tid], struct txq_info,
++					    txq);
++
++			if (!(tids & BIT(tid)) || skb_queue_len(&txqi->queue))
++				continue;
++
++			sta_info_recalc_tim(sta);
++			break;
++		}
+ 	}
+ }
+ 
 --- a/net/mac80211/sta_info.h
 +++ b/net/mac80211/sta_info.h
-@@ -368,6 +368,7 @@ struct sta_info {
+@@ -274,6 +274,7 @@ struct sta_ampdu_mlme {
+  *	entered power saving state, these are also delivered to
+  *	the station when it leaves powersave or polls for frames
+  * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on
++ * @txq_buffered_tids: bitmap of TIDs that mac80211 has txq data buffered on
+  * @rx_packets: Number of MSDUs received from this STA
+  * @rx_bytes: Number of bytes received from this STA
+  * @last_rx: time (in jiffies) when last frame was received from this STA
+@@ -368,6 +369,8 @@ struct sta_info {
  	struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
  	struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
  	unsigned long driver_buffered_tids;
-+	struct txq_info *txq;
++	unsigned long txq_buffered_tids;
++	struct txq_info *txqi;
  
  	/* Updated from RX path only, no locking requirements */
  	unsigned long rx_packets;
@@ -429,7 +539,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  #define TRACE_SYSTEM mac80211_msg
 --- a/net/mac80211/tx.c
 +++ b/net/mac80211/tx.c
-@@ -1201,13 +1201,76 @@ ieee80211_tx_prepare(struct ieee80211_su
+@@ -1201,13 +1201,80 @@ ieee80211_tx_prepare(struct ieee80211_su
  	return TX_CONTINUE;
  }
  
@@ -440,6 +550,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 +{
 +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
++	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 +	struct ieee80211_tx_control control = {
 +		.sta = pubsta
 +	};
@@ -447,6 +558,9 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 +	struct txq_info *txqi;
 +	u8 ac;
 +
++	if (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)
++		goto tx_normal;
++
 +	if (ieee80211_is_mgmt(hdr->frame_control) ||
 +	    ieee80211_is_ctl(hdr->frame_control))
 +		goto tx_normal;
@@ -507,7 +621,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  	struct sk_buff *skb, *tmp;
  	unsigned long flags;
  
-@@ -1265,10 +1328,9 @@ static bool ieee80211_tx_frags(struct ie
+@@ -1265,10 +1332,9 @@ static bool ieee80211_tx_frags(struct ie
  		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
  
  		info->control.vif = vif;
@@ -570,3 +684,34 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 +
 +	atomic_sub(n, &sdata->txqs_len[txq->ac]);
 +}
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1176,6 +1176,7 @@ static void sta_ps_start(struct sta_info
+ 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+ 	struct ieee80211_local *local = sdata->local;
+ 	struct ps_data *ps;
++	int tid;
+ 
+ 	if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+ 	    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+@@ -1189,6 +1190,20 @@ static void sta_ps_start(struct sta_info
+ 		drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
+ 	ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
+ 	       sta->sta.addr, sta->sta.aid);
++
++	if (!sta->txqi)
++		return;
++
++	for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
++		struct txq_info *txqi;
++
++		txqi = container_of(sta->sta.txq[tid], struct txq_info, txq);
++
++		if (!skb_queue_len(&txqi->queue))
++			set_bit(tid, &sta->txq_buffered_tids);
++		else
++			clear_bit(tid, &sta->txq_buffered_tids);
++	}
+ }
+ 
+ static void sta_ps_end(struct sta_info *sta)
diff --git a/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch b/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch
index 6b6903215dbb755f84753bc130b820f3edc1bced..3acc529bb9320034ca057569077c4c3a48119cf7 100644
--- a/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch
+++ b/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch
@@ -115,7 +115,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  
 --- a/net/mac80211/sta_info.h
 +++ b/net/mac80211/sta_info.h
-@@ -348,6 +348,7 @@ struct sta_info {
+@@ -349,6 +349,7 @@ struct sta_info {
  	u8 ptk_idx;
  	struct rate_control_ref *rate_ctrl;
  	void *rate_ctrl_priv;