Commit 284efb47 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Felix Fietkau
Browse files

mt76: mt76u: rely on a dedicated stats workqueue



rate controller and throughput are very sensitive to tx status timing.
In order to improve performances when the system is heavily loaded,
substitute stat_work delayed_work with a regular work_struct and create
a mt76u dedicated workqueue for tx status reporting

Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 80df01f4
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -387,7 +387,8 @@ struct mt76_usb {
	};

	struct tasklet_struct rx_tasklet;
	struct delayed_work stat_work;
	struct workqueue_struct *stat_wq;
	struct work_struct stat_work;

	u8 out_ep[__MT_EP_OUT_MAX];
	u8 in_ep[__MT_EP_IN_MAX];
@@ -823,6 +824,7 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
		     const u16 offset, const u32 val);
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf);
void mt76u_deinit(struct mt76_dev *dev);
int mt76u_alloc_queues(struct mt76_dev *dev);
void mt76u_stop_tx(struct mt76_dev *dev);
void mt76u_stop_rx(struct mt76_dev *dev);
+2 −0
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
err:
	usb_set_intfdata(usb_intf, NULL);
	usb_put_dev(interface_to_usbdev(usb_intf));
	mt76u_deinit(&dev->mt76);

	ieee80211_free_hw(mdev->hw);
	return ret;
@@ -292,6 +293,7 @@ static void mt76x0_disconnect(struct usb_interface *usb_intf)
	usb_set_intfdata(usb_intf, NULL);
	usb_put_dev(interface_to_usbdev(usb_intf));

	mt76u_deinit(&dev->mt76);
	ieee80211_free_hw(dev->mt76.hw);
}

+2 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ static int mt76x2u_probe(struct usb_interface *intf,

err:
	ieee80211_free_hw(mt76_hw(dev));
	mt76u_deinit(&dev->mt76);
	usb_set_intfdata(intf, NULL);
	usb_put_dev(udev);

@@ -88,6 +89,7 @@ static void mt76x2u_disconnect(struct usb_interface *intf)
	set_bit(MT76_REMOVED, &dev->mt76.state);
	ieee80211_unregister_hw(hw);
	mt76x2u_cleanup(dev);
	mt76u_deinit(&dev->mt76);

	ieee80211_free_hw(hw);
	usb_set_intfdata(intf, NULL);
+18 −9
Original line number Diff line number Diff line
@@ -697,10 +697,7 @@ static void mt76u_tx_tasklet(unsigned long data)
		mt76_txq_schedule(dev, i);

		if (!test_and_set_bit(MT76_READING_STATS, &dev->state))
			ieee80211_queue_delayed_work(dev->hw,
						     &dev->usb.stat_work,
						     msecs_to_jiffies(10));

			queue_work(dev->usb.stat_wq, &dev->usb.stat_work);
		if (wake)
			ieee80211_wake_queue(dev->hw, i);
	}
@@ -713,7 +710,7 @@ static void mt76u_tx_status_data(struct work_struct *work)
	u8 update = 1;
	u16 count = 0;

	usb = container_of(work, struct mt76_usb, stat_work.work);
	usb = container_of(work, struct mt76_usb, stat_work);
	dev = container_of(usb, struct mt76_dev, usb);

	while (true) {
@@ -726,8 +723,7 @@ static void mt76u_tx_status_data(struct work_struct *work)
	}

	if (count && test_bit(MT76_STATE_RUNNING, &dev->state))
		ieee80211_queue_delayed_work(dev->hw, &usb->stat_work,
					     msecs_to_jiffies(10));
		queue_work(usb->stat_wq, &usb->stat_work);
	else
		clear_bit(MT76_READING_STATS, &dev->state);
}
@@ -908,7 +904,7 @@ void mt76u_stop_tx(struct mt76_dev *dev)
		}
	}

	cancel_delayed_work_sync(&dev->usb.stat_work);
	cancel_work_sync(&dev->usb.stat_work);
	clear_bit(MT76_READING_STATS, &dev->state);

	mt76_tx_status_check(dev, NULL, true);
@@ -959,9 +955,13 @@ int mt76u_init(struct mt76_dev *dev,

	tasklet_init(&usb->rx_tasklet, mt76u_rx_tasklet, (unsigned long)dev);
	tasklet_init(&dev->tx_tasklet, mt76u_tx_tasklet, (unsigned long)dev);
	INIT_DELAYED_WORK(&usb->stat_work, mt76u_tx_status_data);
	INIT_WORK(&usb->stat_work, mt76u_tx_status_data);
	skb_queue_head_init(&dev->rx_skb[MT_RXQ_MAIN]);

	usb->stat_wq = alloc_workqueue("mt76u", WQ_UNBOUND, 0);
	if (!usb->stat_wq)
		return -ENOMEM;

	mutex_init(&usb->mcu.mutex);

	mutex_init(&usb->usb_ctrl_mtx);
@@ -976,5 +976,14 @@ int mt76u_init(struct mt76_dev *dev,
}
EXPORT_SYMBOL_GPL(mt76u_init);

void mt76u_deinit(struct mt76_dev *dev)
{
	if (dev->usb.stat_wq) {
		destroy_workqueue(dev->usb.stat_wq);
		dev->usb.stat_wq = NULL;
	}
}
EXPORT_SYMBOL_GPL(mt76u_deinit);

MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
MODULE_LICENSE("Dual BSD/GPL");