summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
diff options
context:
space:
mode:
authorLorenzo Bianconi <lorenzo@kernel.org>2022-03-17 19:55:59 +0300
committerFelix Fietkau <nbd@nbd.name>2022-05-13 10:39:34 +0300
commitdf3e4143ba8ac159a0a55e84b616167219b7940b (patch)
tree63cf1d6f5f57cd51269833a2fc5f36cd5d4c5228 /drivers/net/wireless/mediatek/mt76/mt7921/usb.c
parentb619e01380eedf24e8d26a367e94e0ccaeb0c3dd (diff)
downloadlinux-df3e4143ba8ac159a0a55e84b616167219b7940b.tar.xz
mt76: mt7921u: add suspend/resume support
Introduce suspend/resume callbacks for mt7921u driver. Tested-by: Deren Wu <deren.wu@mediatek.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7921/usb.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/usb.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
index b7771e9f1fcd..dc38baef273a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
@@ -246,7 +246,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
if (ret)
goto error;
- ret = mt7921u_dma_init(dev);
+ ret = mt7921u_dma_init(dev, false);
if (ret)
return ret;
@@ -288,6 +288,61 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf)
mt76_free_device(&dev->mt76);
}
+#ifdef CONFIG_PM
+static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
+{
+ struct mt7921_dev *dev = usb_get_intfdata(intf);
+ int err;
+
+ err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
+ if (err)
+ return err;
+
+ mt76u_stop_rx(&dev->mt76);
+ mt76u_stop_tx(&dev->mt76);
+
+ set_bit(MT76_STATE_SUSPEND, &dev->mphy.state);
+
+ return 0;
+}
+
+static int mt7921u_resume(struct usb_interface *intf)
+{
+ struct mt7921_dev *dev = usb_get_intfdata(intf);
+ bool reinit = true;
+ int err, i;
+
+ for (i = 0; i < 10; i++) {
+ u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT);
+
+ if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) {
+ reinit = false;
+ break;
+ }
+ if (val & MT_WF_SW_SER_DONE_SUSPEND) {
+ mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0);
+ break;
+ }
+
+ msleep(20);
+ }
+
+ if (reinit || mt7921_dma_need_reinit(dev)) {
+ err = mt7921u_dma_init(dev, true);
+ if (err)
+ return err;
+ }
+
+ clear_bit(MT76_STATE_SUSPEND, &dev->mphy.state);
+
+ err = mt76u_resume_rx(&dev->mt76);
+ if (err < 0)
+ return err;
+
+ return mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
+}
+#endif /* CONFIG_PM */
+
MODULE_DEVICE_TABLE(usb, mt7921u_device_table);
MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
MODULE_FIRMWARE(MT7921_ROM_PATCH);
@@ -297,6 +352,11 @@ static struct usb_driver mt7921u_driver = {
.id_table = mt7921u_device_table,
.probe = mt7921u_probe,
.disconnect = mt7921u_disconnect,
+#ifdef CONFIG_PM
+ .suspend = mt7921u_suspend,
+ .resume = mt7921u_resume,
+ .reset_resume = mt7921u_resume,
+#endif /* CONFIG_PM */
.soft_unbind = 1,
.disable_hub_initiated_lpm = 1,
};