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: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
80df01f4dc
commit
284efb473e
4 changed files with 25 additions and 10 deletions
|
@ -387,7 +387,8 @@ struct mt76_usb {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tasklet_struct rx_tasklet;
|
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 out_ep[__MT_EP_OUT_MAX];
|
||||||
u8 in_ep[__MT_EP_IN_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,
|
void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
|
||||||
const u16 offset, const u32 val);
|
const u16 offset, const u32 val);
|
||||||
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf);
|
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);
|
int mt76u_alloc_queues(struct mt76_dev *dev);
|
||||||
void mt76u_stop_tx(struct mt76_dev *dev);
|
void mt76u_stop_tx(struct mt76_dev *dev);
|
||||||
void mt76u_stop_rx(struct mt76_dev *dev);
|
void mt76u_stop_rx(struct mt76_dev *dev);
|
||||||
|
|
|
@ -273,6 +273,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
|
||||||
err:
|
err:
|
||||||
usb_set_intfdata(usb_intf, NULL);
|
usb_set_intfdata(usb_intf, NULL);
|
||||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||||
|
mt76u_deinit(&dev->mt76);
|
||||||
|
|
||||||
ieee80211_free_hw(mdev->hw);
|
ieee80211_free_hw(mdev->hw);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -292,6 +293,7 @@ static void mt76x0_disconnect(struct usb_interface *usb_intf)
|
||||||
usb_set_intfdata(usb_intf, NULL);
|
usb_set_intfdata(usb_intf, NULL);
|
||||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||||
|
|
||||||
|
mt76u_deinit(&dev->mt76);
|
||||||
ieee80211_free_hw(dev->mt76.hw);
|
ieee80211_free_hw(dev->mt76.hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,7 @@ static int mt76x2u_probe(struct usb_interface *intf,
|
||||||
|
|
||||||
err:
|
err:
|
||||||
ieee80211_free_hw(mt76_hw(dev));
|
ieee80211_free_hw(mt76_hw(dev));
|
||||||
|
mt76u_deinit(&dev->mt76);
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
usb_put_dev(udev);
|
usb_put_dev(udev);
|
||||||
|
|
||||||
|
@ -88,6 +89,7 @@ static void mt76x2u_disconnect(struct usb_interface *intf)
|
||||||
set_bit(MT76_REMOVED, &dev->mt76.state);
|
set_bit(MT76_REMOVED, &dev->mt76.state);
|
||||||
ieee80211_unregister_hw(hw);
|
ieee80211_unregister_hw(hw);
|
||||||
mt76x2u_cleanup(dev);
|
mt76x2u_cleanup(dev);
|
||||||
|
mt76u_deinit(&dev->mt76);
|
||||||
|
|
||||||
ieee80211_free_hw(hw);
|
ieee80211_free_hw(hw);
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
|
|
|
@ -697,10 +697,7 @@ static void mt76u_tx_tasklet(unsigned long data)
|
||||||
mt76_txq_schedule(dev, i);
|
mt76_txq_schedule(dev, i);
|
||||||
|
|
||||||
if (!test_and_set_bit(MT76_READING_STATS, &dev->state))
|
if (!test_and_set_bit(MT76_READING_STATS, &dev->state))
|
||||||
ieee80211_queue_delayed_work(dev->hw,
|
queue_work(dev->usb.stat_wq, &dev->usb.stat_work);
|
||||||
&dev->usb.stat_work,
|
|
||||||
msecs_to_jiffies(10));
|
|
||||||
|
|
||||||
if (wake)
|
if (wake)
|
||||||
ieee80211_wake_queue(dev->hw, i);
|
ieee80211_wake_queue(dev->hw, i);
|
||||||
}
|
}
|
||||||
|
@ -713,7 +710,7 @@ static void mt76u_tx_status_data(struct work_struct *work)
|
||||||
u8 update = 1;
|
u8 update = 1;
|
||||||
u16 count = 0;
|
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);
|
dev = container_of(usb, struct mt76_dev, usb);
|
||||||
|
|
||||||
while (true) {
|
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))
|
if (count && test_bit(MT76_STATE_RUNNING, &dev->state))
|
||||||
ieee80211_queue_delayed_work(dev->hw, &usb->stat_work,
|
queue_work(usb->stat_wq, &usb->stat_work);
|
||||||
msecs_to_jiffies(10));
|
|
||||||
else
|
else
|
||||||
clear_bit(MT76_READING_STATS, &dev->state);
|
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);
|
clear_bit(MT76_READING_STATS, &dev->state);
|
||||||
|
|
||||||
mt76_tx_status_check(dev, NULL, true);
|
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(&usb->rx_tasklet, mt76u_rx_tasklet, (unsigned long)dev);
|
||||||
tasklet_init(&dev->tx_tasklet, mt76u_tx_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]);
|
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->mcu.mutex);
|
||||||
|
|
||||||
mutex_init(&usb->usb_ctrl_mtx);
|
mutex_init(&usb->usb_ctrl_mtx);
|
||||||
|
@ -976,5 +976,14 @@ int mt76u_init(struct mt76_dev *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mt76u_init);
|
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_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
|
|
Loading…
Add table
Reference in a new issue