From: Felix Fietkau 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.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=commitdiff_plain;hb=5f679d31df5f9bdf4a1454c32209ede6f958c7b7 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);