diff options
author | Christian Lamparter <chunkeey@googlemail.com> | 2012-07-07 15:13:59 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-07-11 15:38:26 -0400 |
commit | c9122c0d63a50bab0a97dc936a38c0f921b6930e (patch) | |
tree | 7263d06049fc2a21971e363557f7bdc17a26f4ad /drivers/net/wireless/ath/carl9170/main.c | |
parent | 4519a7433835f1a8dda242ad508233fcc5963545 (diff) |
carl9170: fix HT peer BA session corruption
This patch adds an alternative tx status path
for BlockAck Requests as the hardware doesn't
recognize that a BlockAck Requests is usually
acked with a BlockAck and not a legacy ACK.
Without this patch, the stack would constantly
resent old and stale BARs. So, depending on the
receiver stack, this could lead to:
- "stuck" ba sessions and package loss, as the
stale BAR would reset the sequence each time.
- lots of reorder releases.
- ...
Reported-by: Sean Patrick Santos <quantheory@gmail.com>
Reported-by: MikoĊaj Kuligowski <mikolaj.q@wp.pl>
Reported-by: Per-Erik Westerberg <per-erik.westerberg@bredband.net>
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/main.c')
-rw-r--r-- | drivers/net/wireless/ath/carl9170/main.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 8d2523b3f722..858e58dfc4dc 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -949,6 +949,9 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw, | |||
949 | if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) { | 949 | if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) { |
950 | u32 rx_filter = 0; | 950 | u32 rx_filter = 0; |
951 | 951 | ||
952 | if (!ar->fw.ba_filter) | ||
953 | rx_filter |= CARL9170_RX_FILTER_CTL_OTHER; | ||
954 | |||
952 | if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))) | 955 | if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))) |
953 | rx_filter |= CARL9170_RX_FILTER_BAD; | 956 | rx_filter |= CARL9170_RX_FILTER_BAD; |
954 | 957 | ||
@@ -1753,6 +1756,9 @@ void *carl9170_alloc(size_t priv_size) | |||
1753 | for (i = 0; i < ar->hw->queues; i++) { | 1756 | for (i = 0; i < ar->hw->queues; i++) { |
1754 | skb_queue_head_init(&ar->tx_status[i]); | 1757 | skb_queue_head_init(&ar->tx_status[i]); |
1755 | skb_queue_head_init(&ar->tx_pending[i]); | 1758 | skb_queue_head_init(&ar->tx_pending[i]); |
1759 | |||
1760 | INIT_LIST_HEAD(&ar->bar_list[i]); | ||
1761 | spin_lock_init(&ar->bar_list_lock[i]); | ||
1756 | } | 1762 | } |
1757 | INIT_WORK(&ar->ps_work, carl9170_ps_work); | 1763 | INIT_WORK(&ar->ps_work, carl9170_ps_work); |
1758 | INIT_WORK(&ar->ping_work, carl9170_ping_work); | 1764 | INIT_WORK(&ar->ping_work, carl9170_ping_work); |