aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-rx.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2012-03-18 17:58:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-09 16:09:36 -0400
commit12d3952fc4a1cd96234bc7023bf7eefeb0bb6355 (patch)
tree5c3437e1f996a5c772b286530a3fce547a7d40f2 /net/mac80211/agg-rx.c
parentfcb2c9e1025cd529890303ffbde813a98cdffed4 (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.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 64d3ce5ea1a..a070d4f460e 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
341end: 355end:
342 mutex_unlock(&sta->ampdu_mlme.mtx); 356 mutex_unlock(&sta->ampdu_mlme.mtx);