diff options
author | Sujith Manoharan <Sujith.Manoharan@atheros.com> | 2011-04-13 11:25:29 +0530 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-13 15:23:42 -0400 |
commit | 8e86a54715c4102a8ed697939de9ebd9715dc59c (patch) | |
tree | 6ec011dfe718973e3aeba78176a51302744f71d5 /drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |
parent | 3deff76095c4ac4252e27c537db3041f619c23a2 (diff) |
ath9k_htc: Fix TX queue management
Handle queue start/stop properly by maintaining
a counter to check if the pending frame count has
exceeded the threshold. Otherwise, packets would be
dropped needlessly. While at it, use a simple flag
to track queue status and use helper functions too.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_txrx.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 6f7987d7b6b0..1cbe194179ab 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -53,6 +53,29 @@ int get_hw_qnum(u16 queue, int *hwq_map) } } +void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv) +{ + spin_lock_bh(&priv->tx.tx_lock); + priv->tx.queued_cnt++; + if ((priv->tx.queued_cnt >= ATH9K_HTC_TX_THRESHOLD) && + !(priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { + priv->tx.flags |= ATH9K_HTC_OP_TX_QUEUES_STOP; + ieee80211_stop_queues(priv->hw); + } + spin_unlock_bh(&priv->tx.tx_lock); +} + +void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv) +{ + spin_lock_bh(&priv->tx.tx_lock); + if ((priv->tx.queued_cnt < ATH9K_HTC_TX_THRESHOLD) && + (priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { + priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; + ieee80211_wake_queues(priv->hw); + } + spin_unlock_bh(&priv->tx.tx_lock); +} + int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, struct ath9k_tx_queue_info *qinfo) { @@ -302,21 +325,17 @@ void ath9k_tx_tasklet(unsigned long data) rcu_read_unlock(); send_mac80211: + spin_lock_bh(&priv->tx.tx_lock); + if (WARN_ON(--priv->tx.queued_cnt < 0)) + priv->tx.queued_cnt = 0; + spin_unlock_bh(&priv->tx.tx_lock); + /* Send status to mac80211 */ ieee80211_tx_status(priv->hw, skb); } /* Wake TX queues if needed */ - spin_lock_bh(&priv->tx.tx_lock); - if (priv->tx.tx_queues_stop) { - priv->tx.tx_queues_stop = false; - spin_unlock_bh(&priv->tx.tx_lock); - ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, - "Waking up TX queues\n"); - ieee80211_wake_queues(priv->hw); - return; - } - spin_unlock_bh(&priv->tx.tx_lock); + ath9k_htc_check_wake_queues(priv); } void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, |