diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7615/mcu.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 190 |
1 files changed, 102 insertions, 88 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 7781530fb3e6..31b40fb83f6c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -324,6 +324,97 @@ int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val) sizeof(req), false); } +static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) +{ + if (!is_mt7622(&dev->mt76)) + return; + + regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC, + MT_INFRACFG_MISC_AP2CONN_WAKE, + !en * MT_INFRACFG_MISC_AP2CONN_WAKE); +} + +static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_dev *mdev = &dev->mt76; + u32 addr; + int err; + + addr = is_mt7663(mdev) ? MT_PCIE_DOORBELL_PUSH : MT_CFG_LPCR_HOST; + mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN); + + mt7622_trigger_hif_int(dev, true); + + addr = is_mt7663(mdev) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; + err = !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000); + + mt7622_trigger_hif_int(dev, false); + + if (err) { + dev_err(mdev->dev, "driver own failed\n"); + return -ETIMEDOUT; + } + + clear_bit(MT76_STATE_PM, &mphy->state); + + return 0; +} + +static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + int i; + + if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state)) + goto out; + + for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) { + mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN); + if (mt76_poll_msec(dev, MT_CONN_HIF_ON_LPCTL, + MT_CFG_LPCR_HOST_FW_OWN, 0, 50)) + break; + } + + if (i == MT7615_DRV_OWN_RETRY_COUNT) { + dev_err(dev->mt76.dev, "driver own failed\n"); + set_bit(MT76_STATE_PM, &mphy->state); + return -EIO; + } + +out: + dev->pm.last_activity = jiffies; + + return 0; +} + +static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + int err = 0; + u32 addr; + + if (test_and_set_bit(MT76_STATE_PM, &mphy->state)) + return 0; + + mt7622_trigger_hif_int(dev, true); + + addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; + mt76_wr(dev, addr, MT_CFG_LPCR_HOST_FW_OWN); + + if (is_mt7622(&dev->mt76) && + !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, + MT_CFG_LPCR_HOST_FW_OWN, 3000)) { + dev_err(dev->mt76.dev, "Timeout for firmware own\n"); + clear_bit(MT76_STATE_PM, &mphy->state); + err = -EIO; + } + + mt7622_trigger_hif_int(dev, false); + + return err; +} + static void mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { @@ -1106,7 +1197,7 @@ mt7615_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), wtbl_tlv, sta_wtbl); ht = (struct wtbl_ht *)tlv; - ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; + ht->ldpc = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING); ht->af = sta->ht_cap.ampdu_factor; ht->mm = sta->ht_cap.ampdu_density; ht->ht = 1; @@ -1124,7 +1215,7 @@ mt7615_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_VHT, sizeof(*vht), wtbl_tlv, sta_wtbl); vht = (struct wtbl_vht *)tlv; - vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC, + vht->ldpc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); vht->vht = 1; af = (sta->vht_cap.cap & @@ -1314,6 +1405,8 @@ static const struct mt7615_mcu_ops wtbl_update_ops = { .add_tx_ba = mt7615_mcu_wtbl_tx_ba, .add_rx_ba = mt7615_mcu_wtbl_rx_ba, .sta_add = mt7615_mcu_wtbl_sta_add, + .set_drv_ctrl = mt7615_mcu_drv_pmctrl, + .set_fw_ctrl = mt7615_mcu_fw_pmctrl, }; static int @@ -1410,6 +1503,8 @@ static const struct mt7615_mcu_ops sta_update_ops = { .add_tx_ba = mt7615_mcu_sta_tx_ba, .add_rx_ba = mt7615_mcu_sta_rx_ba, .sta_add = mt7615_mcu_add_sta, + .set_drv_ctrl = mt7615_mcu_drv_pmctrl, + .set_fw_ctrl = mt7615_mcu_fw_pmctrl, }; static int @@ -1823,6 +1918,8 @@ static const struct mt7615_mcu_ops uni_update_ops = { .add_tx_ba = mt7615_mcu_uni_tx_ba, .add_rx_ba = mt7615_mcu_uni_rx_ba, .sta_add = mt7615_mcu_uni_add_sta, + .set_drv_ctrl = mt7615_mcu_lp_drv_pmctrl, + .set_fw_ctrl = mt7615_mcu_fw_pmctrl, }; static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, @@ -1895,81 +1992,6 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) &req, sizeof(req), true); } -static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) -{ - if (!is_mt7622(&dev->mt76)) - return; - - regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC, - MT_INFRACFG_MISC_AP2CONN_WAKE, - !en * MT_INFRACFG_MISC_AP2CONN_WAKE); -} - -int mt7615_driver_own(struct mt7615_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_dev *mdev = &dev->mt76; - int i; - - if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state)) - goto out; - - mt7622_trigger_hif_int(dev, true); - - for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) { - u32 addr; - - addr = is_mt7663(mdev) ? MT_PCIE_DOORBELL_PUSH : MT_CFG_LPCR_HOST; - mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN); - - addr = is_mt7663(mdev) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; - if (mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 50)) - break; - } - - mt7622_trigger_hif_int(dev, false); - - if (i == MT7615_DRV_OWN_RETRY_COUNT) { - dev_err(mdev->dev, "driver own failed\n"); - set_bit(MT76_STATE_PM, &mphy->state); - return -EIO; - } - -out: - dev->pm.last_activity = jiffies; - - return 0; -} -EXPORT_SYMBOL_GPL(mt7615_driver_own); - -int mt7615_firmware_own(struct mt7615_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - int err = 0; - u32 addr; - - if (test_and_set_bit(MT76_STATE_PM, &mphy->state)) - return 0; - - mt7622_trigger_hif_int(dev, true); - - addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; - mt76_wr(dev, addr, MT_CFG_LPCR_HOST_FW_OWN); - - if (is_mt7622(&dev->mt76) && - !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, - MT_CFG_LPCR_HOST_FW_OWN, 300)) { - dev_err(dev->mt76.dev, "Timeout for firmware own\n"); - clear_bit(MT76_STATE_PM, &mphy->state); - err = -EIO; - } - - mt7622_trigger_hif_int(dev, false); - - return err; -} -EXPORT_SYMBOL_GPL(mt7615_firmware_own); - static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) { const struct mt7615_patch_hdr *hdr; @@ -2452,7 +2474,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev) dev->mt76.mcu_ops = &mt7615_mcu_ops, - ret = mt7615_driver_own(dev); + ret = mt7615_mcu_drv_pmctrl(dev); if (ret) return ret; @@ -2482,7 +2504,7 @@ EXPORT_SYMBOL_GPL(mt7615_mcu_init); void mt7615_mcu_exit(struct mt7615_dev *dev) { __mt76_mcu_restart(&dev->mt76); - mt7615_firmware_own(dev); + mt7615_mcu_set_fw_ctrl(dev); skb_queue_purge(&dev->mt76.mcu.res_q); } EXPORT_SYMBOL_GPL(mt7615_mcu_exit); @@ -2847,14 +2869,6 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) .center_chan2 = ieee80211_frequency_to_channel(freq2), }; -#ifdef CONFIG_NL80211_TESTMODE - if (dev->mt76.test.state == MT76_TM_STATE_TX_FRAMES && - dev->mt76.test.tx_antenna_mask) { - req.tx_streams = hweight8(dev->mt76.test.tx_antenna_mask); - req.rx_streams_mask = dev->mt76.test.tx_antenna_mask; - } -#endif - if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && @@ -3279,7 +3293,7 @@ static int mt7615_dcoc_freq_idx(u16 freq, u8 bw) freq = freq_bw40[idx]; break; } - /* fall through */ + fallthrough; case NL80211_CHAN_WIDTH_40: idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40), freq); |