diff options
author | Lorenzo Bianconi <lorenzo@kernel.org> | 2022-03-17 19:55:59 +0300 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2022-05-13 10:39:34 +0300 |
commit | df3e4143ba8ac159a0a55e84b616167219b7940b (patch) | |
tree | 63cf1d6f5f57cd51269833a2fc5f36cd5d4c5228 /drivers/net/wireless/mediatek/mt76/mt7921/usb.c | |
parent | b619e01380eedf24e8d26a367e94e0ccaeb0c3dd (diff) | |
download | linux-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.c | 62 |
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, }; |