History

mac80211: fix offloaded BA session traffic after hw restart

When starting an offloaded BA session it is unknown what starting sequence number should be used. Using last_seq worked in most cases except after hw restart. When hw restart is requested last_seq is (rightfully so) kept unmodified. This ended up with BA sessions being restarted with an aribtrary BA window values resulting in dropped frames until sequence numbers caught up. Instead of last_seq pick seqno of a first Rxed frame of a given BA session. This fixes stalled traffic after hw restart with offloaded BA sessions (currently only ath10k).

Michal Kazior committed 12 years ago

Commit 4549cf21 parent d0616615 files · +20 −14Browse files

Unified · Split

5 files
  1. net/mac80211/agg-rx.c +3 −2
  2. net/mac80211/ieee80211_i.h +1 −1
  3. net/mac80211/iface.c +3 −11
  4. net/mac80211/rx.c +10 −0
  5. net/mac80211/sta_info.h +3 −0
net/mac80211/agg-rx.c+3−2
@@ -227,7 +227,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d · 226 unmodified lines
227227 void __ieee80211_start_rx_ba_session(struct sta_info *sta,
228228 u8 dialog_token, u16 timeout,
229229 u16 start_seq_num, u16 ba_policy, u16 tid,
230− u16 buf_size, bool tx)
230+ u16 buf_size, bool tx, bool auto_seq)
231231 {
232232 struct ieee80211_local *local = sta->sdata->local;
233233 struct tid_ampdu_rx *tid_agg_rx;
@@ -326,6 +326,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, · 92 unmodified lines
326326 tid_agg_rx->buf_size = buf_size;
327327 tid_agg_rx->timeout = timeout;
328328 tid_agg_rx->stored_mpdu_num = 0;
329+ tid_agg_rx->auto_seq = auto_seq;
329330 status = WLAN_STATUS_SUCCESS;
330331
331332 /* activate it for RX */
@@ -367,7 +368,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, · 35 unmodified lines
367368
368369 __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
369370 start_seq_num, ba_policy, tid,
370− buf_size, true);
371+ buf_size, true, false);
371372 }
372373
373374 void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
net/mac80211/ieee80211_i.h+1−1
@@ -1587,7 +1587,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, · 1586 unmodified lines
15871587 void __ieee80211_start_rx_ba_session(struct sta_info *sta,
15881588 u8 dialog_token, u16 timeout,
15891589 u16 start_seq_num, u16 ba_policy, u16 tid,
1590− u16 buf_size, bool tx);
1590+ u16 buf_size, bool tx, bool auto_seq);
15911591 void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
15921592 enum ieee80211_agg_stop_reason reason);
15931593 void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
net/mac80211/iface.c+3−11
@@ -1172,19 +1172,11 @@ static void ieee80211_iface_work(struct work_struct *work) · 1171 unmodified lines
11721172 rx_agg = (void *)&skb->cb;
11731173 mutex_lock(&local->sta_mtx);
11741174 sta = sta_info_get_bss(sdata, rx_agg->addr);
1175− if (sta) {
1176− u16 last_seq;
1177−
1178− last_seq = le16_to_cpu(
1179− sta->last_seq_ctrl[rx_agg->tid]);
1180−
1175+ if (sta)
11811176 __ieee80211_start_rx_ba_session(sta,
1182− 0, 0,
1183− ieee80211_sn_inc(last_seq),
1184− 1, rx_agg->tid,
1177+ 0, 0, 0, 1, rx_agg->tid,
11851178 IEEE80211_MAX_AMPDU_BUF,
1186− false);
1187− }
1179+ false, true);
11881180 mutex_unlock(&local->sta_mtx);
11891181 } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
11901182 rx_agg = (void *)&skb->cb;
net/mac80211/rx.c+10−0
@@ -835,6 +835,16 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata · 834 unmodified lines
835835
836836 spin_lock(&tid_agg_rx->reorder_lock);
837837
838+ /*
839+ * Offloaded BA sessions have no known starting sequence number so pick
840+ * one from first Rxed frame for this tid after BA was started.
841+ */
842+ if (unlikely(tid_agg_rx->auto_seq)) {
843+ tid_agg_rx->auto_seq = false;
844+ tid_agg_rx->ssn = mpdu_seq_num;
845+ tid_agg_rx->head_seq_num = mpdu_seq_num;
846+ }
847+
838848 buf_size = tid_agg_rx->buf_size;
839849 head_seq_num = tid_agg_rx->head_seq_num;
840850
net/mac80211/sta_info.h+3−0
@@ -167,6 +167,8 @@ struct tid_ampdu_tx { · 166 unmodified lines
167167 * @dialog_token: dialog token for aggregation session
168168 * @rcu_head: RCU head used for freeing this struct
169169 * @reorder_lock: serializes access to reorder buffer, see below.
170+ * @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and
171+ * and ssn.
170172 *
171173 * This structure's lifetime is managed by RCU, assignments to
172174 * the array holding it must hold the aggregation mutex.
@@ -190,6 +192,7 @@ struct tid_ampdu_rx { · 17 unmodified lines
190192 u16 buf_size;
191193 u16 timeout;
192194 u8 dialog_token;
195+ bool auto_seq;
193196 };
194197
195198 /**