Commit 5342758d authored by Felix Fietkau's avatar Felix Fietkau
Browse files

mt76: mt7915: stop queues when running out of tx tokens



Avoids packet drops under load with lots of stations

Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 90d494c9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -690,6 +690,7 @@ void mt7915_unregister_device(struct mt7915_dev *dev)
			ieee80211_free_txskb(hw, txwi->skb);
		}
		mt76_put_txwi(&dev->mt76, txwi);
		dev->token_count--;
	}
	spin_unlock_bh(&dev->token_lock);
	idr_destroy(&dev->token);
+39 −0
Original line number Diff line number Diff line
@@ -906,6 +906,26 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
		mt7915_mac_write_txwi_tm(dev, mphy, txwi, skb);
}

static void
mt7915_set_tx_blocked(struct mt7915_dev *dev, bool blocked)
{
	struct mt76_phy *mphy = &dev->mphy, *mphy2 = dev->mt76.phy2;
	struct mt76_queue *q, *q2 = NULL;

	q = mphy->q_tx[0];
	if (blocked == q->blocked)
		return;

	q->blocked = blocked;
	if (mphy2) {
		q2 = mphy2->q_tx[0];
		q2->blocked = blocked;
	}

	if (!blocked)
		mt76_worker_schedule(&dev->mt76.tx_worker);
}

int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
			  enum mt76_txq_id qid, struct mt76_wcid *wcid,
			  struct ieee80211_sta *sta,
@@ -962,7 +982,13 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,

	spin_lock_bh(&dev->token_lock);
	id = idr_alloc(&dev->token, t, 0, MT7915_TOKEN_SIZE, GFP_ATOMIC);
	if (id >= 0)
		dev->token_count++;

	if (dev->token_count >= MT7915_TOKEN_SIZE - MT7915_TOKEN_FREE_THR)
		mt7915_set_tx_blocked(dev, true);
	spin_unlock_bh(&dev->token_lock);

	if (id < 0)
		return id;

@@ -1071,6 +1097,7 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
	LIST_HEAD(free_list);
	struct sk_buff *tmp;
	u8 i, count;
	bool wake = false;

	/* clean DMA queues and unmap buffers first */
	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
@@ -1123,6 +1150,11 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)

		spin_lock_bh(&dev->token_lock);
		txwi = idr_remove(&dev->token, msdu);
		if (txwi)
			dev->token_count--;
		if (dev->token_count < MT7915_TOKEN_SIZE - MT7915_TOKEN_FREE_THR &&
		    dev->mphy.q_tx[0]->blocked)
			wake = true;
		spin_unlock_bh(&dev->token_lock);

		if (!txwi)
@@ -1153,6 +1185,13 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
	}

	mt7915_mac_sta_poll(dev);

	if (wake) {
		spin_lock_bh(&dev->token_lock);
		mt7915_set_tx_blocked(dev, false);
		spin_unlock_bh(&dev->token_lock);
	}

	mt76_worker_schedule(&dev->mt76.tx_worker);

	napi_consume_skb(skb, 1);
+2 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@

#define MT7915_EEPROM_SIZE		3584
#define MT7915_TOKEN_SIZE		8192
#define MT7915_TOKEN_FREE_THR		64

#define MT7915_CFEND_RATE_DEFAULT	0x49	/* OFDM 24M */
#define MT7915_CFEND_RATE_11B		0x03	/* 11B LP, 11M */
@@ -161,6 +162,7 @@ struct mt7915_dev {
	u32 hw_pattern;

	spinlock_t token_lock;
	int token_count;
	struct idr token;

	s8 **rate_power; /* TODO: use mt76_rate_power */