mac80211: reduce cpu load by optimizing aggregation session timeout handling
authorFelix Fietkau <nbd@openwrt.org>
Sat, 17 Mar 2012 22:34:58 +0000 (22:34 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 17 Mar 2012 22:34:58 +0000 (22:34 +0000)
SVN-Revision: 30968

package/mac80211/patches/565-mac80211_optimize_aggregation_timeout.patch [new file with mode: 0644]

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 (file)
index 0000000..81ae82c
--- /dev/null
@@ -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);