--- /dev/null
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -99,6 +99,7 @@ enum ieee80211_sta_info_flags {
+ * @dialog_token: dialog token for aggregation session
+ * @timeout: session timeout value to be filled in ADDBA requests
+ * @state: session state (see above)
++ * @last_tx: jiffies of last tx activity
+ * @stop_initiator: initiator of a session stop
+ * @tx_stop: TX DelBA frame when stopping
+ * @buf_size: reorder buffer size at receiver
+@@ -120,6 +121,7 @@ struct tid_ampdu_tx {
+ struct timer_list addba_resp_timer;
+ struct sk_buff_head pending;
+ unsigned long state;
++ unsigned long last_tx;
+ u16 timeout;
+ u8 dialog_token;
+ u8 stop_initiator;
+@@ -137,6 +139,7 @@ struct tid_ampdu_tx {
+ * @reorder_time: jiffies when skb was added
+ * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
+ * @reorder_timer: releases expired frames from the reorder buffer.
++ * @last_rx: jiffies of last rx activity
+ * @head_seq_num: head sequence number in reordering buffer.
+ * @stored_mpdu_num: number of MPDUs in reordering buffer
+ * @ssn: Starting Sequence Number expected to be aggregated.
+@@ -161,6 +164,7 @@ struct tid_ampdu_rx {
+ unsigned long *reorder_time;
+ struct timer_list session_timer;
+ struct timer_list reorder_timer;
++ unsigned long last_rx;
+ u16 head_seq_num;
+ u16 stored_mpdu_num;
+ u16 ssn;
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1120,8 +1120,7 @@ static bool ieee80211_tx_prep_agg(struct
+
+ /* reset session timer */
+ if (reset_agg_timer && tid_tx->timeout)
+- mod_timer(&tid_tx->session_timer,
+- TU_TO_EXP_TIME(tid_tx->timeout));
++ tid_tx->last_tx = jiffies;
+
+ return queued;
+ }
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -52,7 +52,8 @@ struct ieee80211_local;
+ * increased memory use (about 2 kB of RAM per entry). */
+ #define IEEE80211_FRAGMENT_MAX 4
+
+-#define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024))
++#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
++#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
+
+ #define IEEE80211_DEFAULT_UAPSD_QUEUES \
+ (IEEE80211_WMM_IE_STA_QOSINFO_AC_BK | \
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -436,6 +436,18 @@ static void sta_tx_agg_session_timer_exp
+ u8 *timer_to_id = ptid - *ptid;
+ struct sta_info *sta = container_of(timer_to_id, struct sta_info,
+ timer_to_tid[0]);
++ struct tid_ampdu_tx *tid_tx;
++ unsigned long timeout;
++
++ tid_tx = rcu_dereference_protected_tid_tx(sta, *ptid);
++ if (!tid_tx)
++ return;
++
++ timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout);
++ if (time_is_after_jiffies(timeout)) {
++ mod_timer(&tid_tx->session_timer, timeout);
++ return;
++ }
+
+ #ifdef CONFIG_MAC80211_HT_DEBUG
+ printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid);
+@@ -908,9 +920,11 @@ void ieee80211_process_addba_resp(struct
+
+ sta->ampdu_mlme.addba_req_num[tid] = 0;
+
+- if (tid_tx->timeout)
++ if (tid_tx->timeout) {
+ mod_timer(&tid_tx->session_timer,
+ TU_TO_EXP_TIME(tid_tx->timeout));
++ tid_tx->last_tx = jiffies;
++ }
+
+ } else {
+ ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR,
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -141,6 +141,18 @@ static void sta_rx_agg_session_timer_exp
+ u8 *timer_to_id = ptid - *ptid;
+ struct sta_info *sta = container_of(timer_to_id, struct sta_info,
+ timer_to_tid[0]);
++ struct tid_ampdu_rx *tid_rx;
++ unsigned long timeout;
++
++ tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]);
++ if (!tid_rx)
++ return;
++
++ timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout);
++ if (time_is_after_jiffies(timeout)) {
++ mod_timer(&tid_rx->session_timer, timeout);
++ return;
++ }
+
+ #ifdef CONFIG_MAC80211_HT_DEBUG
+ printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
+@@ -336,8 +348,10 @@ void ieee80211_process_addba_request(str
+ /* activate it for RX */
+ rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);
+
+- if (timeout)
++ if (timeout) {
+ mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout));
++ tid_agg_rx->last_rx = jiffies;
++ }
+
+ end:
+ mutex_unlock(&sta->ampdu_mlme.mtx);
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -793,8 +793,7 @@ static void ieee80211_rx_reorder_ampdu(s
+
+ /* reset session timer */
+ if (tid_agg_rx->timeout)
+- mod_timer(&tid_agg_rx->session_timer,
+- TU_TO_EXP_TIME(tid_agg_rx->timeout));
++ tid_agg_rx->last_rx = jiffies;
+
+ /* if this mpdu is fragmented - terminate rx aggregation session */
+ sc = le16_to_cpu(hdr->seq_ctrl);