diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2010-03-29 16:07:17 +0530 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-03-31 14:46:40 -0400 |
commit | 7757dfed5809b03aa61c7d7f5ff8092f85df8583 (patch) | |
tree | ae855421010956814bca1917dc6e1fb42c3c19ac /drivers/net/wireless/ath/ath9k/htc_drv_main.c | |
parent | 6335ed0ff8670e6378da41191ab8bda33d1b7ac8 (diff) |
ath9k_htc: Handle TX queue overflow
Stop/restart TX queues when the internal SKB
queue is full. This helps handle TX better
under heavy load.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 90b13ed1ae4..63f032d61d5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -994,7 +994,7 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ieee80211_hdr *hdr; struct ath9k_htc_priv *priv = hw->priv; - int padpos, padsize; + int padpos, padsize, ret; hdr = (struct ieee80211_hdr *) skb->data; @@ -1008,8 +1008,19 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) memmove(skb->data, skb->data + padsize, padpos); } - if (ath9k_htc_tx_start(priv, skb) != 0) { - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed"); + ret = ath9k_htc_tx_start(priv, skb); + if (ret != 0) { + if (ret == -ENOMEM) { + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Stopping TX queues\n"); + ieee80211_stop_queues(hw); + spin_lock_bh(&priv->tx_lock); + priv->tx_queues_stop = true; + spin_unlock_bh(&priv->tx_lock); + } else { + ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Tx failed"); + } goto fail_tx; } @@ -1074,6 +1085,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) priv->op_flags &= ~OP_INVALID; htc_start(priv->htc); + spin_lock_bh(&priv->tx_lock); + priv->tx_queues_stop = false; + spin_unlock_bh(&priv->tx_lock); + + ieee80211_wake_queues(hw); + mutex_unlock: mutex_unlock(&priv->mutex); return ret; |