Commit 781eef5b authored by Felix Fietkau's avatar Felix Fietkau
Browse files

mt76: convert from tx tasklet to tx worker thread



This improves performance by allowing the scheduler to move the tx scheduling
work to idle CPUs. Since tx scheduling work is very latency sensitive and
kept short via AQL, sched_set_fifo_low is used to keep worker priority above
normal tasks

Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 30bdd692
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -592,6 +592,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
{
	int i;

	mt76_worker_disable(&dev->tx_worker);
	netif_napi_del(&dev->tx_napi);
	for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++)
		mt76_dma_tx_cleanup(dev, i, true);
+11 −3
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
/*
 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
 */
#include <linux/sched.h>
#include <linux/of.h>
#include "mt76.h"

@@ -436,14 +437,13 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
	skb_queue_head_init(&dev->mcu.res_q);
	init_waitqueue_head(&dev->mcu.wait);
	mutex_init(&dev->mcu.mutex);
	dev->tx_worker.fn = mt76_tx_worker;

	INIT_LIST_HEAD(&dev->txwi_cache);

	for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
		skb_queue_head_init(&dev->rx_skb[i]);

	tasklet_init(&dev->tx_tasklet, mt76_tx_tasklet, (unsigned long)dev);

	dev->wq = alloc_ordered_workqueue("mt76", 0);
	if (!dev->wq) {
		ieee80211_free_hw(hw);
@@ -486,7 +486,14 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
			return ret;
	}

	return ieee80211_register_hw(hw);
	ret = ieee80211_register_hw(hw);
	if (ret)
		return ret;

	WARN_ON(mt76_worker_setup(hw, &dev->tx_worker, NULL, "tx"));
	sched_set_fifo_low(dev->tx_worker.task);

	return 0;
}
EXPORT_SYMBOL_GPL(mt76_register_device);

@@ -503,6 +510,7 @@ EXPORT_SYMBOL_GPL(mt76_unregister_device);

void mt76_free_device(struct mt76_dev *dev)
{
	mt76_worker_teardown(&dev->tx_worker);
	if (dev->wq) {
		destroy_workqueue(dev->wq);
		dev->wq = NULL;
+2 −2
Original line number Diff line number Diff line
@@ -604,7 +604,7 @@ struct mt76_dev {
	const struct mt76_queue_ops *queue_ops;
	int tx_dma_idx[4];

	struct tasklet_struct tx_tasklet;
	struct mt76_worker tx_worker;
	struct napi_struct tx_napi;
	struct delayed_work mac_work;

@@ -906,7 +906,7 @@ void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta,
void mt76_tx_check_agg_ssn(struct ieee80211_sta *sta, struct sk_buff *skb);
void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid);
void mt76_txq_schedule_all(struct mt76_phy *phy);
void mt76_tx_tasklet(unsigned long data);
void mt76_tx_worker(struct mt76_worker *w);
void mt76_release_buffered_frames(struct ieee80211_hw *hw,
				  struct ieee80211_sta *sta,
				  u16 tids, int nframes,
+1 −2
Original line number Diff line number Diff line
@@ -163,7 +163,7 @@ static int mt7603_poll_tx(struct napi_struct *napi, int budget)

	mt7603_mac_sta_poll(dev);

	tasklet_schedule(&dev->mt76.tx_tasklet);
	mt76_worker_schedule(&dev->mt76.tx_worker);

	return 0;
}
@@ -246,6 +246,5 @@ void mt7603_dma_cleanup(struct mt7603_dev *dev)
		   MT_WPDMA_GLO_CFG_RX_DMA_EN |
		   MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);

	tasklet_kill(&dev->mt76.tx_tasklet);
	mt76_dma_cleanup(&dev->mt76);
}
+2 −2
Original line number Diff line number Diff line
@@ -1402,7 +1402,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
	/* lock/unlock all queues to ensure that no tx is pending */
	mt76_txq_schedule_all(&dev->mphy);

	tasklet_disable(&dev->mt76.tx_tasklet);
	mt76_worker_disable(&dev->mt76.tx_worker);
	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
	napi_disable(&dev->mt76.napi[0]);
	napi_disable(&dev->mt76.napi[1]);
@@ -1451,7 +1451,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
	clear_bit(MT76_RESET, &dev->mphy.state);
	mutex_unlock(&dev->mt76.mutex);

	tasklet_enable(&dev->mt76.tx_tasklet);
	mt76_worker_enable(&dev->mt76.tx_worker);
	napi_enable(&dev->mt76.tx_napi);
	napi_schedule(&dev->mt76.tx_napi);

Loading