forked from Minki/linux
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>
This commit is contained in:
parent
6335ed0ff8
commit
7757dfed58
@ -349,6 +349,9 @@ struct ath9k_htc_priv {
|
||||
struct sk_buff *beacon;
|
||||
spinlock_t beacon_lock;
|
||||
|
||||
bool tx_queues_stop;
|
||||
spinlock_t tx_lock;
|
||||
|
||||
struct ieee80211_vif *vif;
|
||||
unsigned int rxfilter;
|
||||
struct tasklet_struct wmi_tasklet;
|
||||
|
@ -449,6 +449,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid)
|
||||
|
||||
spin_lock_init(&priv->wmi->wmi_lock);
|
||||
spin_lock_init(&priv->beacon_lock);
|
||||
spin_lock_init(&priv->tx_lock);
|
||||
mutex_init(&priv->mutex);
|
||||
mutex_init(&priv->aggr_work.mutex);
|
||||
tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
|
||||
|
@ -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;
|
||||
|
@ -226,6 +226,18 @@ void ath9k_tx_tasklet(unsigned long data)
|
||||
/* Send status to mac80211 */
|
||||
ieee80211_tx_status(priv->hw, skb);
|
||||
}
|
||||
|
||||
/* Wake TX queues if needed */
|
||||
spin_lock_bh(&priv->tx_lock);
|
||||
if (priv->tx_queues_stop) {
|
||||
priv->tx_queues_stop = false;
|
||||
spin_unlock_bh(&priv->tx_lock);
|
||||
ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
|
||||
"Waking up TX queues\n");
|
||||
ieee80211_wake_queues(priv->hw);
|
||||
return;
|
||||
}
|
||||
spin_unlock_bh(&priv->tx_lock);
|
||||
}
|
||||
|
||||
void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
|
||||
|
Loading…
Reference in New Issue
Block a user