[PATCH wireless] wifi: mt76: mt7925: cancel mlo_pm_work on the USB stop path

Devin Wittmayer lucid_duck at justthetip.ca
Thu Sep 10 11:24:57 PDT 2026


81faf578320d added the cancel to mt7925_ops, but it never reaches USB.
mt7925u_probe() takes its own copy of the ops and points .stop back at the
shared mt792x handler, which cancels mac_work, ps_work, wake_work and
reset_work and knows nothing about mlo_pm_work. So the work still outlives
teardown there. The last line of that commit message says it covers both
buses. That's mine and it's a boo-boo.

Give the USB path its own stop that cancels the work first.

Two-link MLO on a Netgear A9000, work armed with a power-save change, then
the interface brought down:

                   stock    patched
    stop ran        3/3      3/3
    work still ran  3/3      0/3

Skipping the stop leaves both builds running the work, so the zero is the
cancel and not a setup that failed.

Fixes: 276a56883257 ("wifi: mt76: mt7925: update the power-saving flow")
Cc: stable at vger.kernel.org
Signed-off-by: Devin Wittmayer <lucid_duck at justthetip.ca>
---
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/usb.c b/drivers/net/wireless/mediatek/mt76/mt7925/usb.c
index 1757023..db6fd01 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/usb.c
@@ -147,6 +147,15 @@ out:
 	return err;
 }
 
+static void mt7925u_stop(struct ieee80211_hw *hw, bool suspend)
+{
+	struct mt792x_dev *dev = mt792x_hw_dev(hw);
+
+	cancel_delayed_work_sync(&dev->mlo_pm_work);
+
+	mt792xu_stop(hw, suspend);
+}
+
 static int mt7925u_probe(struct usb_interface *usb_intf,
 			 const struct usb_device_id *id)
 {
@@ -193,7 +202,7 @@ static int mt7925u_probe(struct usb_interface *usb_intf,
 	if (!ops)
 		return -ENOMEM;
 
-	ops->stop = mt792xu_stop;
+	ops->stop = mt7925u_stop;
 
 	mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
 	if (!mdev)



More information about the Linux-mediatek mailing list