Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7757dfed authored by Sujith's avatar Sujith Committed by John W. Linville
Browse files

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: default avatarSujith <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6335ed0f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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,
+20 −3
Original line number Diff line number Diff line
@@ -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;
+12 −0
Original line number Diff line number Diff line
@@ -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,