mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 09:41:44 +00:00
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;
|
struct sk_buff *beacon;
|
||||||
spinlock_t beacon_lock;
|
spinlock_t beacon_lock;
|
||||||
|
|
||||||
|
bool tx_queues_stop;
|
||||||
|
spinlock_t tx_lock;
|
||||||
|
|
||||||
struct ieee80211_vif *vif;
|
struct ieee80211_vif *vif;
|
||||||
unsigned int rxfilter;
|
unsigned int rxfilter;
|
||||||
struct tasklet_struct wmi_tasklet;
|
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->wmi->wmi_lock);
|
||||||
spin_lock_init(&priv->beacon_lock);
|
spin_lock_init(&priv->beacon_lock);
|
||||||
|
spin_lock_init(&priv->tx_lock);
|
||||||
mutex_init(&priv->mutex);
|
mutex_init(&priv->mutex);
|
||||||
mutex_init(&priv->aggr_work.mutex);
|
mutex_init(&priv->aggr_work.mutex);
|
||||||
tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
|
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 ieee80211_hdr *hdr;
|
||||||
struct ath9k_htc_priv *priv = hw->priv;
|
struct ath9k_htc_priv *priv = hw->priv;
|
||||||
int padpos, padsize;
|
int padpos, padsize, ret;
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *) skb->data;
|
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);
|
memmove(skb->data, skb->data + padsize, padpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ath9k_htc_tx_start(priv, skb) != 0) {
|
ret = ath9k_htc_tx_start(priv, skb);
|
||||||
ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed");
|
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;
|
goto fail_tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,6 +1085,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
|
|||||||
priv->op_flags &= ~OP_INVALID;
|
priv->op_flags &= ~OP_INVALID;
|
||||||
htc_start(priv->htc);
|
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:
|
||||||
mutex_unlock(&priv->mutex);
|
mutex_unlock(&priv->mutex);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -226,6 +226,18 @@ void ath9k_tx_tasklet(unsigned long data)
|
|||||||
/* Send status to mac80211 */
|
/* Send status to mac80211 */
|
||||||
ieee80211_tx_status(priv->hw, skb);
|
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,
|
void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
|
||||||
|
Loading…
Reference in New Issue
Block a user