diff options
author | Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> | 2014-04-08 11:36:18 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-04-22 15:06:29 -0400 |
commit | c888cdd41fdb76f3b179564e41ec2646463d058a (patch) | |
tree | 876b4e52abc27b480eedb5ac0e70c4e1a9adf44e /drivers | |
parent | 6c2faf09394ceaef4efed1e44721830579f16115 (diff) | |
download | linux-c888cdd41fdb76f3b179564e41ec2646463d058a.tar.bz2 |
wil6210: relaxed check for BACK start sequence
Sometimes, due to the race between Rx path and WMI_BA_STATUS_EVENTID WMI event,
few frames may be passed to the stack before reorder buffer allocated.
Then, after BACK establishment, it start getting frames with sequence number ahead of
SSN, and it get interpreted as missing frames. Then, BACK mechanism will wait
for missing frames; data traffic will be stopped. In case of interface configured
for DHCP, this data delay causes DHCP failure.
Relax checking for sequence number; use sequence of 1-st frame handled by the buffer
as SSN for this buffer.
This is work-around, real fix should be done when proper BACK mechanism implemented.
Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/wil6210/rx_reorder.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 1 |
2 files changed, 18 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index d04629fe053f..ec29954bd44d 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -91,6 +91,22 @@ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) spin_lock(&r->reorder_lock); + /** Due to the race between WMI events, where BACK establishment + * reported, and data Rx, few packets may be pass up before reorder + * buffer get allocated. Catch up by pretending SSN is what we + * see in the 1-st Rx packet + */ + if (r->first_time) { + r->first_time = false; + if (seq != r->head_seq_num) { + wil_err(wil, "Error: 1-st frame with wrong sequence" + " %d, should be %d. Fixing...\n", seq, + r->head_seq_num); + r->head_seq_num = seq; + r->ssn = seq; + } + } + /* frame with out of date sequence number */ if (seq_less(seq, r->head_seq_num)) { dev_kfree_skb(skb); @@ -162,6 +178,7 @@ struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, r->head_seq_num = ssn; r->buf_size = size; r->stored_mpdu_num = 0; + r->first_time = true; return r; } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 2a2dec75f026..f881aee6319d 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -301,6 +301,7 @@ struct wil_tid_ampdu_rx { u16 buf_size; u16 timeout; u8 dialog_token; + bool first_time; /* is it 1-st time this buffer used? */ }; struct wil6210_stats { |