* [PATCH v2 1/3] mt76: improve tx queue stop/wake
@ 2020-12-04 13:17 Felix Fietkau
2020-12-04 13:17 ` [PATCH v2 2/3] mt76: mt7915: stop queues when running out of tx tokens Felix Fietkau
2020-12-04 13:17 ` [PATCH v2 3/3] mt76: attempt to free up more room when filling the tx queue Felix Fietkau
0 siblings, 2 replies; 3+ messages in thread
From: Felix Fietkau @ 2020-12-04 13:17 UTC (permalink / raw)
To: linux-wireless
Instead of stopping and waking only a single queue, handle all phy tx queues
mapped ot the same hardware queue.
Also allow the driver to block tx queues
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/net/wireless/mediatek/mt76/dma.c | 10 ----------
drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
drivers/net/wireless/mediatek/mt76/tx.c | 23 ++++++++++++-----------
3 files changed, 13 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index bab961ebdf1c..6255f4f0a455 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -220,7 +220,6 @@ static void
mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
{
struct mt76_queue_entry entry;
- bool wake = false;
int last;
if (!q)
@@ -238,7 +237,6 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
if (entry.txwi) {
if (!(dev->drv->drv_flags & MT_DRV_TXWI_NO_FREE))
mt76_put_txwi(dev, entry.txwi);
- wake = !flush;
}
if (!flush && q->tail == last)
@@ -253,16 +251,8 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
spin_unlock_bh(&q->lock);
}
- wake = wake && q->stopped &&
- q->qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8;
- if (wake)
- q->stopped = false;
-
if (!q->queued)
wake_up(&dev->tx_wait);
-
- if (wake)
- ieee80211_wake_queue(dev->hw, q->qid);
}
static void *
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 15d52af24d12..ea80ae188dd6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -136,6 +136,7 @@ struct mt76_queue {
int queued;
int buf_size;
bool stopped;
+ bool blocked;
u8 buf_offset;
u8 hw_idx;
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 65360067b8fa..4026e5f4f3f3 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -291,12 +291,6 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
spin_lock_bh(&q->lock);
__mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL);
dev->queue_ops->kick(dev, q);
-
- if (q->queued > q->ndesc - 8 && !q->stopped) {
- ieee80211_stop_queue(phy->hw, skb_get_queue_mapping(skb));
- q->stopped = true;
- }
-
spin_unlock_bh(&q->lock);
}
EXPORT_SYMBOL_GPL(mt76_tx);
@@ -381,6 +375,13 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
}
EXPORT_SYMBOL_GPL(mt76_release_buffered_frames);
+static bool
+mt76_txq_stopped(struct mt76_queue *q)
+{
+ return q->stopped || q->blocked ||
+ q->queued + MT_TXQ_FREE_THR >= q->ndesc;
+}
+
static int
mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
struct mt76_txq *mtxq)
@@ -419,10 +420,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
test_bit(MT76_RESET, &phy->state))
return -EBUSY;
- if (stop)
- break;
-
- if (q->queued + MT_TXQ_FREE_THR >= q->ndesc)
+ if (stop || mt76_txq_stopped(q))
break;
skb = mt76_txq_dequeue(phy, mtxq);
@@ -463,7 +461,7 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
break;
}
- if (q->queued + MT_TXQ_FREE_THR >= q->ndesc)
+ if (mt76_txq_stopped(q))
break;
txq = ieee80211_next_txq(phy->hw, qid);
@@ -498,11 +496,14 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)
{
+ struct mt76_queue *q;
int len;
if (qid >= 4)
return;
+ q = phy->q_tx[qid];
+
rcu_read_lock();
do {
--
2.28.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v2 2/3] mt76: mt7915: stop queues when running out of tx tokens
2020-12-04 13:17 [PATCH v2 1/3] mt76: improve tx queue stop/wake Felix Fietkau
@ 2020-12-04 13:17 ` Felix Fietkau
2020-12-04 13:17 ` [PATCH v2 3/3] mt76: attempt to free up more room when filling the tx queue Felix Fietkau
1 sibling, 0 replies; 3+ messages in thread
From: Felix Fietkau @ 2020-12-04 13:17 UTC (permalink / raw)
To: linux-wireless
Avoids packet drops under load with lots of stations
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
.../net/wireless/mediatek/mt76/mt7915/init.c | 1 +
.../net/wireless/mediatek/mt76/mt7915/mac.c | 39 +++++++++++++++++++
.../wireless/mediatek/mt76/mt7915/mt7915.h | 2 +
3 files changed, 42 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index ff29a8090739..ed4635bd151a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index a7fa6fffffff..71714b22188a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -918,6 +918,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,
@@ -974,7 +994,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;
@@ -1083,6 +1109,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);
@@ -1135,6 +1162,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)
@@ -1165,6 +1197,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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 30e53a0f01fb..0339abf360d3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -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 */
--
2.28.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v2 3/3] mt76: attempt to free up more room when filling the tx queue
2020-12-04 13:17 [PATCH v2 1/3] mt76: improve tx queue stop/wake Felix Fietkau
2020-12-04 13:17 ` [PATCH v2 2/3] mt76: mt7915: stop queues when running out of tx tokens Felix Fietkau
@ 2020-12-04 13:17 ` Felix Fietkau
1 sibling, 0 replies; 3+ messages in thread
From: Felix Fietkau @ 2020-12-04 13:17 UTC (permalink / raw)
To: linux-wireless
Run dma cleanup immediately if the queue is almost full, instead of waiting
for the tx interrupt
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/net/wireless/mediatek/mt76/dma.c | 3 +++
drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
drivers/net/wireless/mediatek/mt76/tx.c | 8 ++++++++
3 files changed, 12 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index 6255f4f0a455..73eeb00d5aa6 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -88,6 +88,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
int i;
spin_lock_init(&q->lock);
+ spin_lock_init(&q->cleanup_lock);
q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE;
q->ndesc = n_desc;
@@ -225,6 +226,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
if (!q)
return;
+ spin_lock_bh(&q->cleanup_lock);
if (flush)
last = -1;
else
@@ -243,6 +245,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
last = readl(&q->regs->dma_idx);
}
+ spin_unlock_bh(&q->cleanup_lock);
if (flush) {
spin_lock_bh(&q->lock);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index ea80ae188dd6..3e496a188bf0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -126,6 +126,7 @@ struct mt76_queue {
struct mt76_queue_regs __iomem *regs;
spinlock_t lock;
+ spinlock_t cleanup_lock;
struct mt76_queue_entry *entry;
struct mt76_desc *desc;
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 4026e5f4f3f3..1e20afb70fc1 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -448,6 +448,7 @@ static int
mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
{
struct mt76_queue *q = phy->q_tx[qid];
+ struct mt76_dev *dev = phy->dev;
struct ieee80211_txq *txq;
struct mt76_txq *mtxq;
struct mt76_wcid *wcid;
@@ -461,6 +462,13 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
break;
}
+ if (dev->queue_ops->tx_cleanup &&
+ q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) {
+ spin_unlock_bh(&q->lock);
+ dev->queue_ops->tx_cleanup(dev, q, false);
+ spin_lock_bh(&q->lock);
+ }
+
if (mt76_txq_stopped(q))
break;
--
2.28.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-12-04 13:18 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-04 13:17 [PATCH v2 1/3] mt76: improve tx queue stop/wake Felix Fietkau
2020-12-04 13:17 ` [PATCH v2 2/3] mt76: mt7915: stop queues when running out of tx tokens Felix Fietkau
2020-12-04 13:17 ` [PATCH v2 3/3] mt76: attempt to free up more room when filling the tx queue Felix Fietkau
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.