OSDN Git Service

mt76: mt76u: rely on a dedicated stats workqueue
authorLorenzo Bianconi <lorenzo@kernel.org>
Mon, 28 Oct 2019 16:38:05 +0000 (17:38 +0100)
committerFelix Fietkau <nbd@nbd.name>
Wed, 20 Nov 2019 12:23:50 +0000 (13:23 +0100)
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>
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
drivers/net/wireless/mediatek/mt76/usb.c

index ac439fd..a65890c 100644 (file)
@@ -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);
index b9fd414..a8ab8df 100644 (file)
@@ -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);
 }
 
index 48b9017..b64ad81 100644 (file)
@@ -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);
index be19038..d6d4708 100644 (file)
@@ -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");