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-rx.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-rx.c')
-rw-r--r-- | net/mac80211/agg-rx.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 64d3ce5ea1a0..a070d4f460ea 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -142,6 +142,18 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
142 | u8 *timer_to_id = ptid - *ptid; | 142 | u8 *timer_to_id = ptid - *ptid; |
143 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | 143 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, |
144 | timer_to_tid[0]); | 144 | timer_to_tid[0]); |
145 | struct tid_ampdu_rx *tid_rx; | ||
146 | unsigned long timeout; | ||
147 | |||
148 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]); | ||
149 | if (!tid_rx) | ||
150 | return; | ||
151 | |||
152 | timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout); | ||
153 | if (time_is_after_jiffies(timeout)) { | ||
154 | mod_timer(&tid_rx->session_timer, timeout); | ||
155 | return; | ||
156 | } | ||
145 | 157 | ||
146 | #ifdef CONFIG_MAC80211_HT_DEBUG | 158 | #ifdef CONFIG_MAC80211_HT_DEBUG |
147 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 159 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
@@ -291,7 +303,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
291 | /* rx timer */ | 303 | /* rx timer */ |
292 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; | 304 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; |
293 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 305 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
294 | init_timer(&tid_agg_rx->session_timer); | 306 | init_timer_deferrable(&tid_agg_rx->session_timer); |
295 | 307 | ||
296 | /* rx reorder timer */ | 308 | /* rx reorder timer */ |
297 | tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; | 309 | tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; |
@@ -335,8 +347,10 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
335 | /* activate it for RX */ | 347 | /* activate it for RX */ |
336 | rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); | 348 | rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); |
337 | 349 | ||
338 | if (timeout) | 350 | if (timeout) { |
339 | mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); | 351 | mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); |
352 | tid_agg_rx->last_rx = jiffies; | ||
353 | } | ||
340 | 354 | ||
341 | end: | 355 | end: |
342 | mutex_unlock(&sta->ampdu_mlme.mtx); | 356 | mutex_unlock(&sta->ampdu_mlme.mtx); |