aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-09-02 08:05:10 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-09-03 07:40:38 -0400
commit4549cf2b1803d29cfd019f7bfeaa784f8f9c558f (patch)
treebf39255e299b752cea30ce8437b9a685b189e5d4
parentd0616613d9cf17919fbd46fa0274db4b0084ad62 (diff)
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). Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/agg-rx.c5
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c14
-rw-r--r--net/mac80211/rx.c10
-rw-r--r--net/mac80211/sta_info.h3
5 files changed, 20 insertions, 14 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index f0e84bc48038..a48bad468880 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -227,7 +227,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
227void __ieee80211_start_rx_ba_session(struct sta_info *sta, 227void __ieee80211_start_rx_ba_session(struct sta_info *sta,
228 u8 dialog_token, u16 timeout, 228 u8 dialog_token, u16 timeout,
229 u16 start_seq_num, u16 ba_policy, u16 tid, 229 u16 start_seq_num, u16 ba_policy, u16 tid,
230 u16 buf_size, bool tx) 230 u16 buf_size, bool tx, bool auto_seq)
231{ 231{
232 struct ieee80211_local *local = sta->sdata->local; 232 struct ieee80211_local *local = sta->sdata->local;
233 struct tid_ampdu_rx *tid_agg_rx; 233 struct tid_ampdu_rx *tid_agg_rx;
@@ -326,6 +326,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
326 tid_agg_rx->buf_size = buf_size; 326 tid_agg_rx->buf_size = buf_size;
327 tid_agg_rx->timeout = timeout; 327 tid_agg_rx->timeout = timeout;
328 tid_agg_rx->stored_mpdu_num = 0; 328 tid_agg_rx->stored_mpdu_num = 0;
329 tid_agg_rx->auto_seq = auto_seq;
329 status = WLAN_STATUS_SUCCESS; 330 status = WLAN_STATUS_SUCCESS;
330 331
331 /* activate it for RX */ 332 /* activate it for RX */
@@ -367,7 +368,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
367 368
368 __ieee80211_start_rx_ba_session(sta, dialog_token, timeout, 369 __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
369 start_seq_num, ba_policy, tid, 370 start_seq_num, ba_policy, tid,
370 buf_size, true); 371 buf_size, true, false);
371} 372}
372 373
373void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, 374void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ffb20e5e6cf3..8fe5433f0d35 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1587,7 +1587,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
1587void __ieee80211_start_rx_ba_session(struct sta_info *sta, 1587void __ieee80211_start_rx_ba_session(struct sta_info *sta,
1588 u8 dialog_token, u16 timeout, 1588 u8 dialog_token, u16 timeout,
1589 u16 start_seq_num, u16 ba_policy, u16 tid, 1589 u16 start_seq_num, u16 ba_policy, u16 tid,
1590 u16 buf_size, bool tx); 1590 u16 buf_size, bool tx, bool auto_seq);
1591void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, 1591void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
1592 enum ieee80211_agg_stop_reason reason); 1592 enum ieee80211_agg_stop_reason reason);
1593void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, 1593void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 01eede7406a5..bb7288e3c41c 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1172,19 +1172,11 @@ static void ieee80211_iface_work(struct work_struct *work)
1172 rx_agg = (void *)&skb->cb; 1172 rx_agg = (void *)&skb->cb;
1173 mutex_lock(&local->sta_mtx); 1173 mutex_lock(&local->sta_mtx);
1174 sta = sta_info_get_bss(sdata, rx_agg->addr); 1174 sta = sta_info_get_bss(sdata, rx_agg->addr);
1175 if (sta) { 1175 if (sta)
1176 u16 last_seq;
1177
1178 last_seq = le16_to_cpu(
1179 sta->last_seq_ctrl[rx_agg->tid]);
1180
1181 __ieee80211_start_rx_ba_session(sta, 1176 __ieee80211_start_rx_ba_session(sta,
1182 0, 0, 1177 0, 0, 0, 1, rx_agg->tid,
1183 ieee80211_sn_inc(last_seq),
1184 1, rx_agg->tid,
1185 IEEE80211_MAX_AMPDU_BUF, 1178 IEEE80211_MAX_AMPDU_BUF,
1186 false); 1179 false, true);
1187 }
1188 mutex_unlock(&local->sta_mtx); 1180 mutex_unlock(&local->sta_mtx);
1189 } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) { 1181 } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
1190 rx_agg = (void *)&skb->cb; 1182 rx_agg = (void *)&skb->cb;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a8d862f9183c..41eb12c87240 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -835,6 +835,16 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
835 835
836 spin_lock(&tid_agg_rx->reorder_lock); 836 spin_lock(&tid_agg_rx->reorder_lock);
837 837
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
838 buf_size = tid_agg_rx->buf_size; 848 buf_size = tid_agg_rx->buf_size;
839 head_seq_num = tid_agg_rx->head_seq_num; 849 head_seq_num = tid_agg_rx->head_seq_num;
840 850
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 89c40d5c0633..16dc1d414f69 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -167,6 +167,8 @@ struct tid_ampdu_tx {
167 * @dialog_token: dialog token for aggregation session 167 * @dialog_token: dialog token for aggregation session
168 * @rcu_head: RCU head used for freeing this struct 168 * @rcu_head: RCU head used for freeing this struct
169 * @reorder_lock: serializes access to reorder buffer, see below. 169 * @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.
170 * 172 *
171 * This structure's lifetime is managed by RCU, assignments to 173 * This structure's lifetime is managed by RCU, assignments to
172 * the array holding it must hold the aggregation mutex. 174 * the array holding it must hold the aggregation mutex.
@@ -190,6 +192,7 @@ struct tid_ampdu_rx {
190 u16 buf_size; 192 u16 buf_size;
191 u16 timeout; 193 u16 timeout;
192 u8 dialog_token; 194 u8 dialog_token;
195 bool auto_seq;
193}; 196};
194 197
195/** 198/**