diff options
author | Christian Lamparter <chunkeey@googlemail.com> | 2009-10-17 15:56:43 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-10-27 16:48:34 -0400 |
commit | 02bdf5b48a2cd90a5d036eab68e6f65adb200140 (patch) | |
tree | 5c19c3a7d0ddadc409bef825ef86c2e6ac963372 | |
parent | 4ad177b5c860dc0b1083eccc55957daf4a116b90 (diff) |
ar9170: atomic pending A-MPDU counter
A ref-counting bug emerged after testing ar9170usb's HT
implementation on a bigger SMP/SMT system without the usual
_debugging_ overhead.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ar9170/ar9170.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/main.c | 11 |
2 files changed, 7 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index ec034af26980..9f9459860d82 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -231,7 +231,7 @@ struct ar9170 { | |||
231 | struct sk_buff_head tx_status_ampdu; | 231 | struct sk_buff_head tx_status_ampdu; |
232 | spinlock_t tx_ampdu_list_lock; | 232 | spinlock_t tx_ampdu_list_lock; |
233 | struct list_head tx_ampdu_list; | 233 | struct list_head tx_ampdu_list; |
234 | unsigned int tx_ampdu_pending; | 234 | atomic_t tx_ampdu_pending; |
235 | 235 | ||
236 | /* rxstream mpdu merge */ | 236 | /* rxstream mpdu merge */ |
237 | struct ar9170_rxstream_mpdu_merge rx_mpdu; | 237 | struct ar9170_rxstream_mpdu_merge rx_mpdu; |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index de0ba2bf7691..7e59b82e64d3 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -414,9 +414,9 @@ static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
414 | 414 | ||
415 | skb_queue_tail(&ar->tx_status_ampdu, skb); | 415 | skb_queue_tail(&ar->tx_status_ampdu, skb); |
416 | ar9170_tx_fake_ampdu_status(ar); | 416 | ar9170_tx_fake_ampdu_status(ar); |
417 | ar->tx_ampdu_pending--; | ||
418 | 417 | ||
419 | if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending) | 418 | if (atomic_dec_and_test(&ar->tx_ampdu_pending) && |
419 | !list_empty(&ar->tx_ampdu_list)) | ||
420 | ar9170_tx_ampdu(ar); | 420 | ar9170_tx_ampdu(ar); |
421 | } | 421 | } |
422 | 422 | ||
@@ -1248,6 +1248,7 @@ static int ar9170_op_start(struct ieee80211_hw *hw) | |||
1248 | ar->global_ampdu_density = 6; | 1248 | ar->global_ampdu_density = 6; |
1249 | ar->global_ampdu_factor = 3; | 1249 | ar->global_ampdu_factor = 3; |
1250 | 1250 | ||
1251 | atomic_set(&ar->tx_ampdu_pending, 0); | ||
1251 | ar->bad_hw_nagger = jiffies; | 1252 | ar->bad_hw_nagger = jiffies; |
1252 | 1253 | ||
1253 | err = ar->open(ar); | 1254 | err = ar->open(ar); |
@@ -1773,7 +1774,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1773 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 1774 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
1774 | 1775 | ||
1775 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1776 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) |
1776 | ar->tx_ampdu_pending++; | 1777 | atomic_inc(&ar->tx_ampdu_pending); |
1777 | 1778 | ||
1778 | #ifdef AR9170_QUEUE_DEBUG | 1779 | #ifdef AR9170_QUEUE_DEBUG |
1779 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", | 1780 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", |
@@ -1784,7 +1785,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1784 | err = ar->tx(ar, skb); | 1785 | err = ar->tx(ar, skb); |
1785 | if (unlikely(err)) { | 1786 | if (unlikely(err)) { |
1786 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1787 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) |
1787 | ar->tx_ampdu_pending--; | 1788 | atomic_dec(&ar->tx_ampdu_pending); |
1788 | 1789 | ||
1789 | frames_failed++; | 1790 | frames_failed++; |
1790 | dev_kfree_skb_any(skb); | 1791 | dev_kfree_skb_any(skb); |
@@ -1931,7 +1932,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1931 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1932 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1932 | bool run = ar9170_tx_ampdu_queue(ar, skb); | 1933 | bool run = ar9170_tx_ampdu_queue(ar, skb); |
1933 | 1934 | ||
1934 | if (run || !ar->tx_ampdu_pending) | 1935 | if (run || !atomic_read(&ar->tx_ampdu_pending)) |
1935 | ar9170_tx_ampdu(ar); | 1936 | ar9170_tx_ampdu(ar); |
1936 | } else { | 1937 | } else { |
1937 | unsigned int queue = skb_get_queue_mapping(skb); | 1938 | unsigned int queue = skb_get_queue_mapping(skb); |