Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7615/mcu.c
48524 views
// SPDX-License-Identifier: ISC1/* Copyright (C) 2019 MediaTek Inc.2*3* Author: Roy Luo <[email protected]>4* Ryder Lee <[email protected]>5*/67#include <linux/firmware.h>8#include "mt7615.h"9#include "mcu.h"10#include "mac.h"11#include "eeprom.h"1213static bool prefer_offload_fw = true;14module_param(prefer_offload_fw, bool, 0644);15MODULE_PARM_DESC(prefer_offload_fw,16"Prefer client mode offload firmware (MT7663)");1718struct mt7615_patch_hdr {19char build_date[16];20char platform[4];21__be32 hw_sw_ver;22__be32 patch_ver;23__be16 checksum;24} __packed;2526struct mt7615_fw_trailer {27__le32 addr;28u8 chip_id;29u8 feature_set;30u8 eco_code;31char fw_ver[10];32char build_date[15];33__le32 len;34} __packed;3536#define FW_V3_COMMON_TAILER_SIZE 3637#define FW_V3_REGION_TAILER_SIZE 4038#define FW_START_OVERRIDE BIT(0)39#define FW_START_DLYCAL BIT(1)40#define FW_START_WORKING_PDA_CR4 BIT(2)4142struct mt7663_fw_buf {43__le32 crc;44__le32 d_img_size;45__le32 block_size;46u8 rsv[4];47__le32 img_dest_addr;48__le32 img_size;49u8 feature_set;50};5152#define MT7615_PATCH_ADDRESS 0x8000053#define MT7622_PATCH_ADDRESS 0x9c00054#define MT7663_PATCH_ADDRESS 0xdc0005556#define N9_REGION_NUM 257#define CR4_REGION_NUM 15859#define IMG_CRC_LEN 46061void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,62int cmd, int *wait_seq)63{64int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);65struct mt7615_uni_txd *uni_txd;66struct mt7615_mcu_txd *mcu_txd;67u8 seq, q_idx, pkt_fmt;68__le32 *txd;69u32 val;7071/* TODO: make dynamic based on msg type */72dev->mt76.mcu.timeout = 20 * HZ;7374seq = ++dev->mt76.mcu.msg_seq & 0xf;75if (!seq)76seq = ++dev->mt76.mcu.msg_seq & 0xf;77if (wait_seq)78*wait_seq = seq;7980txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd);81txd = (__le32 *)skb_push(skb, txd_len);8283if (cmd != MCU_CMD(FW_SCATTER)) {84q_idx = MT_TX_MCU_PORT_RX_Q0;85pkt_fmt = MT_TX_TYPE_CMD;86} else {87q_idx = MT_TX_MCU_PORT_RX_FWDL;88pkt_fmt = MT_TX_TYPE_FW;89}9091val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |92FIELD_PREP(MT_TXD0_P_IDX, MT_TX_PORT_IDX_MCU) |93FIELD_PREP(MT_TXD0_Q_IDX, q_idx);94txd[0] = cpu_to_le32(val);9596val = MT_TXD1_LONG_FORMAT |97FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD) |98FIELD_PREP(MT_TXD1_PKT_FMT, pkt_fmt);99txd[1] = cpu_to_le32(val);100101if (cmd & __MCU_CMD_FIELD_UNI) {102uni_txd = (struct mt7615_uni_txd *)txd;103uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd));104uni_txd->option = MCU_CMD_UNI_EXT_ACK;105uni_txd->cid = cpu_to_le16(mcu_cmd);106uni_txd->s2d_index = MCU_S2D_H2N;107uni_txd->pkt_type = MCU_PKT_ID;108uni_txd->seq = seq;109110return;111}112113mcu_txd = (struct mt7615_mcu_txd *)txd;114mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd));115mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, q_idx));116mcu_txd->s2d_index = MCU_S2D_H2N;117mcu_txd->pkt_type = MCU_PKT_ID;118mcu_txd->seq = seq;119mcu_txd->cid = mcu_cmd;120mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd);121122if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) {123if (cmd & __MCU_CMD_FIELD_QUERY)124mcu_txd->set_query = MCU_Q_QUERY;125else126mcu_txd->set_query = MCU_Q_SET;127mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid;128} else {129mcu_txd->set_query = MCU_Q_NA;130}131}132EXPORT_SYMBOL_GPL(mt7615_mcu_fill_msg);133134int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd,135struct sk_buff *skb, int seq)136{137struct mt7615_mcu_rxd *rxd;138int ret = 0;139140if (!skb) {141dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",142cmd, seq);143return -ETIMEDOUT;144}145146rxd = (struct mt7615_mcu_rxd *)skb->data;147if (seq != rxd->seq)148return -EAGAIN;149150if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {151skb_pull(skb, sizeof(*rxd) - 4);152ret = *skb->data;153} else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {154skb_pull(skb, sizeof(*rxd));155ret = le32_to_cpu(*(__le32 *)skb->data);156} else if (cmd == MCU_EXT_QUERY(RF_REG_ACCESS)) {157skb_pull(skb, sizeof(*rxd));158ret = le32_to_cpu(*(__le32 *)&skb->data[8]);159} else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) ||160cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) ||161cmd == MCU_UNI_CMD(STA_REC_UPDATE) ||162cmd == MCU_UNI_CMD(HIF_CTRL) ||163cmd == MCU_UNI_CMD(OFFLOAD) ||164cmd == MCU_UNI_CMD(SUSPEND)) {165struct mt76_connac_mcu_uni_event *event;166167skb_pull(skb, sizeof(*rxd));168event = (struct mt76_connac_mcu_uni_event *)skb->data;169ret = le32_to_cpu(event->status);170} else if (cmd == MCU_CE_QUERY(REG_READ)) {171struct mt76_connac_mcu_reg_event *event;172173skb_pull(skb, sizeof(*rxd));174event = (struct mt76_connac_mcu_reg_event *)skb->data;175ret = (int)le32_to_cpu(event->val);176}177178return ret;179}180EXPORT_SYMBOL_GPL(mt7615_mcu_parse_response);181182static int183mt7615_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,184int cmd, int *seq)185{186struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);187enum mt76_mcuq_id qid;188189mt7615_mcu_fill_msg(dev, skb, cmd, seq);190if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))191qid = MT_MCUQ_WM;192else193qid = MT_MCUQ_FWDL;194195return mt76_tx_queue_skb_raw(dev, dev->mt76.q_mcu[qid], skb, 0);196}197198u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg)199{200struct {201__le32 wifi_stream;202__le32 address;203__le32 data;204} req = {205.wifi_stream = cpu_to_le32(wf),206.address = cpu_to_le32(reg),207};208209return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_QUERY(RF_REG_ACCESS),210&req, sizeof(req), true);211}212213int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val)214{215struct {216__le32 wifi_stream;217__le32 address;218__le32 data;219} req = {220.wifi_stream = cpu_to_le32(wf),221.address = cpu_to_le32(reg),222.data = cpu_to_le32(val),223};224225return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_REG_ACCESS),226&req, sizeof(req), false);227}228229void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)230{231if (!is_mt7622(&dev->mt76))232return;233234#if defined(__linux__)235regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC,236MT_INFRACFG_MISC_AP2CONN_WAKE,237!en * MT_INFRACFG_MISC_AP2CONN_WAKE);238#elif defined(__FreeBSD__)239panic("%s: LinuxKPI needs regmap\n", __func__);240#endif241}242EXPORT_SYMBOL_GPL(mt7622_trigger_hif_int);243244static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev)245{246struct mt76_phy *mphy = &dev->mt76.phy;247struct mt76_connac_pm *pm = &dev->pm;248struct mt76_dev *mdev = &dev->mt76;249u32 addr;250int err;251252if (is_mt7663(mdev)) {253/* Clear firmware own via N9 eint */254mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN);255mt76_poll(dev, MT_CONN_ON_MISC, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000);256257addr = MT_CONN_HIF_ON_LPCTL;258} else {259addr = MT_CFG_LPCR_HOST;260}261262mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN);263264mt7622_trigger_hif_int(dev, true);265266err = !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000);267268mt7622_trigger_hif_int(dev, false);269270if (err) {271dev_err(mdev->dev, "driver own failed\n");272return -ETIMEDOUT;273}274275clear_bit(MT76_STATE_PM, &mphy->state);276277pm->stats.last_wake_event = jiffies;278pm->stats.doze_time += pm->stats.last_wake_event -279pm->stats.last_doze_event;280281return 0;282}283284static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev)285{286struct mt76_phy *mphy = &dev->mt76.phy;287struct mt76_connac_pm *pm = &dev->pm;288int i, err = 0;289290mutex_lock(&pm->mutex);291292if (!test_bit(MT76_STATE_PM, &mphy->state))293goto out;294295for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) {296mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN);297if (mt76_poll_msec(dev, MT_CONN_HIF_ON_LPCTL,298MT_CFG_LPCR_HOST_FW_OWN, 0, 50))299break;300}301302if (i == MT7615_DRV_OWN_RETRY_COUNT) {303dev_err(dev->mt76.dev, "driver own failed\n");304err = -EIO;305goto out;306}307clear_bit(MT76_STATE_PM, &mphy->state);308309pm->stats.last_wake_event = jiffies;310pm->stats.doze_time += pm->stats.last_wake_event -311pm->stats.last_doze_event;312out:313mutex_unlock(&pm->mutex);314315return err;316}317318static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev)319{320struct mt76_phy *mphy = &dev->mt76.phy;321struct mt76_connac_pm *pm = &dev->pm;322int err = 0;323u32 addr;324325mutex_lock(&pm->mutex);326327if (mt76_connac_skip_fw_pmctrl(mphy, pm))328goto out;329330mt7622_trigger_hif_int(dev, true);331332addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST;333mt76_wr(dev, addr, MT_CFG_LPCR_HOST_FW_OWN);334335if (is_mt7622(&dev->mt76) &&336!mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN,337MT_CFG_LPCR_HOST_FW_OWN, 3000)) {338dev_err(dev->mt76.dev, "Timeout for firmware own\n");339clear_bit(MT76_STATE_PM, &mphy->state);340err = -EIO;341}342343mt7622_trigger_hif_int(dev, false);344if (!err) {345pm->stats.last_doze_event = jiffies;346pm->stats.awake_time += pm->stats.last_doze_event -347pm->stats.last_wake_event;348}349out:350mutex_unlock(&pm->mutex);351352return err;353}354355static void356mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)357{358if (vif->bss_conf.csa_active)359ieee80211_csa_finish(vif, 0);360}361362static void363mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb)364{365struct mt7615_phy *ext_phy = mt7615_ext_phy(dev);366struct mt76_phy *mphy = &dev->mt76.phy;367struct mt7615_mcu_csa_notify *c;368369c = (struct mt7615_mcu_csa_notify *)skb->data;370371if (c->omac_idx > EXT_BSSID_MAX)372return;373374if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx))375mphy = dev->mt76.phys[MT_BAND1];376377ieee80211_iterate_active_interfaces_atomic(mphy->hw,378IEEE80211_IFACE_ITER_RESUME_ALL,379mt7615_mcu_csa_finish, mphy->hw);380}381382static void383mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)384{385struct mt76_phy *mphy = &dev->mt76.phy;386struct mt7615_mcu_rdd_report *r;387388r = (struct mt7615_mcu_rdd_report *)skb->data;389390if (!dev->radar_pattern.n_pulses && !r->long_detected &&391!r->constant_prf_detected && !r->staggered_prf_detected)392return;393394if (r->band_idx && dev->mt76.phys[MT_BAND1])395mphy = dev->mt76.phys[MT_BAND1];396397if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)398return;399400ieee80211_radar_detected(mphy->hw, NULL);401dev->hw_pattern++;402}403404static void405mt7615_mcu_rx_log_message(struct mt7615_dev *dev, struct sk_buff *skb)406{407struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;408const char *data = (char *)&rxd[1];409const char *type;410411switch (rxd->s2d_index) {412case 0:413type = "N9";414break;415case 2:416type = "CR4";417break;418default:419type = "unknown";420break;421}422423wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type,424(int)(skb->len - sizeof(*rxd)), data);425}426427static void428mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb)429{430struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;431432switch (rxd->ext_eid) {433case MCU_EXT_EVENT_RDD_REPORT:434mt7615_mcu_rx_radar_detected(dev, skb);435break;436case MCU_EXT_EVENT_CSA_NOTIFY:437mt7615_mcu_rx_csa_notify(dev, skb);438break;439case MCU_EXT_EVENT_FW_LOG_2_HOST:440mt7615_mcu_rx_log_message(dev, skb);441break;442default:443break;444}445}446447static void448mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb)449{450u8 *seq_num = skb->data + sizeof(struct mt7615_mcu_rxd);451struct mt7615_phy *phy;452struct mt76_phy *mphy;453454if (*seq_num & BIT(7) && dev->mt76.phys[MT_BAND1])455mphy = dev->mt76.phys[MT_BAND1];456else457mphy = &dev->mt76.phy;458459phy = mphy->priv;460461spin_lock_bh(&dev->mt76.lock);462__skb_queue_tail(&phy->scan_event_list, skb);463spin_unlock_bh(&dev->mt76.lock);464465ieee80211_queue_delayed_work(mphy->hw, &phy->scan_work,466MT7615_HW_SCAN_TIMEOUT);467}468469static void470mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb)471{472struct mt7615_roc_tlv *event;473struct mt7615_phy *phy;474struct mt76_phy *mphy;475int duration;476477skb_pull(skb, sizeof(struct mt7615_mcu_rxd));478event = (struct mt7615_roc_tlv *)skb->data;479480if (event->dbdc_band && dev->mt76.phys[MT_BAND1])481mphy = dev->mt76.phys[MT_BAND1];482else483mphy = &dev->mt76.phy;484485ieee80211_ready_on_channel(mphy->hw);486487phy = mphy->priv;488phy->roc_grant = true;489wake_up(&phy->roc_wait);490491duration = le32_to_cpu(event->max_interval);492mod_timer(&phy->roc_timer,493round_jiffies_up(jiffies + msecs_to_jiffies(duration)));494}495496static void497mt7615_mcu_beacon_loss_event(struct mt7615_dev *dev, struct sk_buff *skb)498{499struct mt76_connac_beacon_loss_event *event;500struct mt76_phy *mphy;501u8 band_idx = 0; /* DBDC support */502503skb_pull(skb, sizeof(struct mt7615_mcu_rxd));504event = (struct mt76_connac_beacon_loss_event *)skb->data;505if (band_idx && dev->mt76.phys[MT_BAND1])506mphy = dev->mt76.phys[MT_BAND1];507else508mphy = &dev->mt76.phy;509510ieee80211_iterate_active_interfaces_atomic(mphy->hw,511IEEE80211_IFACE_ITER_RESUME_ALL,512mt76_connac_mcu_beacon_loss_iter,513event);514}515516static void517mt7615_mcu_bss_event(struct mt7615_dev *dev, struct sk_buff *skb)518{519struct mt76_connac_mcu_bss_event *event;520struct mt76_phy *mphy;521u8 band_idx = 0; /* DBDC support */522523skb_pull(skb, sizeof(struct mt7615_mcu_rxd));524event = (struct mt76_connac_mcu_bss_event *)skb->data;525526if (band_idx && dev->mt76.phys[MT_BAND1])527mphy = dev->mt76.phys[MT_BAND1];528else529mphy = &dev->mt76.phy;530531if (event->is_absent)532ieee80211_stop_queues(mphy->hw);533else534ieee80211_wake_queues(mphy->hw);535}536537static void538mt7615_mcu_rx_unsolicited_event(struct mt7615_dev *dev, struct sk_buff *skb)539{540struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;541542switch (rxd->eid) {543case MCU_EVENT_EXT:544mt7615_mcu_rx_ext_event(dev, skb);545break;546case MCU_EVENT_BSS_BEACON_LOSS:547mt7615_mcu_beacon_loss_event(dev, skb);548break;549case MCU_EVENT_ROC:550mt7615_mcu_roc_event(dev, skb);551break;552case MCU_EVENT_SCHED_SCAN_DONE:553case MCU_EVENT_SCAN_DONE:554mt7615_mcu_scan_event(dev, skb);555return;556case MCU_EVENT_BSS_ABSENCE:557mt7615_mcu_bss_event(dev, skb);558break;559case MCU_EVENT_COREDUMP:560mt76_connac_mcu_coredump_event(&dev->mt76, skb,561&dev->coredump);562return;563default:564break;565}566dev_kfree_skb(skb);567}568569void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb)570{571struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;572573if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||574rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||575rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||576rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||577rxd->eid == MCU_EVENT_BSS_BEACON_LOSS ||578rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||579rxd->eid == MCU_EVENT_BSS_ABSENCE ||580rxd->eid == MCU_EVENT_SCAN_DONE ||581rxd->eid == MCU_EVENT_COREDUMP ||582rxd->eid == MCU_EVENT_ROC ||583!rxd->seq)584mt7615_mcu_rx_unsolicited_event(dev, skb);585else586mt76_mcu_rx_event(&dev->mt76, skb);587}588589static int590mt7615_mcu_muar_config(struct mt7615_dev *dev, struct ieee80211_vif *vif,591bool bssid, bool enable)592{593struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;594u32 idx = mvif->mt76.omac_idx - REPEATER_BSSID_START;595u32 mask = dev->omac_mask >> 32 & ~BIT(idx);596const u8 *addr = vif->addr;597struct {598u8 mode;599u8 force_clear;600u8 clear_bitmap[8];601u8 entry_count;602u8 write;603604u8 index;605u8 bssid;606u8 addr[ETH_ALEN];607} __packed req = {608.mode = !!mask || enable,609.entry_count = 1,610.write = 1,611612.index = idx * 2 + bssid,613};614615if (bssid)616addr = vif->bss_conf.bssid;617618if (enable)619ether_addr_copy(req.addr, addr);620621return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MUAR_UPDATE),622&req, sizeof(req), true);623}624625static int626mt7615_mcu_add_dev(struct mt7615_phy *phy, struct ieee80211_vif *vif,627bool enable)628{629struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;630struct mt7615_dev *dev = phy->dev;631struct {632struct req_hdr {633u8 omac_idx;634u8 band_idx;635__le16 tlv_num;636u8 is_tlv_append;637u8 rsv[3];638} __packed hdr;639struct req_tlv {640__le16 tag;641__le16 len;642u8 active;643u8 band_idx;644u8 omac_addr[ETH_ALEN];645} __packed tlv;646} data = {647.hdr = {648.omac_idx = mvif->mt76.omac_idx,649.band_idx = mvif->mt76.band_idx,650.tlv_num = cpu_to_le16(1),651.is_tlv_append = 1,652},653.tlv = {654.tag = cpu_to_le16(DEV_INFO_ACTIVE),655.len = cpu_to_le16(sizeof(struct req_tlv)),656.active = enable,657.band_idx = mvif->mt76.band_idx,658},659};660661if (mvif->mt76.omac_idx >= REPEATER_BSSID_START)662return mt7615_mcu_muar_config(dev, vif, false, enable);663664memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN);665return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(DEV_INFO_UPDATE),666&data, sizeof(data), true);667}668669static int670mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,671struct ieee80211_hw *hw,672struct ieee80211_vif *vif, bool enable)673{674struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;675struct mt76_wcid *wcid = &dev->mt76.global_wcid;676struct ieee80211_mutable_offsets offs;677struct ieee80211_tx_info *info;678struct req {679u8 omac_idx;680u8 enable;681u8 wlan_idx;682u8 band_idx;683u8 pkt_type;684u8 need_pre_tbtt_int;685__le16 csa_ie_pos;686__le16 pkt_len;687__le16 tim_ie_pos;688u8 pkt[512];689u8 csa_cnt;690/* bss color change */691u8 bcc_cnt;692__le16 bcc_ie_pos;693} __packed req = {694.omac_idx = mvif->mt76.omac_idx,695.enable = enable,696.wlan_idx = wcid->idx,697.band_idx = mvif->mt76.band_idx,698};699struct sk_buff *skb;700701if (!enable)702goto out;703704skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);705if (!skb)706return -EINVAL;707708if (skb->len > 512 - MT_TXD_SIZE) {709dev_err(dev->mt76.dev, "Bcn size limit exceed\n");710dev_kfree_skb(skb);711return -EINVAL;712}713714info = IEEE80211_SKB_CB(skb);715info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mvif->mt76.band_idx);716717mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL,7180, NULL, 0, true);719memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len);720req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);721req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);722if (offs.cntdwn_counter_offs[0]) {723u16 csa_offs;724725csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;726req.csa_ie_pos = cpu_to_le16(csa_offs);727req.csa_cnt = skb->data[offs.cntdwn_counter_offs[0]];728}729dev_kfree_skb(skb);730731out:732return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(BCN_OFFLOAD), &req,733sizeof(req), true);734}735736static int737mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)738{739return mt76_connac_mcu_set_pm(&dev->mt76, band, state);740}741742static int743mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,744struct ieee80211_sta *sta, bool enable)745{746struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;747struct mt7615_dev *dev = phy->dev;748struct sk_buff *skb;749750if (mvif->mt76.omac_idx >= REPEATER_BSSID_START)751mt7615_mcu_muar_config(dev, vif, true, enable);752753skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL);754if (IS_ERR(skb))755return PTR_ERR(skb);756757if (enable)758mt76_connac_mcu_bss_omac_tlv(skb, vif);759760mt76_connac_mcu_bss_basic_tlv(skb, vif, sta, phy->mt76,761mvif->sta.wcid.idx, enable);762763if (enable && mvif->mt76.omac_idx >= EXT_BSSID_START &&764mvif->mt76.omac_idx < REPEATER_BSSID_START)765mt76_connac_mcu_bss_ext_tlv(skb, &mvif->mt76);766767return mt76_mcu_skb_send_msg(&dev->mt76, skb,768MCU_EXT_CMD(BSS_INFO_UPDATE), true);769}770771static int772mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev,773struct ieee80211_ampdu_params *params,774bool enable)775{776struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;777struct mt7615_vif *mvif = msta->vif;778struct wtbl_req_hdr *wtbl_hdr;779struct sk_buff *skb = NULL;780int err;781782wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,783WTBL_SET, NULL, &skb);784if (IS_ERR(wtbl_hdr))785return PTR_ERR(wtbl_hdr);786787mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, true,788NULL, wtbl_hdr);789790err = mt76_mcu_skb_send_msg(&dev->mt76, skb,791MCU_EXT_CMD(WTBL_UPDATE), true);792if (err < 0)793return err;794795skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,796&msta->wcid);797if (IS_ERR(skb))798return PTR_ERR(skb);799800mt76_connac_mcu_sta_ba_tlv(skb, params, enable, true);801802return mt76_mcu_skb_send_msg(&dev->mt76, skb,803MCU_EXT_CMD(STA_REC_UPDATE), true);804}805806static int807mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev,808struct ieee80211_ampdu_params *params,809bool enable)810{811struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;812struct mt7615_vif *mvif = msta->vif;813struct wtbl_req_hdr *wtbl_hdr;814struct sk_buff *skb;815int err;816817skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,818&msta->wcid);819if (IS_ERR(skb))820return PTR_ERR(skb);821822mt76_connac_mcu_sta_ba_tlv(skb, params, enable, false);823824err = mt76_mcu_skb_send_msg(&dev->mt76, skb,825MCU_EXT_CMD(STA_REC_UPDATE), true);826if (err < 0 || !enable)827return err;828829skb = NULL;830wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,831WTBL_SET, NULL, &skb);832if (IS_ERR(wtbl_hdr))833return PTR_ERR(wtbl_hdr);834835mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, false,836NULL, wtbl_hdr);837838return mt76_mcu_skb_send_msg(&dev->mt76, skb,839MCU_EXT_CMD(WTBL_UPDATE), true);840}841842static int843mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,844struct ieee80211_sta *sta, bool enable)845{846struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;847struct sk_buff *skb, *sskb, *wskb = NULL;848struct ieee80211_link_sta *link_sta;849struct mt7615_dev *dev = phy->dev;850struct wtbl_req_hdr *wtbl_hdr;851struct mt7615_sta *msta;852bool new_entry = true;853int conn_state;854int cmd, err;855856msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta;857link_sta = sta ? &sta->deflink : NULL;858859sskb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,860&msta->wcid);861if (IS_ERR(sskb))862return PTR_ERR(sskb);863864if (!sta) {865if (mvif->sta_added)866new_entry = false;867else868mvif->sta_added = true;869}870conn_state = enable ? CONN_STATE_PORT_SECURE : CONN_STATE_DISCONNECT;871mt76_connac_mcu_sta_basic_tlv(&dev->mt76, sskb, &vif->bss_conf,872link_sta, conn_state, new_entry);873if (enable && sta)874mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0,875MT76_STA_INFO_STATE_ASSOC);876877wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,878WTBL_RESET_AND_SET, NULL,879&wskb);880if (IS_ERR(wtbl_hdr))881return PTR_ERR(wtbl_hdr);882883if (enable) {884mt76_connac_mcu_wtbl_generic_tlv(&dev->mt76, wskb, vif, sta,885NULL, wtbl_hdr);886if (sta)887mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta,888NULL, wtbl_hdr, true, true);889mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, &msta->wcid,890NULL, wtbl_hdr);891}892893cmd = enable ? MCU_EXT_CMD(WTBL_UPDATE) : MCU_EXT_CMD(STA_REC_UPDATE);894skb = enable ? wskb : sskb;895896err = mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);897if (err < 0) {898skb = enable ? sskb : wskb;899dev_kfree_skb(skb);900901return err;902}903904cmd = enable ? MCU_EXT_CMD(STA_REC_UPDATE) : MCU_EXT_CMD(WTBL_UPDATE);905skb = enable ? sskb : wskb;906907return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);908}909910static int911mt7615_mcu_wtbl_update_hdr_trans(struct mt7615_dev *dev,912struct ieee80211_vif *vif,913struct ieee80211_sta *sta)914{915return mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);916}917918static const struct mt7615_mcu_ops wtbl_update_ops = {919.add_beacon_offload = mt7615_mcu_add_beacon_offload,920.set_pm_state = mt7615_mcu_ctrl_pm_state,921.add_dev_info = mt7615_mcu_add_dev,922.add_bss_info = mt7615_mcu_add_bss,923.add_tx_ba = mt7615_mcu_wtbl_tx_ba,924.add_rx_ba = mt7615_mcu_wtbl_rx_ba,925.sta_add = mt7615_mcu_wtbl_sta_add,926.set_drv_ctrl = mt7615_mcu_drv_pmctrl,927.set_fw_ctrl = mt7615_mcu_fw_pmctrl,928.set_sta_decap_offload = mt7615_mcu_wtbl_update_hdr_trans,929};930931static int932mt7615_mcu_sta_ba(struct mt7615_dev *dev,933struct ieee80211_ampdu_params *params,934bool enable, bool tx)935{936struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;937struct mt7615_vif *mvif = msta->vif;938struct wtbl_req_hdr *wtbl_hdr;939struct tlv *sta_wtbl;940struct sk_buff *skb;941942skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,943&msta->wcid);944if (IS_ERR(skb))945return PTR_ERR(skb);946947mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx);948949sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv));950951wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,952WTBL_SET, sta_wtbl, &skb);953if (IS_ERR(wtbl_hdr))954return PTR_ERR(wtbl_hdr);955956mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, tx,957sta_wtbl, wtbl_hdr);958959return mt76_mcu_skb_send_msg(&dev->mt76, skb,960MCU_EXT_CMD(STA_REC_UPDATE), true);961}962963static int964mt7615_mcu_sta_tx_ba(struct mt7615_dev *dev,965struct ieee80211_ampdu_params *params,966bool enable)967{968return mt7615_mcu_sta_ba(dev, params, enable, true);969}970971static int972mt7615_mcu_sta_rx_ba(struct mt7615_dev *dev,973struct ieee80211_ampdu_params *params,974bool enable)975{976return mt7615_mcu_sta_ba(dev, params, enable, false);977}978979static int980__mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif,981struct ieee80211_sta *sta, bool enable, int cmd,982bool offload_fw)983{984struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;985struct mt76_sta_cmd_info info = {986.sta = sta,987.vif = vif,988.offload_fw = offload_fw,989.enable = enable,990.newly = true,991.cmd = cmd,992};993994info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;995return mt76_connac_mcu_sta_cmd(phy, &info);996}997998static int999mt7615_mcu_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif,1000struct ieee80211_sta *sta, bool enable)1001{1002return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable,1003MCU_EXT_CMD(STA_REC_UPDATE), false);1004}10051006static int1007mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,1008struct ieee80211_vif *vif,1009struct ieee80211_sta *sta)1010{1011struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;10121013return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,1014vif, &msta->wcid,1015MCU_EXT_CMD(STA_REC_UPDATE));1016}10171018static const struct mt7615_mcu_ops sta_update_ops = {1019.add_beacon_offload = mt7615_mcu_add_beacon_offload,1020.set_pm_state = mt7615_mcu_ctrl_pm_state,1021.add_dev_info = mt7615_mcu_add_dev,1022.add_bss_info = mt7615_mcu_add_bss,1023.add_tx_ba = mt7615_mcu_sta_tx_ba,1024.add_rx_ba = mt7615_mcu_sta_rx_ba,1025.sta_add = mt7615_mcu_add_sta,1026.set_drv_ctrl = mt7615_mcu_drv_pmctrl,1027.set_fw_ctrl = mt7615_mcu_fw_pmctrl,1028.set_sta_decap_offload = mt7615_mcu_sta_update_hdr_trans,1029};10301031static int1032mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)1033{1034return 0;1035}10361037static int1038mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,1039struct ieee80211_hw *hw,1040struct ieee80211_vif *vif,1041bool enable)1042{1043struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;1044struct mt76_wcid *wcid = &dev->mt76.global_wcid;1045struct ieee80211_mutable_offsets offs;1046struct {1047struct req_hdr {1048u8 bss_idx;1049u8 pad[3];1050} __packed hdr;1051struct bcn_content_tlv {1052__le16 tag;1053__le16 len;1054__le16 tim_ie_pos;1055__le16 csa_ie_pos;1056__le16 bcc_ie_pos;1057/* 0: disable beacon offload1058* 1: enable beacon offload1059* 2: update probe respond offload1060*/1061u8 enable;1062/* 0: legacy format (TXD + payload)1063* 1: only cap field IE1064*/1065u8 type;1066__le16 pkt_len;1067u8 pkt[512];1068} __packed beacon_tlv;1069} req = {1070.hdr = {1071.bss_idx = mvif->mt76.idx,1072},1073.beacon_tlv = {1074.tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT),1075.len = cpu_to_le16(sizeof(struct bcn_content_tlv)),1076.enable = enable,1077},1078};1079struct sk_buff *skb;10801081if (!enable)1082goto out;10831084skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0);1085if (!skb)1086return -EINVAL;10871088if (skb->len > 512 - MT_TXD_SIZE) {1089dev_err(dev->mt76.dev, "beacon size limit exceed\n");1090dev_kfree_skb(skb);1091return -EINVAL;1092}10931094mt7615_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb,1095wcid, NULL, 0, NULL, 0, true);1096memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);1097req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);1098req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);10991100if (offs.cntdwn_counter_offs[0]) {1101u16 csa_offs;11021103csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;1104req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs);1105}1106dev_kfree_skb(skb);11071108out:1109return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),1110&req, sizeof(req), true);1111}11121113static int1114mt7615_mcu_uni_add_dev(struct mt7615_phy *phy, struct ieee80211_vif *vif,1115bool enable)1116{1117struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;11181119return mt76_connac_mcu_uni_add_dev(phy->mt76, &vif->bss_conf, &mvif->mt76,1120&mvif->sta.wcid, enable);1121}11221123static int1124mt7615_mcu_uni_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,1125struct ieee80211_sta *sta, bool enable)1126{1127struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;11281129return mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,1130enable, NULL);1131}11321133static inline int1134mt7615_mcu_uni_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif,1135struct ieee80211_sta *sta, bool enable)1136{1137return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable,1138MCU_UNI_CMD(STA_REC_UPDATE), true);1139}11401141static int1142mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev,1143struct ieee80211_ampdu_params *params,1144bool enable)1145{1146struct mt7615_sta *sta = (struct mt7615_sta *)params->sta->drv_priv;11471148return mt76_connac_mcu_sta_ba(&dev->mt76, &sta->vif->mt76, params,1149MCU_UNI_CMD(STA_REC_UPDATE), enable,1150true);1151}11521153static int1154mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev,1155struct ieee80211_ampdu_params *params,1156bool enable)1157{1158struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;1159struct mt7615_vif *mvif = msta->vif;1160struct wtbl_req_hdr *wtbl_hdr;1161struct tlv *sta_wtbl;1162struct sk_buff *skb;1163int err;11641165skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,1166&msta->wcid);1167if (IS_ERR(skb))1168return PTR_ERR(skb);11691170mt76_connac_mcu_sta_ba_tlv(skb, params, enable, false);11711172err = mt76_mcu_skb_send_msg(&dev->mt76, skb,1173MCU_UNI_CMD(STA_REC_UPDATE), true);1174if (err < 0 || !enable)1175return err;11761177skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,1178&msta->wcid);1179if (IS_ERR(skb))1180return PTR_ERR(skb);11811182sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,1183sizeof(struct tlv));11841185wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,1186WTBL_SET, sta_wtbl, &skb);1187if (IS_ERR(wtbl_hdr))1188return PTR_ERR(wtbl_hdr);11891190mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, false,1191sta_wtbl, wtbl_hdr);11921193return mt76_mcu_skb_send_msg(&dev->mt76, skb,1194MCU_UNI_CMD(STA_REC_UPDATE), true);1195}11961197static int1198mt7615_mcu_sta_uni_update_hdr_trans(struct mt7615_dev *dev,1199struct ieee80211_vif *vif,1200struct ieee80211_sta *sta)1201{1202struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;12031204return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,1205vif, &msta->wcid,1206MCU_UNI_CMD(STA_REC_UPDATE));1207}12081209static const struct mt7615_mcu_ops uni_update_ops = {1210.add_beacon_offload = mt7615_mcu_uni_add_beacon_offload,1211.set_pm_state = mt7615_mcu_uni_ctrl_pm_state,1212.add_dev_info = mt7615_mcu_uni_add_dev,1213.add_bss_info = mt7615_mcu_uni_add_bss,1214.add_tx_ba = mt7615_mcu_uni_tx_ba,1215.add_rx_ba = mt7615_mcu_uni_rx_ba,1216.sta_add = mt7615_mcu_uni_add_sta,1217.set_drv_ctrl = mt7615_mcu_lp_drv_pmctrl,1218.set_fw_ctrl = mt7615_mcu_fw_pmctrl,1219.set_sta_decap_offload = mt7615_mcu_sta_uni_update_hdr_trans,1220};12211222int mt7615_mcu_restart(struct mt76_dev *dev)1223{1224return mt76_mcu_send_msg(dev, MCU_CMD(RESTART_DL_REQ), NULL, 0, true);1225}1226EXPORT_SYMBOL_GPL(mt7615_mcu_restart);12271228static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name)1229{1230const struct mt7615_patch_hdr *hdr;1231const struct firmware *fw = NULL;1232int len, ret, sem;12331234ret = firmware_request_nowarn(&fw, name, dev->mt76.dev);1235if (ret)1236return ret;12371238if (!fw || !fw->data || fw->size < sizeof(*hdr)) {1239dev_err(dev->mt76.dev, "Invalid firmware\n");1240ret = -EINVAL;1241goto release_fw;1242}12431244sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, true);1245switch (sem) {1246case PATCH_IS_DL:1247goto release_fw;1248case PATCH_NOT_DL_SEM_SUCCESS:1249break;1250default:1251dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");1252ret = -EAGAIN;1253goto release_fw;1254}12551256hdr = (const struct mt7615_patch_hdr *)(fw->data);12571258dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",1259be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);12601261len = fw->size - sizeof(*hdr);12621263ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,1264DL_MODE_NEED_RSP);1265if (ret) {1266dev_err(dev->mt76.dev, "Download request failed\n");1267goto out;1268}12691270ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),1271fw->data + sizeof(*hdr), len);1272if (ret) {1273dev_err(dev->mt76.dev, "Failed to send firmware to device\n");1274goto out;1275}12761277ret = mt76_connac_mcu_start_patch(&dev->mt76);1278if (ret)1279dev_err(dev->mt76.dev, "Failed to start patch\n");12801281out:1282sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);1283switch (sem) {1284case PATCH_REL_SEM_SUCCESS:1285break;1286default:1287ret = -EAGAIN;1288dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");1289break;1290}12911292release_fw:1293release_firmware(fw);12941295return ret;1296}12971298static int1299mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev,1300const struct mt7615_fw_trailer *hdr,1301const u8 *data, bool is_cr4)1302{1303int n_region = is_cr4 ? CR4_REGION_NUM : N9_REGION_NUM;1304int err, i, offset = 0;1305u32 len, addr, mode;13061307for (i = 0; i < n_region; i++) {1308mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,1309hdr[i].feature_set, is_cr4);1310len = le32_to_cpu(hdr[i].len) + IMG_CRC_LEN;1311addr = le32_to_cpu(hdr[i].addr);13121313err = mt76_connac_mcu_init_download(&dev->mt76, addr, len,1314mode);1315if (err) {1316dev_err(dev->mt76.dev, "Download request failed\n");1317return err;1318}13191320err = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),1321data + offset, len);1322if (err) {1323dev_err(dev->mt76.dev, "Failed to send firmware to device\n");1324return err;1325}13261327offset += len;1328}13291330return 0;1331}13321333static int mt7615_load_n9(struct mt7615_dev *dev, const char *name)1334{1335const struct mt7615_fw_trailer *hdr;1336const struct firmware *fw;1337int ret;13381339ret = request_firmware(&fw, name, dev->mt76.dev);1340if (ret)1341return ret;13421343if (!fw || !fw->data || fw->size < N9_REGION_NUM * sizeof(*hdr)) {1344dev_err(dev->mt76.dev, "Invalid firmware\n");1345ret = -EINVAL;1346goto out;1347}13481349hdr = (const struct mt7615_fw_trailer *)(fw->data + fw->size -1350N9_REGION_NUM * sizeof(*hdr));13511352dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",1353hdr->fw_ver, hdr->build_date);13541355ret = mt7615_mcu_send_ram_firmware(dev, hdr, fw->data, false);1356if (ret)1357goto out;13581359ret = mt76_connac_mcu_start_firmware(&dev->mt76,1360le32_to_cpu(hdr->addr),1361FW_START_OVERRIDE);1362if (ret) {1363dev_err(dev->mt76.dev, "Failed to start N9 firmware\n");1364goto out;1365}13661367snprintf(dev->mt76.hw->wiphy->fw_version,1368sizeof(dev->mt76.hw->wiphy->fw_version),1369"%.10s-%.15s", hdr->fw_ver, hdr->build_date);13701371if (!is_mt7615(&dev->mt76)) {1372dev->fw_ver = MT7615_FIRMWARE_V2;1373dev->mcu_ops = &sta_update_ops;1374} else {1375dev->fw_ver = MT7615_FIRMWARE_V1;1376dev->mcu_ops = &wtbl_update_ops;1377}13781379out:1380release_firmware(fw);1381return ret;1382}13831384static int mt7615_load_cr4(struct mt7615_dev *dev, const char *name)1385{1386const struct mt7615_fw_trailer *hdr;1387const struct firmware *fw;1388int ret;13891390ret = request_firmware(&fw, name, dev->mt76.dev);1391if (ret)1392return ret;13931394if (!fw || !fw->data || fw->size < CR4_REGION_NUM * sizeof(*hdr)) {1395dev_err(dev->mt76.dev, "Invalid firmware\n");1396ret = -EINVAL;1397goto out;1398}13991400hdr = (const struct mt7615_fw_trailer *)(fw->data + fw->size -1401CR4_REGION_NUM * sizeof(*hdr));14021403dev_info(dev->mt76.dev, "CR4 Firmware Version: %.10s, Build Time: %.15s\n",1404hdr->fw_ver, hdr->build_date);14051406ret = mt7615_mcu_send_ram_firmware(dev, hdr, fw->data, true);1407if (ret)1408goto out;14091410ret = mt76_connac_mcu_start_firmware(&dev->mt76, 0,1411FW_START_WORKING_PDA_CR4);1412if (ret) {1413dev_err(dev->mt76.dev, "Failed to start CR4 firmware\n");1414goto out;1415}14161417out:1418release_firmware(fw);14191420return ret;1421}14221423static int mt7615_load_ram(struct mt7615_dev *dev)1424{1425int ret;14261427ret = mt7615_load_n9(dev, MT7615_FIRMWARE_N9);1428if (ret)1429return ret;14301431return mt7615_load_cr4(dev, MT7615_FIRMWARE_CR4);1432}14331434static int mt7615_load_firmware(struct mt7615_dev *dev)1435{1436int ret;1437u32 val;14381439val = mt76_get_field(dev, MT_TOP_MISC2, MT_TOP_MISC2_FW_STATE);14401441if (val != FW_STATE_FW_DOWNLOAD) {1442dev_err(dev->mt76.dev, "Firmware is not ready for download\n");1443return -EIO;1444}14451446ret = mt7615_load_patch(dev, MT7615_PATCH_ADDRESS, MT7615_ROM_PATCH);1447if (ret)1448return ret;14491450ret = mt7615_load_ram(dev);1451if (ret)1452return ret;14531454if (!mt76_poll_msec(dev, MT_TOP_MISC2, MT_TOP_MISC2_FW_STATE,1455FIELD_PREP(MT_TOP_MISC2_FW_STATE,1456FW_STATE_RDY), 500)) {1457dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");1458return -EIO;1459}14601461return 0;1462}14631464static int mt7622_load_firmware(struct mt7615_dev *dev)1465{1466int ret;1467u32 val;14681469mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);14701471val = mt76_get_field(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE);1472if (val != FW_STATE_FW_DOWNLOAD) {1473dev_err(dev->mt76.dev, "Firmware is not ready for download\n");1474return -EIO;1475}14761477ret = mt7615_load_patch(dev, MT7622_PATCH_ADDRESS, MT7622_ROM_PATCH);1478if (ret)1479return ret;14801481ret = mt7615_load_n9(dev, MT7622_FIRMWARE_N9);1482if (ret)1483return ret;14841485if (!mt76_poll_msec(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE,1486FIELD_PREP(MT_TOP_OFF_RSV_FW_STATE,1487FW_STATE_NORMAL_TRX), 1500)) {1488dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");1489return -EIO;1490}14911492mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);14931494return 0;1495}14961497int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl)1498{1499struct {1500u8 ctrl_val;1501u8 pad[3];1502} data = {1503.ctrl_val = ctrl1504};15051506return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(FW_LOG_2_HOST),1507&data, sizeof(data), true);1508}15091510static int mt7615_mcu_cal_cache_apply(struct mt7615_dev *dev)1511{1512struct {1513bool cache_enable;1514u8 pad[3];1515} data = {1516.cache_enable = true1517};15181519return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(CAL_CACHE), &data,1520sizeof(data), false);1521}15221523static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)1524{1525u32 offset = 0, override_addr = 0, flag = FW_START_DLYCAL;1526const struct mt76_connac2_fw_trailer *hdr;1527const struct mt7663_fw_buf *buf;1528const struct firmware *fw;1529const u8 *base_addr;1530int i, ret;15311532ret = request_firmware(&fw, name, dev->mt76.dev);1533if (ret)1534return ret;15351536if (!fw || !fw->data || fw->size < FW_V3_COMMON_TAILER_SIZE) {1537dev_err(dev->mt76.dev, "Invalid firmware\n");1538ret = -EINVAL;1539goto out;1540}15411542hdr = (const void *)(fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE);1543dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",1544hdr->fw_ver, hdr->build_date);1545dev_info(dev->mt76.dev, "Region number: 0x%x\n", hdr->n_region);15461547base_addr = fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE;1548for (i = 0; i < hdr->n_region; i++) {1549u32 shift = (hdr->n_region - i) * FW_V3_REGION_TAILER_SIZE;1550u32 len, addr, mode;15511552dev_info(dev->mt76.dev, "Parsing tailer Region: %d\n", i);15531554buf = (const struct mt7663_fw_buf *)(base_addr - shift);1555mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,1556buf->feature_set, false);1557addr = le32_to_cpu(buf->img_dest_addr);1558len = le32_to_cpu(buf->img_size);15591560ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,1561mode);1562if (ret) {1563dev_err(dev->mt76.dev, "Download request failed\n");1564goto out;1565}15661567ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),1568fw->data + offset, len);1569if (ret) {1570dev_err(dev->mt76.dev, "Failed to send firmware\n");1571goto out;1572}15731574offset += le32_to_cpu(buf->img_size);1575if (buf->feature_set & DL_MODE_VALID_RAM_ENTRY) {1576override_addr = le32_to_cpu(buf->img_dest_addr);1577dev_info(dev->mt76.dev, "Region %d, override_addr = 0x%08x\n",1578i, override_addr);1579}1580}15811582if (override_addr)1583flag |= FW_START_OVERRIDE;15841585dev_info(dev->mt76.dev, "override_addr = 0x%08x, option = %d\n",1586override_addr, flag);15871588ret = mt76_connac_mcu_start_firmware(&dev->mt76, override_addr, flag);1589if (ret) {1590dev_err(dev->mt76.dev, "Failed to start N9 firmware\n");1591goto out;1592}15931594snprintf(dev->mt76.hw->wiphy->fw_version,1595sizeof(dev->mt76.hw->wiphy->fw_version),1596"%.10s-%.15s", hdr->fw_ver, hdr->build_date);15971598out:1599release_firmware(fw);16001601return ret;1602}16031604static int1605mt7663_load_rom_patch(struct mt7615_dev *dev, const char **n9_firmware)1606{1607const char *selected_rom, *secondary_rom = MT7663_ROM_PATCH;1608const char *primary_rom = MT7663_OFFLOAD_ROM_PATCH;1609int ret;16101611if (!prefer_offload_fw) {1612secondary_rom = MT7663_OFFLOAD_ROM_PATCH;1613primary_rom = MT7663_ROM_PATCH;1614}1615selected_rom = primary_rom;16161617ret = mt7615_load_patch(dev, MT7663_PATCH_ADDRESS, primary_rom);1618if (ret) {1619dev_info(dev->mt76.dev, "%s not found, switching to %s",1620primary_rom, secondary_rom);1621ret = mt7615_load_patch(dev, MT7663_PATCH_ADDRESS,1622secondary_rom);1623if (ret) {1624dev_err(dev->mt76.dev, "failed to load %s",1625secondary_rom);1626return ret;1627}1628selected_rom = secondary_rom;1629}16301631if (!strcmp(selected_rom, MT7663_OFFLOAD_ROM_PATCH)) {1632*n9_firmware = MT7663_OFFLOAD_FIRMWARE_N9;1633dev->fw_ver = MT7615_FIRMWARE_V3;1634dev->mcu_ops = &uni_update_ops;1635} else {1636*n9_firmware = MT7663_FIRMWARE_N9;1637dev->fw_ver = MT7615_FIRMWARE_V2;1638dev->mcu_ops = &sta_update_ops;1639}16401641return 0;1642}16431644int __mt7663_load_firmware(struct mt7615_dev *dev)1645{1646const char *n9_firmware;1647int ret;16481649ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);1650if (ret) {1651dev_dbg(dev->mt76.dev, "Firmware is already download\n");1652return -EIO;1653}16541655ret = mt7663_load_rom_patch(dev, &n9_firmware);1656if (ret)1657return ret;16581659ret = mt7663_load_n9(dev, n9_firmware);1660if (ret)1661return ret;16621663if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY,1664MT_TOP_MISC2_FW_N9_RDY, 1500)) {1665ret = mt76_get_field(dev, MT_CONN_ON_MISC,1666MT7663_TOP_MISC2_FW_STATE);1667dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");1668return -EIO;1669}16701671#ifdef CONFIG_PM1672if (mt7615_firmware_offload(dev))1673dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;1674#endif /* CONFIG_PM */16751676dev_dbg(dev->mt76.dev, "Firmware init done\n");16771678return 0;1679}1680EXPORT_SYMBOL_GPL(__mt7663_load_firmware);16811682static int mt7663_load_firmware(struct mt7615_dev *dev)1683{1684int ret;16851686mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);16871688ret = __mt7663_load_firmware(dev);1689if (ret)1690return ret;16911692mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);16931694return 0;1695}16961697int mt7615_mcu_init(struct mt7615_dev *dev)1698{1699static const struct mt76_mcu_ops mt7615_mcu_ops = {1700.headroom = sizeof(struct mt7615_mcu_txd),1701.mcu_skb_send_msg = mt7615_mcu_send_message,1702.mcu_parse_response = mt7615_mcu_parse_response,1703};1704int ret;17051706dev->mt76.mcu_ops = &mt7615_mcu_ops;17071708ret = mt7615_mcu_drv_pmctrl(dev);1709if (ret)1710return ret;17111712switch (mt76_chip(&dev->mt76)) {1713case 0x7622:1714ret = mt7622_load_firmware(dev);1715break;1716case 0x7663:1717ret = mt7663_load_firmware(dev);1718break;1719default:1720ret = mt7615_load_firmware(dev);1721break;1722}1723if (ret)1724return ret;17251726mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);1727dev_dbg(dev->mt76.dev, "Firmware init done\n");1728set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);17291730if (dev->dbdc_support) {1731ret = mt7615_mcu_cal_cache_apply(dev);1732if (ret)1733return ret;1734}17351736return mt7615_mcu_fw_log_2_host(dev, 0);1737}1738EXPORT_SYMBOL_GPL(mt7615_mcu_init);17391740void mt7615_mcu_exit(struct mt7615_dev *dev)1741{1742mt7615_mcu_restart(&dev->mt76);1743mt7615_mcu_set_fw_ctrl(dev);1744skb_queue_purge(&dev->mt76.mcu.res_q);1745}1746EXPORT_SYMBOL_GPL(mt7615_mcu_exit);17471748int mt7615_mcu_set_eeprom(struct mt7615_dev *dev)1749{1750struct {1751u8 buffer_mode;1752u8 content_format;1753__le16 len;1754} __packed req_hdr = {1755.buffer_mode = 1,1756};1757u8 *eep = (u8 *)dev->mt76.eeprom.data;1758struct sk_buff *skb;1759int eep_len, offset;17601761switch (mt76_chip(&dev->mt76)) {1762case 0x7622:1763eep_len = MT7622_EE_MAX - MT_EE_NIC_CONF_0;1764offset = MT_EE_NIC_CONF_0;1765break;1766case 0x7663:1767eep_len = MT7663_EE_MAX - MT_EE_CHIP_ID;1768req_hdr.content_format = 1;1769offset = MT_EE_CHIP_ID;1770break;1771default:1772eep_len = MT7615_EE_MAX - MT_EE_NIC_CONF_0;1773offset = MT_EE_NIC_CONF_0;1774break;1775}17761777req_hdr.len = cpu_to_le16(eep_len);17781779skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) + eep_len);1780if (!skb)1781return -ENOMEM;17821783skb_put_data(skb, &req_hdr, sizeof(req_hdr));1784skb_put_data(skb, eep + offset, eep_len);17851786return mt76_mcu_skb_send_msg(&dev->mt76, skb,1787MCU_EXT_CMD(EFUSE_BUFFER_MODE), true);1788}17891790int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue,1791const struct ieee80211_tx_queue_params *params)1792{1793#define WMM_AIFS_SET BIT(0)1794#define WMM_CW_MIN_SET BIT(1)1795#define WMM_CW_MAX_SET BIT(2)1796#define WMM_TXOP_SET BIT(3)1797#define WMM_PARAM_SET (WMM_AIFS_SET | WMM_CW_MIN_SET | \1798WMM_CW_MAX_SET | WMM_TXOP_SET)1799struct req_data {1800u8 number;1801u8 rsv[3];1802u8 queue;1803u8 valid;1804u8 aifs;1805u8 cw_min;1806__le16 cw_max;1807__le16 txop;1808} __packed req = {1809.number = 1,1810.queue = queue,1811.valid = WMM_PARAM_SET,1812.aifs = params->aifs,1813.cw_min = 5,1814.cw_max = cpu_to_le16(10),1815.txop = cpu_to_le16(params->txop),1816};18171818if (params->cw_min)1819req.cw_min = fls(params->cw_min);1820if (params->cw_max)1821req.cw_max = cpu_to_le16(fls(params->cw_max));18221823return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EDCA_UPDATE),1824&req, sizeof(req), true);1825}18261827int mt7615_mcu_set_dbdc(struct mt7615_dev *dev)1828{1829struct mt7615_phy *ext_phy = mt7615_ext_phy(dev);1830struct dbdc_entry {1831u8 type;1832u8 index;1833u8 band;1834u8 _rsv;1835};1836struct {1837u8 enable;1838u8 num;1839u8 _rsv[2];1840struct dbdc_entry entry[64];1841} req = {1842.enable = !!ext_phy,1843};1844int i;18451846if (!ext_phy)1847goto out;18481849#define ADD_DBDC_ENTRY(_type, _idx, _band) \1850do { \1851req.entry[req.num].type = _type; \1852req.entry[req.num].index = _idx; \1853req.entry[req.num++].band = _band; \1854} while (0)18551856for (i = 0; i < 4; i++) {1857bool band = !!(ext_phy->omac_mask & BIT_ULL(i));18581859ADD_DBDC_ENTRY(DBDC_TYPE_BSS, i, band);1860}18611862for (i = 0; i < 14; i++) {1863bool band = !!(ext_phy->omac_mask & BIT_ULL(0x11 + i));18641865ADD_DBDC_ENTRY(DBDC_TYPE_MBSS, i, band);1866}18671868ADD_DBDC_ENTRY(DBDC_TYPE_MU, 0, 1);18691870for (i = 0; i < 3; i++)1871ADD_DBDC_ENTRY(DBDC_TYPE_BF, i, 1);18721873ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 0, 0);1874ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 1, 0);1875ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 2, 1);1876ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 3, 1);18771878ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 0, 0);1879ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 1, 1);18801881out:1882return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(DBDC_CTRL), &req,1883sizeof(req), true);1884}18851886int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val)1887{1888struct {1889__le16 tag;1890__le16 min_lpn;1891} req = {1892.tag = cpu_to_le16(0x1),1893.min_lpn = cpu_to_le16(val),1894};18951896return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH),1897&req, sizeof(req), true);1898}18991900int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,1901const struct mt7615_dfs_pulse *pulse)1902{1903struct {1904__le16 tag;1905__le32 max_width; /* us */1906__le32 max_pwr; /* dbm */1907__le32 min_pwr; /* dbm */1908__le32 min_stgr_pri; /* us */1909__le32 max_stgr_pri; /* us */1910__le32 min_cr_pri; /* us */1911__le32 max_cr_pri; /* us */1912} req = {1913.tag = cpu_to_le16(0x3),1914#define __req_field(field) .field = cpu_to_le32(pulse->field)1915__req_field(max_width),1916__req_field(max_pwr),1917__req_field(min_pwr),1918__req_field(min_stgr_pri),1919__req_field(max_stgr_pri),1920__req_field(min_cr_pri),1921__req_field(max_cr_pri),1922#undef __req_field1923};19241925return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH),1926&req, sizeof(req), true);1927}19281929int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index,1930const struct mt7615_dfs_pattern *pattern)1931{1932struct {1933__le16 tag;1934__le16 radar_type;1935u8 enb;1936u8 stgr;1937u8 min_crpn;1938u8 max_crpn;1939u8 min_crpr;1940u8 min_pw;1941u8 max_pw;1942__le32 min_pri;1943__le32 max_pri;1944u8 min_crbn;1945u8 max_crbn;1946u8 min_stgpn;1947u8 max_stgpn;1948u8 min_stgpr;1949} req = {1950.tag = cpu_to_le16(0x2),1951.radar_type = cpu_to_le16(index),1952#define __req_field_u8(field) .field = pattern->field1953#define __req_field_u32(field) .field = cpu_to_le32(pattern->field)1954__req_field_u8(enb),1955__req_field_u8(stgr),1956__req_field_u8(min_crpn),1957__req_field_u8(max_crpn),1958__req_field_u8(min_crpr),1959__req_field_u8(min_pw),1960__req_field_u8(max_pw),1961__req_field_u32(min_pri),1962__req_field_u32(max_pri),1963__req_field_u8(min_crbn),1964__req_field_u8(max_crbn),1965__req_field_u8(min_stgpn),1966__req_field_u8(max_stgpn),1967__req_field_u8(min_stgpr),1968#undef __req_field_u81969#undef __req_field_u321970};19711972return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH),1973&req, sizeof(req), true);1974}19751976int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev)1977{1978struct {1979u8 pulse_num;1980u8 rsv[3];1981struct {1982__le32 start_time;1983__le16 width;1984__le16 power;1985} pattern[32];1986} req = {1987.pulse_num = dev->radar_pattern.n_pulses,1988};1989u32 start_time = ktime_to_ms(ktime_get_boottime());1990int i;19911992if (dev->radar_pattern.n_pulses > ARRAY_SIZE(req.pattern))1993return -EINVAL;19941995/* TODO: add some noise here */1996for (i = 0; i < dev->radar_pattern.n_pulses; i++) {1997u32 ts = start_time + i * dev->radar_pattern.period;19981999req.pattern[i].width = cpu_to_le16(dev->radar_pattern.width);2000req.pattern[i].power = cpu_to_le16(dev->radar_pattern.power);2001req.pattern[i].start_time = cpu_to_le32(ts);2002}20032004return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_PATTERN),2005&req, sizeof(req), false);2006}20072008static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku)2009{2010struct mt76_phy *mphy = phy->mt76;2011struct ieee80211_hw *hw = mphy->hw;2012struct mt76_power_limits limits;2013s8 *limits_array = (s8 *)&limits;2014int n_chains = hweight8(mphy->antenna_mask);2015int tx_power = hw->conf.power_level * 2;2016int i;2017static const u8 sku_mapping[] = {2018#define SKU_FIELD(_type, _field) \2019[MT_SKU_##_type] = offsetof(struct mt76_power_limits, _field)2020SKU_FIELD(CCK_1_2, cck[0]),2021SKU_FIELD(CCK_55_11, cck[2]),2022SKU_FIELD(OFDM_6_9, ofdm[0]),2023SKU_FIELD(OFDM_12_18, ofdm[2]),2024SKU_FIELD(OFDM_24_36, ofdm[4]),2025SKU_FIELD(OFDM_48, ofdm[6]),2026SKU_FIELD(OFDM_54, ofdm[7]),2027SKU_FIELD(HT20_0_8, mcs[0][0]),2028SKU_FIELD(HT20_32, ofdm[0]),2029SKU_FIELD(HT20_1_2_9_10, mcs[0][1]),2030SKU_FIELD(HT20_3_4_11_12, mcs[0][3]),2031SKU_FIELD(HT20_5_13, mcs[0][5]),2032SKU_FIELD(HT20_6_14, mcs[0][6]),2033SKU_FIELD(HT20_7_15, mcs[0][7]),2034SKU_FIELD(HT40_0_8, mcs[1][0]),2035SKU_FIELD(HT40_32, ofdm[0]),2036SKU_FIELD(HT40_1_2_9_10, mcs[1][1]),2037SKU_FIELD(HT40_3_4_11_12, mcs[1][3]),2038SKU_FIELD(HT40_5_13, mcs[1][5]),2039SKU_FIELD(HT40_6_14, mcs[1][6]),2040SKU_FIELD(HT40_7_15, mcs[1][7]),2041SKU_FIELD(VHT20_0, mcs[0][0]),2042SKU_FIELD(VHT20_1_2, mcs[0][1]),2043SKU_FIELD(VHT20_3_4, mcs[0][3]),2044SKU_FIELD(VHT20_5_6, mcs[0][5]),2045SKU_FIELD(VHT20_7, mcs[0][7]),2046SKU_FIELD(VHT20_8, mcs[0][8]),2047SKU_FIELD(VHT20_9, mcs[0][9]),2048SKU_FIELD(VHT40_0, mcs[1][0]),2049SKU_FIELD(VHT40_1_2, mcs[1][1]),2050SKU_FIELD(VHT40_3_4, mcs[1][3]),2051SKU_FIELD(VHT40_5_6, mcs[1][5]),2052SKU_FIELD(VHT40_7, mcs[1][7]),2053SKU_FIELD(VHT40_8, mcs[1][8]),2054SKU_FIELD(VHT40_9, mcs[1][9]),2055SKU_FIELD(VHT80_0, mcs[2][0]),2056SKU_FIELD(VHT80_1_2, mcs[2][1]),2057SKU_FIELD(VHT80_3_4, mcs[2][3]),2058SKU_FIELD(VHT80_5_6, mcs[2][5]),2059SKU_FIELD(VHT80_7, mcs[2][7]),2060SKU_FIELD(VHT80_8, mcs[2][8]),2061SKU_FIELD(VHT80_9, mcs[2][9]),2062SKU_FIELD(VHT160_0, mcs[3][0]),2063SKU_FIELD(VHT160_1_2, mcs[3][1]),2064SKU_FIELD(VHT160_3_4, mcs[3][3]),2065SKU_FIELD(VHT160_5_6, mcs[3][5]),2066SKU_FIELD(VHT160_7, mcs[3][7]),2067SKU_FIELD(VHT160_8, mcs[3][8]),2068SKU_FIELD(VHT160_9, mcs[3][9]),2069#undef SKU_FIELD2070};20712072tx_power = mt76_get_sar_power(mphy, mphy->chandef.chan, tx_power);2073tx_power -= mt76_tx_power_path_delta(n_chains);2074tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,2075&limits, tx_power);2076mphy->txpower_cur = tx_power;20772078if (is_mt7663(mphy->dev)) {2079memset(sku, tx_power, MT_SKU_4SS_DELTA + 1);2080return;2081}20822083for (i = 0; i < MT_SKU_1SS_DELTA; i++)2084sku[i] = limits_array[sku_mapping[i]];20852086for (i = 0; i < 4; i++) {2087int delta = 0;20882089if (i < n_chains - 1)2090delta = mt76_tx_power_path_delta(n_chains) -2091mt76_tx_power_path_delta(i + 1);2092sku[MT_SKU_1SS_DELTA + i] = delta;2093}2094}20952096static u8 mt7615_mcu_chan_bw(struct cfg80211_chan_def *chandef)2097{2098static const u8 width_to_bw[] = {2099[NL80211_CHAN_WIDTH_40] = CMD_CBW_40MHZ,2100[NL80211_CHAN_WIDTH_80] = CMD_CBW_80MHZ,2101[NL80211_CHAN_WIDTH_80P80] = CMD_CBW_8080MHZ,2102[NL80211_CHAN_WIDTH_160] = CMD_CBW_160MHZ,2103[NL80211_CHAN_WIDTH_5] = CMD_CBW_5MHZ,2104[NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ,2105[NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ,2106[NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ,2107};21082109if (chandef->width >= ARRAY_SIZE(width_to_bw))2110return 0;21112112return width_to_bw[chandef->width];2113}21142115int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)2116{2117struct mt7615_dev *dev = phy->dev;2118struct cfg80211_chan_def *chandef = &phy->mt76->chandef;2119int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;2120struct {2121u8 control_chan;2122u8 center_chan;2123u8 bw;2124u8 tx_streams;2125u8 rx_streams_mask;2126u8 switch_reason;2127u8 band_idx;2128/* for 80+80 only */2129u8 center_chan2;2130__le16 cac_case;2131u8 channel_band;2132u8 rsv0;2133__le32 outband_freq;2134u8 txpower_drop;2135u8 rsv1[3];2136u8 txpower_sku[53];2137u8 rsv2[3];2138} req = {2139.control_chan = chandef->chan->hw_value,2140.center_chan = ieee80211_frequency_to_channel(freq1),2141.tx_streams = hweight8(phy->mt76->antenna_mask),2142.rx_streams_mask = phy->mt76->chainmask,2143.center_chan2 = ieee80211_frequency_to_channel(freq2),2144};21452146if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||2147phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)2148req.switch_reason = CH_SWITCH_NORMAL;2149else if (phy->mt76->offchannel)2150req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;2151else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,2152NL80211_IFTYPE_AP))2153req.switch_reason = CH_SWITCH_DFS;2154else2155req.switch_reason = CH_SWITCH_NORMAL;21562157req.band_idx = phy != &dev->phy;2158req.bw = mt7615_mcu_chan_bw(chandef);21592160if (mt76_testmode_enabled(phy->mt76))2161memset(req.txpower_sku, 0x3f, 49);2162else2163mt7615_mcu_set_txpower_sku(phy, req.txpower_sku);21642165return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);2166}21672168int mt7615_mcu_get_temperature(struct mt7615_dev *dev)2169{2170struct {2171u8 action;2172u8 rsv[3];2173} req = {};21742175return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL),2176&req, sizeof(req), true);2177}21782179int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode,2180u32 val)2181{2182struct {2183u8 test_mode_en;2184u8 param_idx;2185u8 _rsv[2];21862187__le32 value;21882189u8 pad[8];2190} req = {2191.test_mode_en = test_mode,2192.param_idx = param,2193.value = cpu_to_le32(val),2194};21952196return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL),2197&req, sizeof(req), false);2198}21992200int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable)2201{2202struct mt7615_dev *dev = phy->dev;2203struct {2204u8 format_id;2205u8 sku_enable;2206u8 band_idx;2207u8 rsv;2208} req = {2209.format_id = 0,2210.band_idx = phy != &dev->phy,2211.sku_enable = enable,2212};22132214return mt76_mcu_send_msg(&dev->mt76,2215MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),2216&req, sizeof(req), true);2217}22182219static int mt7615_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)2220{2221int i;22222223for (i = 0; i < n_freqs; i++)2224if (cur == freqs[i])2225return i;22262227return -1;2228}22292230static int mt7615_dcoc_freq_idx(u16 freq, u8 bw)2231{2232static const u16 freq_list[] = {22334980, 5805, 5905, 5190,22345230, 5270, 5310, 5350,22355390, 5430, 5470, 5510,22365550, 5590, 5630, 5670,22375710, 5755, 5795, 5835,22385875, 5210, 5290, 5370,22395450, 5530, 5610, 5690,22405775, 58552241};2242static const u16 freq_bw40[] = {22435190, 5230, 5270, 5310,22445350, 5390, 5430, 5470,22455510, 5550, 5590, 5630,22465670, 5710, 5755, 5795,22475835, 58752248};2249int offset_2g = ARRAY_SIZE(freq_list);2250int idx;22512252if (freq < 4000) {2253if (freq < 2427)2254return offset_2g;2255if (freq < 2442)2256return offset_2g + 1;2257if (freq < 2457)2258return offset_2g + 2;22592260return offset_2g + 3;2261}22622263switch (bw) {2264case NL80211_CHAN_WIDTH_80:2265case NL80211_CHAN_WIDTH_80P80:2266case NL80211_CHAN_WIDTH_160:2267break;2268default:2269idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),2270freq + 10);2271if (idx >= 0) {2272freq = freq_bw40[idx];2273break;2274}22752276idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),2277freq - 10);2278if (idx >= 0) {2279freq = freq_bw40[idx];2280break;2281}2282fallthrough;2283case NL80211_CHAN_WIDTH_40:2284idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),2285freq);2286if (idx >= 0)2287break;22882289return -1;22902291}22922293return mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), freq);2294}22952296int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy)2297{2298struct mt7615_dev *dev = phy->dev;2299struct cfg80211_chan_def *chandef = &phy->mt76->chandef;2300int freq2 = chandef->center_freq2;2301int ret;2302struct {2303u8 direction;2304u8 runtime_calibration;2305u8 _rsv[2];23062307__le16 center_freq;2308u8 bw;2309u8 band;2310u8 is_freq2;2311u8 success;2312u8 dbdc_en;23132314u8 _rsv2;23152316struct {2317__le32 sx0_i_lna[4];2318__le32 sx0_q_lna[4];23192320__le32 sx2_i_lna[4];2321__le32 sx2_q_lna[4];2322} dcoc_data[4];2323} req = {2324.direction = 1,23252326.bw = mt7615_mcu_chan_bw(chandef),2327.band = chandef->center_freq1 > 4000,2328.dbdc_en = !!dev->mt76.phys[MT_BAND1],2329};2330u16 center_freq = chandef->center_freq1;2331int freq_idx;2332u8 *eep = dev->mt76.eeprom.data;23332334if (!(eep[MT_EE_CALDATA_FLASH] & MT_EE_CALDATA_FLASH_RX_CAL))2335return 0;23362337if (chandef->width == NL80211_CHAN_WIDTH_160) {2338freq2 = center_freq + 40;2339center_freq -= 40;2340}23412342again:2343req.runtime_calibration = 1;2344freq_idx = mt7615_dcoc_freq_idx(center_freq, chandef->width);2345if (freq_idx < 0)2346goto out;23472348memcpy(req.dcoc_data, eep + MT7615_EEPROM_DCOC_OFFSET +2349freq_idx * MT7615_EEPROM_DCOC_SIZE,2350sizeof(req.dcoc_data));2351req.runtime_calibration = 0;23522353out:2354req.center_freq = cpu_to_le16(center_freq);2355ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RXDCOC_CAL), &req,2356sizeof(req), true);23572358if ((chandef->width == NL80211_CHAN_WIDTH_80P80 ||2359chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) {2360req.is_freq2 = true;2361center_freq = freq2;2362goto again;2363}23642365return ret;2366}23672368static int mt7615_dpd_freq_idx(u16 freq, u8 bw)2369{2370static const u16 freq_list[] = {23714920, 4940, 4960, 4980,23725040, 5060, 5080, 5180,23735200, 5220, 5240, 5260,23745280, 5300, 5320, 5340,23755360, 5380, 5400, 5420,23765440, 5460, 5480, 5500,23775520, 5540, 5560, 5580,23785600, 5620, 5640, 5660,23795680, 5700, 5720, 5745,23805765, 5785, 5805, 5825,23815845, 5865, 5885, 59052382};2383int offset_2g = ARRAY_SIZE(freq_list);2384int idx;23852386if (freq < 4000) {2387if (freq < 2432)2388return offset_2g;2389if (freq < 2457)2390return offset_2g + 1;23912392return offset_2g + 2;2393}23942395if (bw != NL80211_CHAN_WIDTH_20) {2396idx = mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),2397freq + 10);2398if (idx >= 0)2399return idx;24002401idx = mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),2402freq - 10);2403if (idx >= 0)2404return idx;2405}24062407return mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), freq);2408}240924102411int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy)2412{2413struct mt7615_dev *dev = phy->dev;2414struct cfg80211_chan_def *chandef = &phy->mt76->chandef;2415int freq2 = chandef->center_freq2;2416int ret;2417struct {2418u8 direction;2419u8 runtime_calibration;2420u8 _rsv[2];24212422__le16 center_freq;2423u8 bw;2424u8 band;2425u8 is_freq2;2426u8 success;2427u8 dbdc_en;24282429u8 _rsv2;24302431struct {2432struct {2433u32 dpd_g0;2434u8 data[32];2435} wf0, wf1;24362437struct {2438u32 dpd_g0_prim;2439u32 dpd_g0_sec;2440u8 data_prim[32];2441u8 data_sec[32];2442} wf2, wf3;2443} dpd_data;2444} req = {2445.direction = 1,24462447.bw = mt7615_mcu_chan_bw(chandef),2448.band = chandef->center_freq1 > 4000,2449.dbdc_en = !!dev->mt76.phys[MT_BAND1],2450};2451u16 center_freq = chandef->center_freq1;2452int freq_idx;2453u8 *eep = dev->mt76.eeprom.data;24542455if (!(eep[MT_EE_CALDATA_FLASH] & MT_EE_CALDATA_FLASH_TX_DPD))2456return 0;24572458if (chandef->width == NL80211_CHAN_WIDTH_160) {2459freq2 = center_freq + 40;2460center_freq -= 40;2461}24622463again:2464req.runtime_calibration = 1;2465freq_idx = mt7615_dpd_freq_idx(center_freq, chandef->width);2466if (freq_idx < 0)2467goto out;24682469memcpy(&req.dpd_data, eep + MT7615_EEPROM_TXDPD_OFFSET +2470freq_idx * MT7615_EEPROM_TXDPD_SIZE,2471sizeof(req.dpd_data));2472req.runtime_calibration = 0;24732474out:2475req.center_freq = cpu_to_le16(center_freq);2476ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXDPD_CAL),2477&req, sizeof(req), true);24782479if ((chandef->width == NL80211_CHAN_WIDTH_80P80 ||2480chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) {2481req.is_freq2 = true;2482center_freq = freq2;2483goto again;2484}24852486return ret;2487}24882489int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev)2490{2491struct {2492u8 operation;2493u8 count;2494u8 _rsv[2];2495u8 index;2496u8 enable;2497__le16 etype;2498} req = {2499.operation = 1,2500.count = 1,2501.enable = 1,2502.etype = cpu_to_le16(ETH_P_PAE),2503};25042505return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS),2506&req, sizeof(req), false);2507}25082509int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,2510bool enable)2511{2512struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;2513struct {2514u8 bss_idx;2515u8 dtim_period;2516__le16 aid;2517__le16 bcn_interval;2518__le16 atim_window;2519u8 uapsd;2520u8 bmc_delivered_ac;2521u8 bmc_triggered_ac;2522u8 pad;2523} req = {2524.bss_idx = mvif->mt76.idx,2525.aid = cpu_to_le16(vif->cfg.aid),2526.dtim_period = vif->bss_conf.dtim_period,2527.bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int),2528};2529struct {2530u8 bss_idx;2531u8 pad[3];2532} req_hdr = {2533.bss_idx = mvif->mt76.idx,2534};2535int err;25362537if (vif->type != NL80211_IFTYPE_STATION)2538return 0;25392540err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT),2541&req_hdr, sizeof(req_hdr), false);2542if (err < 0 || !enable)2543return err;25442545return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_CONNECTED),2546&req, sizeof(req), false);2547}25482549int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,2550struct ieee80211_channel *chan, int duration)2551{2552struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;2553struct mt7615_dev *dev = phy->dev;2554struct mt7615_roc_tlv req = {2555.bss_idx = mvif->mt76.idx,2556.active = !chan,2557.max_interval = cpu_to_le32(duration),2558.primary_chan = chan ? chan->hw_value : 0,2559.band = chan ? chan->band : 0,2560.req_type = 2,2561};25622563phy->roc_grant = false;25642565return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_ROC),2566&req, sizeof(req), false);2567}256825692570