From: Felix Fietkau <nbd@openwrt.org>
Date: Sat, 17 Mar 2012 22:34:58 +0000 (+0000)
Subject: mac80211: reduce cpu load by optimizing aggregation session timeout handling
X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=5f679d31df5f9bdf4a1454c32209ede6f958c7b7;p=openwrt%2Fsvn-archive%2Farchive.git

mac80211: reduce cpu load by optimizing aggregation session timeout handling

SVN-Revision: 30968
---

diff --git a/package/mac80211/patches/565-mac80211_optimize_aggregation_timeout.patch b/package/mac80211/patches/565-mac80211_optimize_aggregation_timeout.patch
new file mode 100644
index 0000000000..81ae82c2ec
--- /dev/null
+++ b/package/mac80211/patches/565-mac80211_optimize_aggregation_timeout.patch
@@ -0,0 +1,137 @@
+--- 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);