aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/status.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-08-28 15:11:01 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-13 15:42:30 -0400
commitf0425beda4d404a6e751439b562100b902ba9c98 (patch)
tree5a8966c3172557e80fa0a4903ade8a76e5d21415 /net/mac80211/status.c
parent765b07e46725287ceb1be648b6cb5988fbb585f2 (diff)
mac80211: retry sending failed BAR frames later instead of tearing down aggr
Unfortunately failed BAR tx attempts happen more frequently than I expected, and the resulting aggregation teardowns cause performance issues, as the aggregation session does not always get re-established properly. Instead of tearing down the entire aggr session, we can simply store the SSN of the last failed BAR tx attempt, wait for the first successful tx status event, and then send another BAR with the same SSN. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Cc: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r--net/mac80211/status.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index e51bd2a1a073..ba405bc4f812 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -127,12 +127,32 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
127 dev_kfree_skb(skb); 127 dev_kfree_skb(skb);
128} 128}
129 129
130static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
131{
132 struct tid_ampdu_tx *tid_tx;
133
134 tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
135 if (!tid_tx || !tid_tx->bar_pending)
136 return;
137
138 tid_tx->bar_pending = false;
139 ieee80211_send_bar(sta->sdata, addr, tid, tid_tx->failed_bar_ssn);
140}
141
130static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) 142static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
131{ 143{
132 struct ieee80211_mgmt *mgmt = (void *) skb->data; 144 struct ieee80211_mgmt *mgmt = (void *) skb->data;
133 struct ieee80211_local *local = sta->local; 145 struct ieee80211_local *local = sta->local;
134 struct ieee80211_sub_if_data *sdata = sta->sdata; 146 struct ieee80211_sub_if_data *sdata = sta->sdata;
135 147
148 if (ieee80211_is_data_qos(mgmt->frame_control)) {
149 struct ieee80211_hdr *hdr = (void *) skb->data;
150 u8 *qc = ieee80211_get_qos_ctl(hdr);
151 u16 tid = qc[0] & 0xf;
152
153 ieee80211_check_pending_bar(sta, hdr->addr1, tid);
154 }
155
136 if (ieee80211_is_action(mgmt->frame_control) && 156 if (ieee80211_is_action(mgmt->frame_control) &&
137 sdata->vif.type == NL80211_IFTYPE_STATION && 157 sdata->vif.type == NL80211_IFTYPE_STATION &&
138 mgmt->u.action.category == WLAN_CATEGORY_HT && 158 mgmt->u.action.category == WLAN_CATEGORY_HT &&
@@ -161,6 +181,18 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
161 } 181 }
162} 182}
163 183
184static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
185{
186 struct tid_ampdu_tx *tid_tx;
187
188 tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
189 if (!tid_tx)
190 return;
191
192 tid_tx->failed_bar_ssn = ssn;
193 tid_tx->bar_pending = true;
194}
195
164/* 196/*
165 * Use a static threshold for now, best value to be determined 197 * Use a static threshold for now, best value to be determined
166 * by testing ... 198 * by testing ...
@@ -254,10 +286,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
254 */ 286 */
255 bar = (struct ieee80211_bar *) skb->data; 287 bar = (struct ieee80211_bar *) skb->data;
256 if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) { 288 if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
289 u16 ssn = le16_to_cpu(bar->start_seq_num);
290
257 tid = (bar->control & 291 tid = (bar->control &
258 IEEE80211_BAR_CTRL_TID_INFO_MASK) >> 292 IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
259 IEEE80211_BAR_CTRL_TID_INFO_SHIFT; 293 IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
260 ieee80211_stop_tx_ba_session(&sta->sta, tid); 294
295 ieee80211_set_bar_pending(sta, tid, ssn);
261 } 296 }
262 } 297 }
263 298