correct DMA registers and poll for firmware state, to fix "failed to get patch semaphore" timeout Signed-off-by: tnguy3333 <tnguy3333@xxxxxxxxx> --- .../net/wireless/mediatek/mt76/mt7902/mcu.c | 62 ++++++++++++++++++- .../wireless/mediatek/mt76/mt7902/mt7902.h | 6 +- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7902/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7902/mcu.c index dfb1b9ef9..677c2c165 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7902/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7902/mcu.c @@ -634,11 +634,71 @@ int mt7902_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl) &data, sizeof(data), false); } +int mt7902_firmware_state(struct mt792x_dev *dev, bool wa) +{ + u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE, + wa ? FW_STATE_RDY : FW_STATE_FW_DOWNLOAD); + + if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, + state, 1000)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; + } + return 0; +} + +int mt7902_load_firmware(struct mt792x_dev *dev) +{ + int ret; + + /* make sure fw is download state */ + if (mt7902_firmware_state(dev, false)) { + /* restart firmware once */ + mt76_connac_mcu_restart(&dev->mt76); + ret = mt7902_firmware_state(dev, false); + if (ret) { + dev_err(dev->mt76.dev, + "Firmware is not ready for download\n"); + return ret; + } + } + + ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev)); + if (ret) + return ret; + + if (mt76_is_sdio(&dev->mt76)) { + /* activate again */ + ret = __mt792x_mcu_fw_pmctrl(dev); + if (!ret) + ret = __mt792x_mcu_drv_pmctrl(dev); + } + + ret = mt76_connac2_load_ram(&dev->mt76, mt792x_ram_name(dev), NULL); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY, + MT_TOP_MISC2_FW_N9_RDY, 1500)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + + return -EIO; + } + +#ifdef CONFIG_PM + dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support; +#endif /* CONFIG_PM */ + + dev_dbg(dev->mt76.dev, "Firmware init done\n"); + + return 0; +} + int mt7902_run_firmware(struct mt792x_dev *dev) { int err; - err = mt792x_load_firmware(dev); + err = mt7902_load_firmware(dev); if (err) return err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7902/mt7902.h b/drivers/net/wireless/mediatek/mt76/mt7902/mt7902.h index 03beb683b..debd18034 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7902/mt7902.h +++ b/drivers/net/wireless/mediatek/mt76/mt7902/mt7902.h @@ -107,8 +107,8 @@ struct mt7902_sdio_intr { enum mt7902_txq_id { MT7902_TXQ_BAND0, MT7902_TXQ_BAND1, - MT7902_TXQ_FWDL = 16, - MT7902_TXQ_MCU_WM, + MT7902_TXQ_MCU_WM = 15, + MT7902_TXQ_FWDL, }; enum mt7902_rxq_id { @@ -188,6 +188,8 @@ u32 mt7902_reg_map(struct mt792x_dev *dev, u32 addr); int __mt7902_start(struct mt792x_phy *phy); int mt7902_register_device(struct mt792x_dev *dev); void mt7902_unregister_device(struct mt792x_dev *dev); +int mt7902_firmware_state(struct mt792x_dev *dev, bool wa); +int mt7902_load_firmware(struct mt792x_dev *dev); int mt7902_run_firmware(struct mt792x_dev *dev); int mt7902_set_channel(struct mt76_phy *mphy); int mt7902_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, -- 2.39.5