diff options
author | Felix Fietkau <nbd@openwrt.org> | 2013-10-14 15:18:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-10-18 13:41:11 -0400 |
commit | 7ede612fd615abcda0cc30e5bef2a70f4cf4f75c (patch) | |
tree | 7ce5cb444b4da536727c70d6bd5fc1b77275bcf8 /drivers/net/wireless | |
parent | 334300f247abc4f21124ff3ac192df5222ea79bf (diff) |
ath5k: fix regression in tx status processing
The regression was introduced in the following commit:
0967e01e8e713ed2982fb4eba8ba13794e9a6e89
"ath5k: make use of the new rate control API"
ath5k_tx_frame_completed saves the intended per-rate retry counts before
they are cleared by ieee80211_tx_info_clear_status, however at this
point the information in info->status.rates is incomplete.
This causes significant throughput degradation and excessive packet loss
on links where high bit rates don't work properly.
Move the copy from bf->rates a few lines up to ensure that the saved
retry counts are updated, and that they are really cleared in
info->status.rates after the call to ieee80211_tx_info_clear_status.
Cc: stable@vger.kernel.org # 3.10+
Cc: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
Cc: Benjamin Vahl <bvahl@net.t-labs.tu-berlin.de>
Reported-by: Ben West <ben@gowasabi.net>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Acked-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 48161edec8de..69f58b073e85 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1663,15 +1663,15 @@ ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb, | |||
1663 | ah->stats.tx_bytes_count += skb->len; | 1663 | ah->stats.tx_bytes_count += skb->len; |
1664 | info = IEEE80211_SKB_CB(skb); | 1664 | info = IEEE80211_SKB_CB(skb); |
1665 | 1665 | ||
1666 | size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates)); | ||
1667 | memcpy(info->status.rates, bf->rates, size); | ||
1668 | |||
1666 | tries[0] = info->status.rates[0].count; | 1669 | tries[0] = info->status.rates[0].count; |
1667 | tries[1] = info->status.rates[1].count; | 1670 | tries[1] = info->status.rates[1].count; |
1668 | tries[2] = info->status.rates[2].count; | 1671 | tries[2] = info->status.rates[2].count; |
1669 | 1672 | ||
1670 | ieee80211_tx_info_clear_status(info); | 1673 | ieee80211_tx_info_clear_status(info); |
1671 | 1674 | ||
1672 | size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates)); | ||
1673 | memcpy(info->status.rates, bf->rates, size); | ||
1674 | |||
1675 | for (i = 0; i < ts->ts_final_idx; i++) { | 1675 | for (i = 0; i < ts->ts_final_idx; i++) { |
1676 | struct ieee80211_tx_rate *r = | 1676 | struct ieee80211_tx_rate *r = |
1677 | &info->status.rates[i]; | 1677 | &info->status.rates[i]; |