diff options
author | Felix Fietkau <nbd@openwrt.org> | 2012-03-18 17:58:06 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-04-09 16:09:36 -0400 |
commit | 12d3952fc4a1cd96234bc7023bf7eefeb0bb6355 (patch) | |
tree | 5c3437e1f996a5c772b286530a3fce547a7d40f2 /net/mac80211/agg-tx.c | |
parent | fcb2c9e1025cd529890303ffbde813a98cdffed4 (diff) |
mac80211: optimize aggregation session timeout handling
Calling mod_timer from the rx/tx hotpath is somewhat expensive, and the
timeout doesn't need to be so precise.
Switch to a different strategy: Schedule the timer initially, store jiffies
of all last rx/tx activity which would previously modify the timer, and
let the timer re-arm itself after checking the last rx/tx timestamp.
Make the session timers deferrable to avoid causing extra wakeups on systems
running on battery.
This visibly reduces CPU load under high network load on small embedded
systems.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r-- | net/mac80211/agg-tx.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 76be61744198..9628a1892441 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -417,6 +417,18 @@ static void sta_tx_agg_session_timer_expired(unsigned long data) | |||
417 | u8 *timer_to_id = ptid - *ptid; | 417 | u8 *timer_to_id = ptid - *ptid; |
418 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | 418 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, |
419 | timer_to_tid[0]); | 419 | timer_to_tid[0]); |
420 | struct tid_ampdu_tx *tid_tx; | ||
421 | unsigned long timeout; | ||
422 | |||
423 | tid_tx = rcu_dereference_protected_tid_tx(sta, *ptid); | ||
424 | if (!tid_tx) | ||
425 | return; | ||
426 | |||
427 | timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout); | ||
428 | if (time_is_after_jiffies(timeout)) { | ||
429 | mod_timer(&tid_tx->session_timer, timeout); | ||
430 | return; | ||
431 | } | ||
420 | 432 | ||
421 | #ifdef CONFIG_MAC80211_HT_DEBUG | 433 | #ifdef CONFIG_MAC80211_HT_DEBUG |
422 | printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); | 434 | printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); |
@@ -542,7 +554,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
542 | /* tx timer */ | 554 | /* tx timer */ |
543 | tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; | 555 | tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; |
544 | tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 556 | tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
545 | init_timer(&tid_tx->session_timer); | 557 | init_timer_deferrable(&tid_tx->session_timer); |
546 | 558 | ||
547 | /* assign a dialog token */ | 559 | /* assign a dialog token */ |
548 | sta->ampdu_mlme.dialog_token_allocator++; | 560 | sta->ampdu_mlme.dialog_token_allocator++; |
@@ -884,9 +896,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
884 | 896 | ||
885 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 897 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
886 | 898 | ||
887 | if (tid_tx->timeout) | 899 | if (tid_tx->timeout) { |
888 | mod_timer(&tid_tx->session_timer, | 900 | mod_timer(&tid_tx->session_timer, |
889 | TU_TO_EXP_TIME(tid_tx->timeout)); | 901 | TU_TO_EXP_TIME(tid_tx->timeout)); |
902 | tid_tx->last_tx = jiffies; | ||
903 | } | ||
890 | 904 | ||
891 | } else { | 905 | } else { |
892 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, | 906 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, |