]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mt76: mt792x: add common USB transport reset helpers
authorSean Wang <sean.wang@mediatek.com>
Wed, 1 Apr 2026 19:06:31 +0000 (14:06 -0500)
committerFelix Fietkau <nbd@nbd.name>
Tue, 9 Jun 2026 10:15:22 +0000 (10:15 +0000)
Add per-device USB reset work and a control-path access check helper
for mt7921u and mt7925u.

This prepares common infrastructure for transport-level recovery while
keeping the reset state per-device for correct lifetime handling.

No functional change intended.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Link: https://patch.msgid.link/20260401190632.147042-1-sean.wang@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7921/usb.c
drivers/net/wireless/mediatek/mt76/mt7925/usb.c
drivers/net/wireless/mediatek/mt76/mt792x.h
drivers/net/wireless/mediatek/mt76/mt792x_usb.c

index 4105c1baec1ec00778504e133ef7e9b8a973a180..01fa1b03e2105fdb4fb95784faae8397887cb090 100644 (file)
@@ -198,6 +198,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
        dev = container_of(mdev, struct mt792x_dev, mt76);
        dev->fw_features = features;
        dev->hif_ops = &hif_ops;
+       mt792xu_reset_work_init(dev);
 
        usb_reset_device(udev);
 
@@ -245,6 +246,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
 
 error:
        mt76u_queues_deinit(&dev->mt76);
+       mt792xu_reset_work_cleanup(dev);
 
        usb_set_intfdata(usb_intf, NULL);
 
index caacc54be71d3035c2b928869abde00bb1e2c2e8..e9f58492bf7df8c6003625686137e377216c90c5 100644 (file)
@@ -195,6 +195,7 @@ static int mt7925u_probe(struct usb_interface *usb_intf,
        dev = container_of(mdev, struct mt792x_dev, mt76);
        dev->fw_features = features;
        dev->hif_ops = &hif_ops;
+       mt792xu_reset_work_init(dev);
 
        usb_reset_device(udev);
 
@@ -249,6 +250,7 @@ static int mt7925u_probe(struct usb_interface *usb_intf,
 
 error:
        mt76u_queues_deinit(&dev->mt76);
+       mt792xu_reset_work_cleanup(dev);
 
        usb_set_intfdata(usb_intf, NULL);
 
index 4f823fb705d510e77363bbb975e644801841ac30..95e7fb64599d9c7718e1549a465a56c61dcaf6a6 100644 (file)
@@ -262,6 +262,8 @@ struct mt792x_dev {
        wait_queue_head_t wait;
 
        struct work_struct init_work;
+       struct work_struct usb_reset_work;
+       atomic_t usb_reset_pending;
 
        u8 fw_debug;
        u8 fw_features;
@@ -516,6 +518,9 @@ int mt792xu_dma_init(struct mt792x_dev *dev, bool resume);
 int mt792xu_mcu_power_on(struct mt792x_dev *dev);
 int mt792xu_wfsys_reset(struct mt792x_dev *dev);
 int mt792xu_init_reset(struct mt792x_dev *dev);
+void mt792xu_reset_work_init(struct mt792x_dev *dev);
+void mt792xu_reset_work_cleanup(struct mt792x_dev *dev);
+int mt792xu_check_bus(struct mt792x_dev *dev);
 u32 mt792xu_rr(struct mt76_dev *dev, u32 addr);
 void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val);
 u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val);
index be043e964c3cc9b9592fa7709ebb81c939c2ff4a..58d442b395362bf30a27d3ba4f71244c360042a2 100644 (file)
 #include "mt792x.h"
 #include "mt76_connac2_mac.h"
 
+static int mt792xu_read32(struct mt76_dev *dev, u32 addr, void *buf)
+{
+       return __mt76u_vendor_request(dev, MT_VEND_READ_EXT,
+                                     USB_DIR_IN | MT_USB_TYPE_VENDOR,
+                                     (u16)(addr >> 16), (u16)addr,
+                                     buf, sizeof(__le32));
+}
+
+static void mt792xu_reset_work(struct work_struct *work)
+{
+       struct mt792x_dev *dev =
+               container_of(work, struct mt792x_dev, usb_reset_work);
+       struct usb_interface *usb_intf = to_usb_interface(dev->mt76.dev);
+
+       if (usb_intf && usb_get_intfdata(usb_intf) == dev)
+               usb_queue_reset_device(usb_intf);
+
+       atomic_set(&dev->usb_reset_pending, 0);
+}
+
+void mt792xu_reset_work_init(struct mt792x_dev *dev)
+{
+       INIT_WORK(&dev->usb_reset_work, mt792xu_reset_work);
+       atomic_set(&dev->usb_reset_pending, 0);
+}
+EXPORT_SYMBOL_GPL(mt792xu_reset_work_init);
+
+void mt792xu_reset_work_cleanup(struct mt792x_dev *dev)
+{
+       cancel_work_sync(&dev->usb_reset_work);
+       atomic_set(&dev->usb_reset_pending, 0);
+}
+EXPORT_SYMBOL_GPL(mt792xu_reset_work_cleanup);
+
+int mt792xu_check_bus(struct mt792x_dev *dev)
+{
+       int ret;
+
+       mutex_lock(&dev->mt76.usb.usb_ctrl_mtx);
+       ret = mt792xu_read32(&dev->mt76, MT_HW_CHIPID, dev->mt76.usb.data);
+       mutex_unlock(&dev->mt76.usb.usb_ctrl_mtx);
+
+       if (ret == sizeof(__le32))
+               return 0;
+
+       return ret < 0 ? ret : -EIO;
+}
+EXPORT_SYMBOL_GPL(mt792xu_check_bus);
+
 u32 mt792xu_rr(struct mt76_dev *dev, u32 addr)
 {
        u32 ret;
@@ -333,6 +382,7 @@ void mt792xu_disconnect(struct usb_interface *usb_intf)
 {
        struct mt792x_dev *dev = usb_get_intfdata(usb_intf);
 
+       mt792xu_reset_work_cleanup(dev);
        cancel_work_sync(&dev->init_work);
        if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
                return;