diff options
author | Sara Sharon <sara.sharon@intel.com> | 2015-12-08 12:09:05 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2016-02-24 03:04:16 -0500 |
commit | 412a6d800c7380c1b87c11080c7da905c27cfea8 (patch) | |
tree | 6ebbfc270d12f9da48558c0d445fae32495c8c73 | |
parent | 50ea05efaf3bed7dd34bcc2635a8b3f53bd0ccc1 (diff) |
mac80211: support hw managing reorder logic
Enable driver to manage the reordering logic itself.
This is needed for example for the iwlwifi driver that
will support hardware assisted reordering.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | include/net/mac80211.h | 6 | ||||
-rw-r--r-- | net/mac80211/agg-rx.c | 24 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 1 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 21 |
4 files changed, 41 insertions, 11 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 6c9c559394b0..ee6305a52251 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1929,6 +1929,11 @@ struct ieee80211_txq { | |||
1929 | * by just its MAC address; this prevents, for example, the same station | 1929 | * by just its MAC address; this prevents, for example, the same station |
1930 | * from connecting to two virtual AP interfaces at the same time. | 1930 | * from connecting to two virtual AP interfaces at the same time. |
1931 | * | 1931 | * |
1932 | * @IEEE80211_HW_SUPPORTS_REORDERING_BUFFER: Hardware (or driver) manages the | ||
1933 | * reordering buffer internally, guaranteeing mac80211 receives frames in | ||
1934 | * order and does not need to manage its own reorder buffer or BA session | ||
1935 | * timeout. | ||
1936 | * | ||
1932 | * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays | 1937 | * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays |
1933 | */ | 1938 | */ |
1934 | enum ieee80211_hw_flags { | 1939 | enum ieee80211_hw_flags { |
@@ -1965,6 +1970,7 @@ enum ieee80211_hw_flags { | |||
1965 | IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU, | 1970 | IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU, |
1966 | IEEE80211_HW_BEACON_TX_STATUS, | 1971 | IEEE80211_HW_BEACON_TX_STATUS, |
1967 | IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR, | 1972 | IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR, |
1973 | IEEE80211_HW_SUPPORTS_REORDERING_BUFFER, | ||
1968 | 1974 | ||
1969 | /* keep last, obviously */ | 1975 | /* keep last, obviously */ |
1970 | NUM_IEEE80211_HW_FLAGS | 1976 | NUM_IEEE80211_HW_FLAGS |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index ec80db7c955c..2ab54791281d 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -76,10 +76,11 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
76 | tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid], | 76 | tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid], |
77 | lockdep_is_held(&sta->ampdu_mlme.mtx)); | 77 | lockdep_is_held(&sta->ampdu_mlme.mtx)); |
78 | 78 | ||
79 | if (!tid_rx) | 79 | if (!test_bit(tid, sta->ampdu_mlme.agg_session_valid)) |
80 | return; | 80 | return; |
81 | 81 | ||
82 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); | 82 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); |
83 | __clear_bit(tid, sta->ampdu_mlme.agg_session_valid); | ||
83 | 84 | ||
84 | ht_dbg(sta->sdata, | 85 | ht_dbg(sta->sdata, |
85 | "Rx BA session stop requested for %pM tid %u %s reason: %d\n", | 86 | "Rx BA session stop requested for %pM tid %u %s reason: %d\n", |
@@ -97,6 +98,13 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
97 | ieee80211_send_delba(sta->sdata, sta->sta.addr, | 98 | ieee80211_send_delba(sta->sdata, sta->sta.addr, |
98 | tid, WLAN_BACK_RECIPIENT, reason); | 99 | tid, WLAN_BACK_RECIPIENT, reason); |
99 | 100 | ||
101 | /* | ||
102 | * return here in case tid_rx is not assigned - which will happen if | ||
103 | * IEEE80211_HW_SUPPORTS_REORDERING_BUFFER is set. | ||
104 | */ | ||
105 | if (!tid_rx) | ||
106 | return; | ||
107 | |||
100 | del_timer_sync(&tid_rx->session_timer); | 108 | del_timer_sync(&tid_rx->session_timer); |
101 | 109 | ||
102 | /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */ | 110 | /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */ |
@@ -297,7 +305,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, | |||
297 | /* examine state machine */ | 305 | /* examine state machine */ |
298 | mutex_lock(&sta->ampdu_mlme.mtx); | 306 | mutex_lock(&sta->ampdu_mlme.mtx); |
299 | 307 | ||
300 | if (sta->ampdu_mlme.tid_rx[tid]) { | 308 | if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) { |
301 | ht_dbg_ratelimited(sta->sdata, | 309 | ht_dbg_ratelimited(sta->sdata, |
302 | "unexpected AddBA Req from %pM on tid %u\n", | 310 | "unexpected AddBA Req from %pM on tid %u\n", |
303 | sta->sta.addr, tid); | 311 | sta->sta.addr, tid); |
@@ -308,6 +316,16 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, | |||
308 | false); | 316 | false); |
309 | } | 317 | } |
310 | 318 | ||
319 | if (ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) { | ||
320 | ret = drv_ampdu_action(local, sta->sdata, ¶ms); | ||
321 | ht_dbg(sta->sdata, | ||
322 | "Rx A-MPDU request on %pM tid %d result %d\n", | ||
323 | sta->sta.addr, tid, ret); | ||
324 | if (!ret) | ||
325 | status = WLAN_STATUS_SUCCESS; | ||
326 | goto end; | ||
327 | } | ||
328 | |||
311 | /* prepare A-MPDU MLME for Rx aggregation */ | 329 | /* prepare A-MPDU MLME for Rx aggregation */ |
312 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL); | 330 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL); |
313 | if (!tid_agg_rx) | 331 | if (!tid_agg_rx) |
@@ -369,6 +387,8 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, | |||
369 | } | 387 | } |
370 | 388 | ||
371 | end: | 389 | end: |
390 | if (status == WLAN_STATUS_SUCCESS) | ||
391 | __set_bit(tid, sta->ampdu_mlme.agg_session_valid); | ||
372 | mutex_unlock(&sta->ampdu_mlme.mtx); | 392 | mutex_unlock(&sta->ampdu_mlme.mtx); |
373 | 393 | ||
374 | end_no_lock: | 394 | end_no_lock: |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index abbdff03ce92..e433d0c97e86 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -126,6 +126,7 @@ static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = { | |||
126 | FLAG(SUPPORTS_AMSDU_IN_AMPDU), | 126 | FLAG(SUPPORTS_AMSDU_IN_AMPDU), |
127 | FLAG(BEACON_TX_STATUS), | 127 | FLAG(BEACON_TX_STATUS), |
128 | FLAG(NEEDS_UNIQUE_STA_ADDR), | 128 | FLAG(NEEDS_UNIQUE_STA_ADDR), |
129 | FLAG(SUPPORTS_REORDERING_BUFFER), | ||
129 | 130 | ||
130 | /* keep last for the build bug below */ | 131 | /* keep last for the build bug below */ |
131 | (void *)0x1 | 132 | (void *)0x1 |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d6051629ed15..f4d38994ecee 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2002-2005, Devicescape Software, Inc. | 2 | * Copyright 2002-2005, Devicescape Software, Inc. |
3 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 3 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
4 | * Copyright(c) 2015 Intel Deutschland GmbH | ||
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -212,20 +213,21 @@ struct tid_ampdu_rx { | |||
212 | /** | 213 | /** |
213 | * struct sta_ampdu_mlme - STA aggregation information. | 214 | * struct sta_ampdu_mlme - STA aggregation information. |
214 | * | 215 | * |
216 | * @mtx: mutex to protect all TX data (except non-NULL assignments | ||
217 | * to tid_tx[idx], which are protected by the sta spinlock) | ||
218 | * tid_start_tx is also protected by sta->lock. | ||
215 | * @tid_rx: aggregation info for Rx per TID -- RCU protected | 219 | * @tid_rx: aggregation info for Rx per TID -- RCU protected |
216 | * @tid_tx: aggregation info for Tx per TID | ||
217 | * @tid_start_tx: sessions where start was requested | ||
218 | * @addba_req_num: number of times addBA request has been sent. | ||
219 | * @last_addba_req_time: timestamp of the last addBA request. | ||
220 | * @dialog_token_allocator: dialog token enumerator for each new session; | ||
221 | * @work: work struct for starting/stopping aggregation | ||
222 | * @tid_rx_timer_expired: bitmap indicating on which TIDs the | 220 | * @tid_rx_timer_expired: bitmap indicating on which TIDs the |
223 | * RX timer expired until the work for it runs | 221 | * RX timer expired until the work for it runs |
224 | * @tid_rx_stop_requested: bitmap indicating which BA sessions per TID the | 222 | * @tid_rx_stop_requested: bitmap indicating which BA sessions per TID the |
225 | * driver requested to close until the work for it runs | 223 | * driver requested to close until the work for it runs |
226 | * @mtx: mutex to protect all TX data (except non-NULL assignments | 224 | * @agg_session_valid: bitmap indicating which TID has a rx BA session open on |
227 | * to tid_tx[idx], which are protected by the sta spinlock) | 225 | * @work: work struct for starting/stopping aggregation |
228 | * tid_start_tx is also protected by sta->lock. | 226 | * @tid_tx: aggregation info for Tx per TID |
227 | * @tid_start_tx: sessions where start was requested | ||
228 | * @last_addba_req_time: timestamp of the last addBA request. | ||
229 | * @addba_req_num: number of times addBA request has been sent. | ||
230 | * @dialog_token_allocator: dialog token enumerator for each new session; | ||
229 | */ | 231 | */ |
230 | struct sta_ampdu_mlme { | 232 | struct sta_ampdu_mlme { |
231 | struct mutex mtx; | 233 | struct mutex mtx; |
@@ -233,6 +235,7 @@ struct sta_ampdu_mlme { | |||
233 | struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS]; | 235 | struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS]; |
234 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; | 236 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; |
235 | unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; | 237 | unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; |
238 | unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; | ||
236 | /* tx */ | 239 | /* tx */ |
237 | struct work_struct work; | 240 | struct work_struct work; |
238 | struct tid_ampdu_tx __rcu *tid_tx[IEEE80211_NUM_TIDS]; | 241 | struct tid_ampdu_tx __rcu *tid_tx[IEEE80211_NUM_TIDS]; |