mt76: mt7663u: introduce suspend/resume to mt7663u
authorSean Wang <sean.wang@mediatek.com>
Fri, 1 May 2020 10:36:14 +0000 (12:36 +0200)
committerFelix Fietkau <nbd@nbd.name>
Tue, 12 May 2020 17:52:34 +0000 (19:52 +0200)
Tested on Chromebok by "echo mem to /sys/power/state" to suspend and
then waked up by keyboard keystrokes to resume system.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
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/mt7615/usb.c

index f1c9116b6ab4901240a00b0d89c0b3046ddf5c0c..728a2fb8b14d45831b571cf582560fb102c60698 100644 (file)
@@ -381,6 +381,7 @@ enum mt_vendor_req {
        MT_VEND_READ_CFG =      0x47,
        MT_VEND_READ_EXT =      0x63,
        MT_VEND_WRITE_EXT =     0x66,
+       MT_VEND_FEATURE_SET =   0x91,
 };
 
 enum mt76u_in_ep {
index 9353175b139bce0c5fdbaa8d28639409dec8235d..f2825b8f4539dec9df7db46cbeefaded92fafb3b 100644 (file)
@@ -372,18 +372,50 @@ static void mt7663u_disconnect(struct usb_interface *usb_intf)
        ieee80211_free_hw(dev->mt76.hw);
 }
 
-static int __maybe_unused
-mt7663u_suspend(struct usb_interface *intf,
-               pm_message_t state)
+#ifdef CONFIG_PM
+static int mt7663u_suspend(struct usb_interface *intf, pm_message_t state)
 {
+       struct mt7615_dev *dev = usb_get_intfdata(intf);
+
+       if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&
+           mt7615_firmware_offload(dev)) {
+               int err;
+
+               err = mt7615_mcu_set_hif_suspend(dev, true);
+               if (err < 0)
+                       return err;
+       }
+
+       mt76u_stop_rx(&dev->mt76);
+
+       mt76u_stop_tx(&dev->mt76);
+       tasklet_kill(&dev->mt76.tx_tasklet);
+
        return 0;
 }
 
-static int __maybe_unused
-mt7663u_resume(struct usb_interface *intf)
+static int mt7663u_resume(struct usb_interface *intf)
 {
-       return 0;
+       struct mt7615_dev *dev = usb_get_intfdata(intf);
+       int err;
+
+       err = mt76u_vendor_request(&dev->mt76, MT_VEND_FEATURE_SET,
+                                  USB_DIR_OUT | USB_TYPE_VENDOR,
+                                  0x5, 0x0, NULL, 0);
+       if (err)
+               return err;
+
+       err = mt76u_resume_rx(&dev->mt76);
+       if (err < 0)
+               return err;
+
+       if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&
+           mt7615_firmware_offload(dev))
+               err = mt7615_mcu_set_hif_suspend(dev, false);
+
+       return err;
 }
+#endif /* CONFIG_PM */
 
 MODULE_DEVICE_TABLE(usb, mt7615_device_table);
 MODULE_FIRMWARE(MT7663_OFFLOAD_FIRMWARE_N9);