Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7615/mcu.c
108325 views
// SPDX-License-Identifier: BSD-3-Clause-Clear1/* 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)) {881dev_kfree_skb(sskb);882return PTR_ERR(wtbl_hdr);883}884885if (enable) {886mt76_connac_mcu_wtbl_generic_tlv(&dev->mt76, wskb, vif, sta,887NULL, wtbl_hdr);888if (sta)889mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta,890NULL, wtbl_hdr, true, true);891mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, &msta->wcid,892NULL, wtbl_hdr);893}894895cmd = enable ? MCU_EXT_CMD(WTBL_UPDATE) : MCU_EXT_CMD(STA_REC_UPDATE);896skb = enable ? wskb : sskb;897898err = mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);899if (err < 0) {900skb = enable ? sskb : wskb;901dev_kfree_skb(skb);902903return err;904}905906cmd = enable ? MCU_EXT_CMD(STA_REC_UPDATE) : MCU_EXT_CMD(WTBL_UPDATE);907skb = enable ? sskb : wskb;908909return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);910}911912static int913mt7615_mcu_wtbl_update_hdr_trans(struct mt7615_dev *dev,914struct ieee80211_vif *vif,915struct ieee80211_sta *sta)916{917return mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);918}919920static const struct mt7615_mcu_ops wtbl_update_ops = {921.add_beacon_offload = mt7615_mcu_add_beacon_offload,922.set_pm_state = mt7615_mcu_ctrl_pm_state,923.add_dev_info = mt7615_mcu_add_dev,924.add_bss_info = mt7615_mcu_add_bss,925.add_tx_ba = mt7615_mcu_wtbl_tx_ba,926.add_rx_ba = mt7615_mcu_wtbl_rx_ba,927.sta_add = mt7615_mcu_wtbl_sta_add,928.set_drv_ctrl = mt7615_mcu_drv_pmctrl,929.set_fw_ctrl = mt7615_mcu_fw_pmctrl,930.set_sta_decap_offload = mt7615_mcu_wtbl_update_hdr_trans,931};932933static int934mt7615_mcu_sta_ba(struct mt7615_dev *dev,935struct ieee80211_ampdu_params *params,936bool enable, bool tx)937{938struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;939struct mt7615_vif *mvif = msta->vif;940struct wtbl_req_hdr *wtbl_hdr;941struct tlv *sta_wtbl;942struct sk_buff *skb;943944skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,945&msta->wcid);946if (IS_ERR(skb))947return PTR_ERR(skb);948949mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx);950951sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv));952953wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,954WTBL_SET, sta_wtbl, &skb);955if (IS_ERR(wtbl_hdr))956return PTR_ERR(wtbl_hdr);957958mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, tx,959sta_wtbl, wtbl_hdr);960961return mt76_mcu_skb_send_msg(&dev->mt76, skb,962MCU_EXT_CMD(STA_REC_UPDATE), true);963}964965static int966mt7615_mcu_sta_tx_ba(struct mt7615_dev *dev,967struct ieee80211_ampdu_params *params,968bool enable)969{970return mt7615_mcu_sta_ba(dev, params, enable, true);971}972973static int974mt7615_mcu_sta_rx_ba(struct mt7615_dev *dev,975struct ieee80211_ampdu_params *params,976bool enable)977{978return mt7615_mcu_sta_ba(dev, params, enable, false);979}980981static int982__mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif,983struct ieee80211_sta *sta, bool enable, int cmd,984bool offload_fw)985{986struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;987struct mt76_sta_cmd_info info = {988.sta = sta,989.vif = vif,990.offload_fw = offload_fw,991.enable = enable,992.newly = true,993.cmd = cmd,994};995996info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;997return mt76_connac_mcu_sta_cmd(phy, &info);998}9991000static int1001mt7615_mcu_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif,1002struct ieee80211_sta *sta, bool enable)1003{1004return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable,1005MCU_EXT_CMD(STA_REC_UPDATE), false);1006}10071008static int1009mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,1010struct ieee80211_vif *vif,1011struct ieee80211_sta *sta)1012{1013struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;10141015return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,1016vif, &msta->wcid,1017MCU_EXT_CMD(STA_REC_UPDATE));1018}10191020static const struct mt7615_mcu_ops sta_update_ops = {1021.add_beacon_offload = mt7615_mcu_add_beacon_offload,1022.set_pm_state = mt7615_mcu_ctrl_pm_state,1023.add_dev_info = mt7615_mcu_add_dev,1024.add_bss_info = mt7615_mcu_add_bss,1025.add_tx_ba = mt7615_mcu_sta_tx_ba,1026.add_rx_ba = mt7615_mcu_sta_rx_ba,1027.sta_add = mt7615_mcu_add_sta,1028.set_drv_ctrl = mt7615_mcu_drv_pmctrl,1029.set_fw_ctrl = mt7615_mcu_fw_pmctrl,1030.set_sta_decap_offload = mt7615_mcu_sta_update_hdr_trans,1031};10321033static int1034mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)1035{1036return 0;1037}10381039static int1040mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,1041struct ieee80211_hw *hw,1042struct ieee80211_vif *vif,1043bool enable)1044{1045struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;1046struct mt76_wcid *wcid = &dev->mt76.global_wcid;1047struct ieee80211_mutable_offsets offs;1048struct {1049struct req_hdr {1050u8 bss_idx;1051u8 pad[3];1052} __packed hdr;1053struct bcn_content_tlv {1054__le16 tag;1055__le16 len;1056__le16 tim_ie_pos;1057__le16 csa_ie_pos;1058__le16 bcc_ie_pos;1059/* 0: disable beacon offload1060* 1: enable beacon offload1061* 2: update probe respond offload1062*/1063u8 enable;1064/* 0: legacy format (TXD + payload)1065* 1: only cap field IE1066*/1067u8 type;1068__le16 pkt_len;1069u8 pkt[512];1070} __packed beacon_tlv;1071} req = {1072.hdr = {1073.bss_idx = mvif->mt76.idx,1074},1075.beacon_tlv = {1076.tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT),1077.len = cpu_to_le16(sizeof(struct bcn_content_tlv)),1078.enable = enable,1079},1080};1081struct sk_buff *skb;10821083if (!enable)1084goto out;10851086skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0);1087if (!skb)1088return -EINVAL;10891090if (skb->len > 512 - MT_TXD_SIZE) {1091dev_err(dev->mt76.dev, "beacon size limit exceed\n");1092dev_kfree_skb(skb);1093return -EINVAL;1094}10951096mt7615_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb,1097wcid, NULL, 0, NULL, 0, true);1098memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);1099req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);1100req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);11011102if (offs.cntdwn_counter_offs[0]) {1103u16 csa_offs;11041105csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;1106req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs);1107}1108dev_kfree_skb(skb);11091110out:1111return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),1112&req, sizeof(req), true);1113}11141115static int1116mt7615_mcu_uni_add_dev(struct mt7615_phy *phy, struct ieee80211_vif *vif,1117bool enable)1118{1119struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;11201121return mt76_connac_mcu_uni_add_dev(phy->mt76, &vif->bss_conf, &mvif->mt76,1122&mvif->sta.wcid, enable);1123}11241125static int1126mt7615_mcu_uni_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,1127struct ieee80211_sta *sta, bool enable)1128{1129struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;11301131return mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,1132enable, NULL);1133}11341135static inline int1136mt7615_mcu_uni_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif,1137struct ieee80211_sta *sta, bool enable)1138{1139return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable,1140MCU_UNI_CMD(STA_REC_UPDATE), true);1141}11421143static int1144mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev,1145struct ieee80211_ampdu_params *params,1146bool enable)1147{1148struct mt7615_sta *sta = (struct mt7615_sta *)params->sta->drv_priv;11491150return mt76_connac_mcu_sta_ba(&dev->mt76, &sta->vif->mt76, params,1151MCU_UNI_CMD(STA_REC_UPDATE), enable,1152true);1153}11541155static int1156mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev,1157struct ieee80211_ampdu_params *params,1158bool enable)1159{1160struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;1161struct mt7615_vif *mvif = msta->vif;1162struct wtbl_req_hdr *wtbl_hdr;1163struct tlv *sta_wtbl;1164struct sk_buff *skb;1165int err;11661167skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,1168&msta->wcid);1169if (IS_ERR(skb))1170return PTR_ERR(skb);11711172mt76_connac_mcu_sta_ba_tlv(skb, params, enable, false);11731174err = mt76_mcu_skb_send_msg(&dev->mt76, skb,1175MCU_UNI_CMD(STA_REC_UPDATE), true);1176if (err < 0 || !enable)1177return err;11781179skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,1180&msta->wcid);1181if (IS_ERR(skb))1182return PTR_ERR(skb);11831184sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,1185sizeof(struct tlv));11861187wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,1188WTBL_SET, sta_wtbl, &skb);1189if (IS_ERR(wtbl_hdr))1190return PTR_ERR(wtbl_hdr);11911192mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, false,1193sta_wtbl, wtbl_hdr);11941195return mt76_mcu_skb_send_msg(&dev->mt76, skb,1196MCU_UNI_CMD(STA_REC_UPDATE), true);1197}11981199static int1200mt7615_mcu_sta_uni_update_hdr_trans(struct mt7615_dev *dev,1201struct ieee80211_vif *vif,1202struct ieee80211_sta *sta)1203{1204struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;12051206return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,1207vif, &msta->wcid,1208MCU_UNI_CMD(STA_REC_UPDATE));1209}12101211static const struct mt7615_mcu_ops uni_update_ops = {1212.add_beacon_offload = mt7615_mcu_uni_add_beacon_offload,1213.set_pm_state = mt7615_mcu_uni_ctrl_pm_state,1214.add_dev_info = mt7615_mcu_uni_add_dev,1215.add_bss_info = mt7615_mcu_uni_add_bss,1216.add_tx_ba = mt7615_mcu_uni_tx_ba,1217.add_rx_ba = mt7615_mcu_uni_rx_ba,1218.sta_add = mt7615_mcu_uni_add_sta,1219.set_drv_ctrl = mt7615_mcu_lp_drv_pmctrl,1220.set_fw_ctrl = mt7615_mcu_fw_pmctrl,1221.set_sta_decap_offload = mt7615_mcu_sta_uni_update_hdr_trans,1222};12231224int mt7615_mcu_restart(struct mt76_dev *dev)1225{1226return mt76_mcu_send_msg(dev, MCU_CMD(RESTART_DL_REQ), NULL, 0, true);1227}1228EXPORT_SYMBOL_GPL(mt7615_mcu_restart);12291230static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name)1231{1232const struct mt7615_patch_hdr *hdr;1233const struct firmware *fw = NULL;1234int len, ret, sem;12351236ret = firmware_request_nowarn(&fw, name, dev->mt76.dev);1237if (ret)1238return ret;12391240if (!fw || !fw->data || fw->size < sizeof(*hdr)) {1241dev_err(dev->mt76.dev, "Invalid firmware\n");1242ret = -EINVAL;1243goto release_fw;1244}12451246sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, true);1247switch (sem) {1248case PATCH_IS_DL:1249goto release_fw;1250case PATCH_NOT_DL_SEM_SUCCESS:1251break;1252default:1253dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");1254ret = -EAGAIN;1255goto release_fw;1256}12571258hdr = (const struct mt7615_patch_hdr *)(fw->data);12591260dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",1261be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);12621263len = fw->size - sizeof(*hdr);12641265ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,1266DL_MODE_NEED_RSP);1267if (ret) {1268dev_err(dev->mt76.dev, "Download request failed\n");1269goto out;1270}12711272ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),1273fw->data + sizeof(*hdr), len);1274if (ret) {1275dev_err(dev->mt76.dev, "Failed to send firmware to device\n");1276goto out;1277}12781279ret = mt76_connac_mcu_start_patch(&dev->mt76);1280if (ret)1281dev_err(dev->mt76.dev, "Failed to start patch\n");12821283out:1284sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);1285switch (sem) {1286case PATCH_REL_SEM_SUCCESS:1287break;1288default:1289ret = -EAGAIN;1290dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");1291break;1292}12931294release_fw:1295release_firmware(fw);12961297return ret;1298}12991300static int1301mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev,1302const struct mt7615_fw_trailer *hdr,1303const u8 *data, bool is_cr4)1304{1305int n_region = is_cr4 ? CR4_REGION_NUM : N9_REGION_NUM;1306int err, i, offset = 0;1307u32 len, addr, mode;13081309for (i = 0; i < n_region; i++) {1310mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,1311hdr[i].feature_set, is_cr4);1312len = le32_to_cpu(hdr[i].len) + IMG_CRC_LEN;1313addr = le32_to_cpu(hdr[i].addr);13141315err = mt76_connac_mcu_init_download(&dev->mt76, addr, len,1316mode);1317if (err) {1318dev_err(dev->mt76.dev, "Download request failed\n");1319return err;1320}13211322err = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),1323data + offset, len);1324if (err) {1325dev_err(dev->mt76.dev, "Failed to send firmware to device\n");1326return err;1327}13281329offset += len;1330}13311332return 0;1333}13341335static int mt7615_load_n9(struct mt7615_dev *dev, const char *name)1336{1337const struct mt7615_fw_trailer *hdr;1338const struct firmware *fw;1339int ret;13401341ret = request_firmware(&fw, name, dev->mt76.dev);1342if (ret)1343return ret;13441345if (!fw || !fw->data || fw->size < N9_REGION_NUM * sizeof(*hdr)) {1346dev_err(dev->mt76.dev, "Invalid firmware\n");1347ret = -EINVAL;1348goto out;1349}13501351hdr = (const struct mt7615_fw_trailer *)(fw->data + fw->size -1352N9_REGION_NUM * sizeof(*hdr));13531354dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",1355hdr->fw_ver, hdr->build_date);13561357ret = mt7615_mcu_send_ram_firmware(dev, hdr, fw->data, false);1358if (ret)1359goto out;13601361ret = mt76_connac_mcu_start_firmware(&dev->mt76,1362le32_to_cpu(hdr->addr),1363FW_START_OVERRIDE);1364if (ret) {1365dev_err(dev->mt76.dev, "Failed to start N9 firmware\n");1366goto out;1367}13681369snprintf(dev->mt76.hw->wiphy->fw_version,1370sizeof(dev->mt76.hw->wiphy->fw_version),1371"%.10s-%.15s", hdr->fw_ver, hdr->build_date);13721373if (!is_mt7615(&dev->mt76)) {1374dev->fw_ver = MT7615_FIRMWARE_V2;1375dev->mcu_ops = &sta_update_ops;1376} else {1377dev->fw_ver = MT7615_FIRMWARE_V1;1378dev->mcu_ops = &wtbl_update_ops;1379}13801381out:1382release_firmware(fw);1383return ret;1384}13851386static int mt7615_load_cr4(struct mt7615_dev *dev, const char *name)1387{1388const struct mt7615_fw_trailer *hdr;1389const struct firmware *fw;1390int ret;13911392ret = request_firmware(&fw, name, dev->mt76.dev);1393if (ret)1394return ret;13951396if (!fw || !fw->data || fw->size < CR4_REGION_NUM * sizeof(*hdr)) {1397dev_err(dev->mt76.dev, "Invalid firmware\n");1398ret = -EINVAL;1399goto out;1400}14011402hdr = (const struct mt7615_fw_trailer *)(fw->data + fw->size -1403CR4_REGION_NUM * sizeof(*hdr));14041405dev_info(dev->mt76.dev, "CR4 Firmware Version: %.10s, Build Time: %.15s\n",1406hdr->fw_ver, hdr->build_date);14071408ret = mt7615_mcu_send_ram_firmware(dev, hdr, fw->data, true);1409if (ret)1410goto out;14111412ret = mt76_connac_mcu_start_firmware(&dev->mt76, 0,1413FW_START_WORKING_PDA_CR4);1414if (ret) {1415dev_err(dev->mt76.dev, "Failed to start CR4 firmware\n");1416goto out;1417}14181419out:1420release_firmware(fw);14211422return ret;1423}14241425static int mt7615_load_ram(struct mt7615_dev *dev)1426{1427int ret;14281429ret = mt7615_load_n9(dev, MT7615_FIRMWARE_N9);1430if (ret)1431return ret;14321433return mt7615_load_cr4(dev, MT7615_FIRMWARE_CR4);1434}14351436static int mt7615_load_firmware(struct mt7615_dev *dev)1437{1438int ret;1439u32 val;14401441val = mt76_get_field(dev, MT_TOP_MISC2, MT_TOP_MISC2_FW_STATE);14421443if (val != FW_STATE_FW_DOWNLOAD) {1444dev_err(dev->mt76.dev, "Firmware is not ready for download\n");1445return -EIO;1446}14471448ret = mt7615_load_patch(dev, MT7615_PATCH_ADDRESS, MT7615_ROM_PATCH);1449if (ret)1450return ret;14511452ret = mt7615_load_ram(dev);1453if (ret)1454return ret;14551456if (!mt76_poll_msec(dev, MT_TOP_MISC2, MT_TOP_MISC2_FW_STATE,1457FIELD_PREP(MT_TOP_MISC2_FW_STATE,1458FW_STATE_RDY), 500)) {1459dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");1460return -EIO;1461}14621463return 0;1464}14651466static int mt7622_load_firmware(struct mt7615_dev *dev)1467{1468int ret;1469u32 val;14701471mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);14721473val = mt76_get_field(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE);1474if (val != FW_STATE_FW_DOWNLOAD) {1475dev_err(dev->mt76.dev, "Firmware is not ready for download\n");1476return -EIO;1477}14781479ret = mt7615_load_patch(dev, MT7622_PATCH_ADDRESS, MT7622_ROM_PATCH);1480if (ret)1481return ret;14821483ret = mt7615_load_n9(dev, MT7622_FIRMWARE_N9);1484if (ret)1485return ret;14861487if (!mt76_poll_msec(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE,1488FIELD_PREP(MT_TOP_OFF_RSV_FW_STATE,1489FW_STATE_NORMAL_TRX), 1500)) {1490dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");1491return -EIO;1492}14931494mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);14951496return 0;1497}14981499int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl)1500{1501struct {1502u8 ctrl_val;1503u8 pad[3];1504} data = {1505.ctrl_val = ctrl1506};15071508return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(FW_LOG_2_HOST),1509&data, sizeof(data), true);1510}15111512static int mt7615_mcu_cal_cache_apply(struct mt7615_dev *dev)1513{1514struct {1515bool cache_enable;1516u8 pad[3];1517} data = {1518.cache_enable = true1519};15201521return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(CAL_CACHE), &data,1522sizeof(data), false);1523}15241525static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)1526{1527u32 offset = 0, override_addr = 0, flag = FW_START_DLYCAL;1528const struct mt76_connac2_fw_trailer *hdr;1529const struct mt7663_fw_buf *buf;1530const struct firmware *fw;1531const u8 *base_addr;1532int i, ret;15331534ret = request_firmware(&fw, name, dev->mt76.dev);1535if (ret)1536return ret;15371538if (!fw || !fw->data || fw->size < FW_V3_COMMON_TAILER_SIZE) {1539dev_err(dev->mt76.dev, "Invalid firmware\n");1540ret = -EINVAL;1541goto out;1542}15431544hdr = (const void *)(fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE);1545dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",1546hdr->fw_ver, hdr->build_date);1547dev_info(dev->mt76.dev, "Region number: 0x%x\n", hdr->n_region);15481549base_addr = fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE;1550for (i = 0; i < hdr->n_region; i++) {1551u32 shift = (hdr->n_region - i) * FW_V3_REGION_TAILER_SIZE;1552u32 len, addr, mode;15531554dev_info(dev->mt76.dev, "Parsing tailer Region: %d\n", i);15551556buf = (const struct mt7663_fw_buf *)(base_addr - shift);1557mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,1558buf->feature_set, false);1559addr = le32_to_cpu(buf->img_dest_addr);1560len = le32_to_cpu(buf->img_size);15611562ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,1563mode);1564if (ret) {1565dev_err(dev->mt76.dev, "Download request failed\n");1566goto out;1567}15681569ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),1570fw->data + offset, len);1571if (ret) {1572dev_err(dev->mt76.dev, "Failed to send firmware\n");1573goto out;1574}15751576offset += le32_to_cpu(buf->img_size);1577if (buf->feature_set & DL_MODE_VALID_RAM_ENTRY) {1578override_addr = le32_to_cpu(buf->img_dest_addr);1579dev_info(dev->mt76.dev, "Region %d, override_addr = 0x%08x\n",1580i, override_addr);1581}1582}15831584if (override_addr)1585flag |= FW_START_OVERRIDE;15861587dev_info(dev->mt76.dev, "override_addr = 0x%08x, option = %d\n",1588override_addr, flag);15891590ret = mt76_connac_mcu_start_firmware(&dev->mt76, override_addr, flag);1591if (ret) {1592dev_err(dev->mt76.dev, "Failed to start N9 firmware\n");1593goto out;1594}15951596snprintf(dev->mt76.hw->wiphy->fw_version,1597sizeof(dev->mt76.hw->wiphy->fw_version),1598"%.10s-%.15s", hdr->fw_ver, hdr->build_date);15991600out:1601release_firmware(fw);16021603return ret;1604}16051606static int1607mt7663_load_rom_patch(struct mt7615_dev *dev, const char **n9_firmware)1608{1609const char *selected_rom, *secondary_rom = MT7663_ROM_PATCH;1610const char *primary_rom = MT7663_OFFLOAD_ROM_PATCH;1611int ret;16121613if (!prefer_offload_fw) {1614secondary_rom = MT7663_OFFLOAD_ROM_PATCH;1615primary_rom = MT7663_ROM_PATCH;1616}1617selected_rom = primary_rom;16181619ret = mt7615_load_patch(dev, MT7663_PATCH_ADDRESS, primary_rom);1620if (ret) {1621dev_info(dev->mt76.dev, "%s not found, switching to %s",1622primary_rom, secondary_rom);1623ret = mt7615_load_patch(dev, MT7663_PATCH_ADDRESS,1624secondary_rom);1625if (ret) {1626dev_err(dev->mt76.dev, "failed to load %s",1627secondary_rom);1628return ret;1629}1630selected_rom = secondary_rom;1631}16321633if (!strcmp(selected_rom, MT7663_OFFLOAD_ROM_PATCH)) {1634*n9_firmware = MT7663_OFFLOAD_FIRMWARE_N9;1635dev->fw_ver = MT7615_FIRMWARE_V3;1636dev->mcu_ops = &uni_update_ops;1637} else {1638*n9_firmware = MT7663_FIRMWARE_N9;1639dev->fw_ver = MT7615_FIRMWARE_V2;1640dev->mcu_ops = &sta_update_ops;1641}16421643return 0;1644}16451646int __mt7663_load_firmware(struct mt7615_dev *dev)1647{1648const char *n9_firmware;1649int ret;16501651ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);1652if (ret) {1653dev_dbg(dev->mt76.dev, "Firmware is already download\n");1654return -EIO;1655}16561657ret = mt7663_load_rom_patch(dev, &n9_firmware);1658if (ret)1659return ret;16601661ret = mt7663_load_n9(dev, n9_firmware);1662if (ret)1663return ret;16641665if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY,1666MT_TOP_MISC2_FW_N9_RDY, 1500)) {1667ret = mt76_get_field(dev, MT_CONN_ON_MISC,1668MT7663_TOP_MISC2_FW_STATE);1669dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");1670return -EIO;1671}16721673#ifdef CONFIG_PM1674if (mt7615_firmware_offload(dev))1675dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;1676#endif /* CONFIG_PM */16771678dev_dbg(dev->mt76.dev, "Firmware init done\n");16791680return 0;1681}1682EXPORT_SYMBOL_GPL(__mt7663_load_firmware);16831684static int mt7663_load_firmware(struct mt7615_dev *dev)1685{1686int ret;16871688mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);16891690ret = __mt7663_load_firmware(dev);1691if (ret)1692return ret;16931694mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);16951696return 0;1697}16981699int mt7615_mcu_init(struct mt7615_dev *dev)1700{1701static const struct mt76_mcu_ops mt7615_mcu_ops = {1702.headroom = sizeof(struct mt7615_mcu_txd),1703.mcu_skb_send_msg = mt7615_mcu_send_message,1704.mcu_parse_response = mt7615_mcu_parse_response,1705};1706int ret;17071708dev->mt76.mcu_ops = &mt7615_mcu_ops;17091710ret = mt7615_mcu_drv_pmctrl(dev);1711if (ret)1712return ret;17131714switch (mt76_chip(&dev->mt76)) {1715case 0x7622:1716ret = mt7622_load_firmware(dev);1717break;1718case 0x7663:1719ret = mt7663_load_firmware(dev);1720break;1721default:1722ret = mt7615_load_firmware(dev);1723break;1724}1725if (ret)1726return ret;17271728mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);1729dev_dbg(dev->mt76.dev, "Firmware init done\n");1730set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);17311732if (dev->dbdc_support) {1733ret = mt7615_mcu_cal_cache_apply(dev);1734if (ret)1735return ret;1736}17371738return mt7615_mcu_fw_log_2_host(dev, 0);1739}1740EXPORT_SYMBOL_GPL(mt7615_mcu_init);17411742void mt7615_mcu_exit(struct mt7615_dev *dev)1743{1744mt7615_mcu_restart(&dev->mt76);1745mt7615_mcu_set_fw_ctrl(dev);1746skb_queue_purge(&dev->mt76.mcu.res_q);1747}1748EXPORT_SYMBOL_GPL(mt7615_mcu_exit);17491750int mt7615_mcu_set_eeprom(struct mt7615_dev *dev)1751{1752struct {1753u8 buffer_mode;1754u8 content_format;1755__le16 len;1756} __packed req_hdr = {1757.buffer_mode = 1,1758};1759u8 *eep = (u8 *)dev->mt76.eeprom.data;1760struct sk_buff *skb;1761int eep_len, offset;17621763switch (mt76_chip(&dev->mt76)) {1764case 0x7622:1765eep_len = MT7622_EE_MAX - MT_EE_NIC_CONF_0;1766offset = MT_EE_NIC_CONF_0;1767break;1768case 0x7663:1769eep_len = MT7663_EE_MAX - MT_EE_CHIP_ID;1770req_hdr.content_format = 1;1771offset = MT_EE_CHIP_ID;1772break;1773default:1774eep_len = MT7615_EE_MAX - MT_EE_NIC_CONF_0;1775offset = MT_EE_NIC_CONF_0;1776break;1777}17781779req_hdr.len = cpu_to_le16(eep_len);17801781skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) + eep_len);1782if (!skb)1783return -ENOMEM;17841785skb_put_data(skb, &req_hdr, sizeof(req_hdr));1786skb_put_data(skb, eep + offset, eep_len);17871788return mt76_mcu_skb_send_msg(&dev->mt76, skb,1789MCU_EXT_CMD(EFUSE_BUFFER_MODE), true);1790}17911792int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue,1793const struct ieee80211_tx_queue_params *params)1794{1795#define WMM_AIFS_SET BIT(0)1796#define WMM_CW_MIN_SET BIT(1)1797#define WMM_CW_MAX_SET BIT(2)1798#define WMM_TXOP_SET BIT(3)1799#define WMM_PARAM_SET (WMM_AIFS_SET | WMM_CW_MIN_SET | \1800WMM_CW_MAX_SET | WMM_TXOP_SET)1801struct req_data {1802u8 number;1803u8 rsv[3];1804u8 queue;1805u8 valid;1806u8 aifs;1807u8 cw_min;1808__le16 cw_max;1809__le16 txop;1810} __packed req = {1811.number = 1,1812.queue = queue,1813.valid = WMM_PARAM_SET,1814.aifs = params->aifs,1815.cw_min = 5,1816.cw_max = cpu_to_le16(10),1817.txop = cpu_to_le16(params->txop),1818};18191820if (params->cw_min)1821req.cw_min = fls(params->cw_min);1822if (params->cw_max)1823req.cw_max = cpu_to_le16(fls(params->cw_max));18241825return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EDCA_UPDATE),1826&req, sizeof(req), true);1827}18281829int mt7615_mcu_set_dbdc(struct mt7615_dev *dev)1830{1831struct mt7615_phy *ext_phy = mt7615_ext_phy(dev);1832struct dbdc_entry {1833u8 type;1834u8 index;1835u8 band;1836u8 _rsv;1837};1838struct {1839u8 enable;1840u8 num;1841u8 _rsv[2];1842struct dbdc_entry entry[64];1843} req = {1844.enable = !!ext_phy,1845};1846int i;18471848if (!ext_phy)1849goto out;18501851#define ADD_DBDC_ENTRY(_type, _idx, _band) \1852do { \1853req.entry[req.num].type = _type; \1854req.entry[req.num].index = _idx; \1855req.entry[req.num++].band = _band; \1856} while (0)18571858for (i = 0; i < 4; i++) {1859bool band = !!(ext_phy->omac_mask & BIT_ULL(i));18601861ADD_DBDC_ENTRY(DBDC_TYPE_BSS, i, band);1862}18631864for (i = 0; i < 14; i++) {1865bool band = !!(ext_phy->omac_mask & BIT_ULL(0x11 + i));18661867ADD_DBDC_ENTRY(DBDC_TYPE_MBSS, i, band);1868}18691870ADD_DBDC_ENTRY(DBDC_TYPE_MU, 0, 1);18711872for (i = 0; i < 3; i++)1873ADD_DBDC_ENTRY(DBDC_TYPE_BF, i, 1);18741875ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 0, 0);1876ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 1, 0);1877ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 2, 1);1878ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 3, 1);18791880ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 0, 0);1881ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 1, 1);18821883out:1884return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(DBDC_CTRL), &req,1885sizeof(req), true);1886}18871888int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val)1889{1890struct {1891__le16 tag;1892__le16 min_lpn;1893} req = {1894.tag = cpu_to_le16(0x1),1895.min_lpn = cpu_to_le16(val),1896};18971898return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH),1899&req, sizeof(req), true);1900}19011902int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,1903const struct mt7615_dfs_pulse *pulse)1904{1905struct {1906__le16 tag;1907__le32 max_width; /* us */1908__le32 max_pwr; /* dbm */1909__le32 min_pwr; /* dbm */1910__le32 min_stgr_pri; /* us */1911__le32 max_stgr_pri; /* us */1912__le32 min_cr_pri; /* us */1913__le32 max_cr_pri; /* us */1914} req = {1915.tag = cpu_to_le16(0x3),1916#define __req_field(field) .field = cpu_to_le32(pulse->field)1917__req_field(max_width),1918__req_field(max_pwr),1919__req_field(min_pwr),1920__req_field(min_stgr_pri),1921__req_field(max_stgr_pri),1922__req_field(min_cr_pri),1923__req_field(max_cr_pri),1924#undef __req_field1925};19261927return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH),1928&req, sizeof(req), true);1929}19301931int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index,1932const struct mt7615_dfs_pattern *pattern)1933{1934struct {1935__le16 tag;1936__le16 radar_type;1937u8 enb;1938u8 stgr;1939u8 min_crpn;1940u8 max_crpn;1941u8 min_crpr;1942u8 min_pw;1943u8 max_pw;1944__le32 min_pri;1945__le32 max_pri;1946u8 min_crbn;1947u8 max_crbn;1948u8 min_stgpn;1949u8 max_stgpn;1950u8 min_stgpr;1951} req = {1952.tag = cpu_to_le16(0x2),1953.radar_type = cpu_to_le16(index),1954#define __req_field_u8(field) .field = pattern->field1955#define __req_field_u32(field) .field = cpu_to_le32(pattern->field)1956__req_field_u8(enb),1957__req_field_u8(stgr),1958__req_field_u8(min_crpn),1959__req_field_u8(max_crpn),1960__req_field_u8(min_crpr),1961__req_field_u8(min_pw),1962__req_field_u8(max_pw),1963__req_field_u32(min_pri),1964__req_field_u32(max_pri),1965__req_field_u8(min_crbn),1966__req_field_u8(max_crbn),1967__req_field_u8(min_stgpn),1968__req_field_u8(max_stgpn),1969__req_field_u8(min_stgpr),1970#undef __req_field_u81971#undef __req_field_u321972};19731974return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH),1975&req, sizeof(req), true);1976}19771978int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev)1979{1980struct {1981u8 pulse_num;1982u8 rsv[3];1983struct {1984__le32 start_time;1985__le16 width;1986__le16 power;1987} pattern[32];1988} req = {1989.pulse_num = dev->radar_pattern.n_pulses,1990};1991u32 start_time = ktime_to_ms(ktime_get_boottime());1992int i;19931994if (dev->radar_pattern.n_pulses > ARRAY_SIZE(req.pattern))1995return -EINVAL;19961997/* TODO: add some noise here */1998for (i = 0; i < dev->radar_pattern.n_pulses; i++) {1999u32 ts = start_time + i * dev->radar_pattern.period;20002001req.pattern[i].width = cpu_to_le16(dev->radar_pattern.width);2002req.pattern[i].power = cpu_to_le16(dev->radar_pattern.power);2003req.pattern[i].start_time = cpu_to_le32(ts);2004}20052006return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_PATTERN),2007&req, sizeof(req), false);2008}20092010static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku)2011{2012struct mt76_phy *mphy = phy->mt76;2013struct ieee80211_hw *hw = mphy->hw;2014struct mt76_power_limits limits;2015s8 *limits_array = (s8 *)&limits;2016int n_chains = hweight8(mphy->antenna_mask);2017int tx_power = hw->conf.power_level * 2;2018int i;2019static const u8 sku_mapping[] = {2020#define SKU_FIELD(_type, _field) \2021[MT_SKU_##_type] = offsetof(struct mt76_power_limits, _field)2022SKU_FIELD(CCK_1_2, cck[0]),2023SKU_FIELD(CCK_55_11, cck[2]),2024SKU_FIELD(OFDM_6_9, ofdm[0]),2025SKU_FIELD(OFDM_12_18, ofdm[2]),2026SKU_FIELD(OFDM_24_36, ofdm[4]),2027SKU_FIELD(OFDM_48, ofdm[6]),2028SKU_FIELD(OFDM_54, ofdm[7]),2029SKU_FIELD(HT20_0_8, mcs[0][0]),2030SKU_FIELD(HT20_32, ofdm[0]),2031SKU_FIELD(HT20_1_2_9_10, mcs[0][1]),2032SKU_FIELD(HT20_3_4_11_12, mcs[0][3]),2033SKU_FIELD(HT20_5_13, mcs[0][5]),2034SKU_FIELD(HT20_6_14, mcs[0][6]),2035SKU_FIELD(HT20_7_15, mcs[0][7]),2036SKU_FIELD(HT40_0_8, mcs[1][0]),2037SKU_FIELD(HT40_32, ofdm[0]),2038SKU_FIELD(HT40_1_2_9_10, mcs[1][1]),2039SKU_FIELD(HT40_3_4_11_12, mcs[1][3]),2040SKU_FIELD(HT40_5_13, mcs[1][5]),2041SKU_FIELD(HT40_6_14, mcs[1][6]),2042SKU_FIELD(HT40_7_15, mcs[1][7]),2043SKU_FIELD(VHT20_0, mcs[0][0]),2044SKU_FIELD(VHT20_1_2, mcs[0][1]),2045SKU_FIELD(VHT20_3_4, mcs[0][3]),2046SKU_FIELD(VHT20_5_6, mcs[0][5]),2047SKU_FIELD(VHT20_7, mcs[0][7]),2048SKU_FIELD(VHT20_8, mcs[0][8]),2049SKU_FIELD(VHT20_9, mcs[0][9]),2050SKU_FIELD(VHT40_0, mcs[1][0]),2051SKU_FIELD(VHT40_1_2, mcs[1][1]),2052SKU_FIELD(VHT40_3_4, mcs[1][3]),2053SKU_FIELD(VHT40_5_6, mcs[1][5]),2054SKU_FIELD(VHT40_7, mcs[1][7]),2055SKU_FIELD(VHT40_8, mcs[1][8]),2056SKU_FIELD(VHT40_9, mcs[1][9]),2057SKU_FIELD(VHT80_0, mcs[2][0]),2058SKU_FIELD(VHT80_1_2, mcs[2][1]),2059SKU_FIELD(VHT80_3_4, mcs[2][3]),2060SKU_FIELD(VHT80_5_6, mcs[2][5]),2061SKU_FIELD(VHT80_7, mcs[2][7]),2062SKU_FIELD(VHT80_8, mcs[2][8]),2063SKU_FIELD(VHT80_9, mcs[2][9]),2064SKU_FIELD(VHT160_0, mcs[3][0]),2065SKU_FIELD(VHT160_1_2, mcs[3][1]),2066SKU_FIELD(VHT160_3_4, mcs[3][3]),2067SKU_FIELD(VHT160_5_6, mcs[3][5]),2068SKU_FIELD(VHT160_7, mcs[3][7]),2069SKU_FIELD(VHT160_8, mcs[3][8]),2070SKU_FIELD(VHT160_9, mcs[3][9]),2071#undef SKU_FIELD2072};20732074tx_power = mt76_get_sar_power(mphy, mphy->chandef.chan, tx_power);2075tx_power -= mt76_tx_power_path_delta(n_chains);2076tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,2077&limits, tx_power);2078mphy->txpower_cur = tx_power;20792080if (is_mt7663(mphy->dev)) {2081memset(sku, tx_power, MT_SKU_4SS_DELTA + 1);2082return;2083}20842085for (i = 0; i < MT_SKU_1SS_DELTA; i++)2086sku[i] = limits_array[sku_mapping[i]];20872088for (i = 0; i < 4; i++) {2089int delta = 0;20902091if (i < n_chains - 1)2092delta = mt76_tx_power_path_delta(n_chains) -2093mt76_tx_power_path_delta(i + 1);2094sku[MT_SKU_1SS_DELTA + i] = delta;2095}2096}20972098static u8 mt7615_mcu_chan_bw(struct cfg80211_chan_def *chandef)2099{2100static const u8 width_to_bw[] = {2101[NL80211_CHAN_WIDTH_40] = CMD_CBW_40MHZ,2102[NL80211_CHAN_WIDTH_80] = CMD_CBW_80MHZ,2103[NL80211_CHAN_WIDTH_80P80] = CMD_CBW_8080MHZ,2104[NL80211_CHAN_WIDTH_160] = CMD_CBW_160MHZ,2105[NL80211_CHAN_WIDTH_5] = CMD_CBW_5MHZ,2106[NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ,2107[NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ,2108[NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ,2109};21102111if (chandef->width >= ARRAY_SIZE(width_to_bw))2112return 0;21132114return width_to_bw[chandef->width];2115}21162117int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)2118{2119struct mt7615_dev *dev = phy->dev;2120struct cfg80211_chan_def *chandef = &phy->mt76->chandef;2121int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;2122struct {2123u8 control_chan;2124u8 center_chan;2125u8 bw;2126u8 tx_streams;2127u8 rx_streams_mask;2128u8 switch_reason;2129u8 band_idx;2130/* for 80+80 only */2131u8 center_chan2;2132__le16 cac_case;2133u8 channel_band;2134u8 rsv0;2135__le32 outband_freq;2136u8 txpower_drop;2137u8 rsv1[3];2138u8 txpower_sku[53];2139u8 rsv2[3];2140} req = {2141.control_chan = chandef->chan->hw_value,2142.center_chan = ieee80211_frequency_to_channel(freq1),2143.tx_streams = hweight8(phy->mt76->antenna_mask),2144.rx_streams_mask = phy->mt76->chainmask,2145.center_chan2 = ieee80211_frequency_to_channel(freq2),2146};21472148if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||2149phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)2150req.switch_reason = CH_SWITCH_NORMAL;2151else if (phy->mt76->offchannel)2152req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;2153else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,2154NL80211_IFTYPE_AP))2155req.switch_reason = CH_SWITCH_DFS;2156else2157req.switch_reason = CH_SWITCH_NORMAL;21582159req.band_idx = phy != &dev->phy;2160req.bw = mt7615_mcu_chan_bw(chandef);21612162if (mt76_testmode_enabled(phy->mt76))2163memset(req.txpower_sku, 0x3f, 49);2164else2165mt7615_mcu_set_txpower_sku(phy, req.txpower_sku);21662167return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);2168}21692170int mt7615_mcu_get_temperature(struct mt7615_dev *dev)2171{2172struct {2173u8 action;2174u8 rsv[3];2175} req = {};21762177return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL),2178&req, sizeof(req), true);2179}21802181int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode,2182u32 val)2183{2184struct {2185u8 test_mode_en;2186u8 param_idx;2187u8 _rsv[2];21882189__le32 value;21902191u8 pad[8];2192} req = {2193.test_mode_en = test_mode,2194.param_idx = param,2195.value = cpu_to_le32(val),2196};21972198return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL),2199&req, sizeof(req), false);2200}22012202int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable)2203{2204struct mt7615_dev *dev = phy->dev;2205struct {2206u8 format_id;2207u8 sku_enable;2208u8 band_idx;2209u8 rsv;2210} req = {2211.format_id = 0,2212.band_idx = phy != &dev->phy,2213.sku_enable = enable,2214};22152216return mt76_mcu_send_msg(&dev->mt76,2217MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),2218&req, sizeof(req), true);2219}22202221static int mt7615_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)2222{2223int i;22242225for (i = 0; i < n_freqs; i++)2226if (cur == freqs[i])2227return i;22282229return -1;2230}22312232static int mt7615_dcoc_freq_idx(u16 freq, u8 bw)2233{2234static const u16 freq_list[] = {22354980, 5805, 5905, 5190,22365230, 5270, 5310, 5350,22375390, 5430, 5470, 5510,22385550, 5590, 5630, 5670,22395710, 5755, 5795, 5835,22405875, 5210, 5290, 5370,22415450, 5530, 5610, 5690,22425775, 58552243};2244static const u16 freq_bw40[] = {22455190, 5230, 5270, 5310,22465350, 5390, 5430, 5470,22475510, 5550, 5590, 5630,22485670, 5710, 5755, 5795,22495835, 58752250};2251int offset_2g = ARRAY_SIZE(freq_list);2252int idx;22532254if (freq < 4000) {2255if (freq < 2427)2256return offset_2g;2257if (freq < 2442)2258return offset_2g + 1;2259if (freq < 2457)2260return offset_2g + 2;22612262return offset_2g + 3;2263}22642265switch (bw) {2266case NL80211_CHAN_WIDTH_80:2267case NL80211_CHAN_WIDTH_80P80:2268case NL80211_CHAN_WIDTH_160:2269break;2270default:2271idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),2272freq + 10);2273if (idx >= 0) {2274freq = freq_bw40[idx];2275break;2276}22772278idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),2279freq - 10);2280if (idx >= 0) {2281freq = freq_bw40[idx];2282break;2283}2284fallthrough;2285case NL80211_CHAN_WIDTH_40:2286idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),2287freq);2288if (idx >= 0)2289break;22902291return -1;22922293}22942295return mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), freq);2296}22972298int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy)2299{2300struct mt7615_dev *dev = phy->dev;2301struct cfg80211_chan_def *chandef = &phy->mt76->chandef;2302int freq2 = chandef->center_freq2;2303int ret;2304struct {2305u8 direction;2306u8 runtime_calibration;2307u8 _rsv[2];23082309__le16 center_freq;2310u8 bw;2311u8 band;2312u8 is_freq2;2313u8 success;2314u8 dbdc_en;23152316u8 _rsv2;23172318struct {2319__le32 sx0_i_lna[4];2320__le32 sx0_q_lna[4];23212322__le32 sx2_i_lna[4];2323__le32 sx2_q_lna[4];2324} dcoc_data[4];2325} req = {2326.direction = 1,23272328.bw = mt7615_mcu_chan_bw(chandef),2329.band = chandef->center_freq1 > 4000,2330.dbdc_en = !!dev->mt76.phys[MT_BAND1],2331};2332u16 center_freq = chandef->center_freq1;2333int freq_idx;2334u8 *eep = dev->mt76.eeprom.data;23352336if (!(eep[MT_EE_CALDATA_FLASH] & MT_EE_CALDATA_FLASH_RX_CAL))2337return 0;23382339if (chandef->width == NL80211_CHAN_WIDTH_160) {2340freq2 = center_freq + 40;2341center_freq -= 40;2342}23432344again:2345req.runtime_calibration = 1;2346freq_idx = mt7615_dcoc_freq_idx(center_freq, chandef->width);2347if (freq_idx < 0)2348goto out;23492350memcpy(req.dcoc_data, eep + MT7615_EEPROM_DCOC_OFFSET +2351freq_idx * MT7615_EEPROM_DCOC_SIZE,2352sizeof(req.dcoc_data));2353req.runtime_calibration = 0;23542355out:2356req.center_freq = cpu_to_le16(center_freq);2357ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RXDCOC_CAL), &req,2358sizeof(req), true);23592360if ((chandef->width == NL80211_CHAN_WIDTH_80P80 ||2361chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) {2362req.is_freq2 = true;2363center_freq = freq2;2364goto again;2365}23662367return ret;2368}23692370static int mt7615_dpd_freq_idx(u16 freq, u8 bw)2371{2372static const u16 freq_list[] = {23734920, 4940, 4960, 4980,23745040, 5060, 5080, 5180,23755200, 5220, 5240, 5260,23765280, 5300, 5320, 5340,23775360, 5380, 5400, 5420,23785440, 5460, 5480, 5500,23795520, 5540, 5560, 5580,23805600, 5620, 5640, 5660,23815680, 5700, 5720, 5745,23825765, 5785, 5805, 5825,23835845, 5865, 5885, 59052384};2385int offset_2g = ARRAY_SIZE(freq_list);2386int idx;23872388if (freq < 4000) {2389if (freq < 2432)2390return offset_2g;2391if (freq < 2457)2392return offset_2g + 1;23932394return offset_2g + 2;2395}23962397if (bw != NL80211_CHAN_WIDTH_20) {2398idx = mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),2399freq + 10);2400if (idx >= 0)2401return idx;24022403idx = mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),2404freq - 10);2405if (idx >= 0)2406return idx;2407}24082409return mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), freq);2410}241124122413int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy)2414{2415struct mt7615_dev *dev = phy->dev;2416struct cfg80211_chan_def *chandef = &phy->mt76->chandef;2417int freq2 = chandef->center_freq2;2418int ret;2419struct {2420u8 direction;2421u8 runtime_calibration;2422u8 _rsv[2];24232424__le16 center_freq;2425u8 bw;2426u8 band;2427u8 is_freq2;2428u8 success;2429u8 dbdc_en;24302431u8 _rsv2;24322433struct {2434struct {2435u32 dpd_g0;2436u8 data[32];2437} wf0, wf1;24382439struct {2440u32 dpd_g0_prim;2441u32 dpd_g0_sec;2442u8 data_prim[32];2443u8 data_sec[32];2444} wf2, wf3;2445} dpd_data;2446} req = {2447.direction = 1,24482449.bw = mt7615_mcu_chan_bw(chandef),2450.band = chandef->center_freq1 > 4000,2451.dbdc_en = !!dev->mt76.phys[MT_BAND1],2452};2453u16 center_freq = chandef->center_freq1;2454int freq_idx;2455u8 *eep = dev->mt76.eeprom.data;24562457if (!(eep[MT_EE_CALDATA_FLASH] & MT_EE_CALDATA_FLASH_TX_DPD))2458return 0;24592460if (chandef->width == NL80211_CHAN_WIDTH_160) {2461freq2 = center_freq + 40;2462center_freq -= 40;2463}24642465again:2466req.runtime_calibration = 1;2467freq_idx = mt7615_dpd_freq_idx(center_freq, chandef->width);2468if (freq_idx < 0)2469goto out;24702471memcpy(&req.dpd_data, eep + MT7615_EEPROM_TXDPD_OFFSET +2472freq_idx * MT7615_EEPROM_TXDPD_SIZE,2473sizeof(req.dpd_data));2474req.runtime_calibration = 0;24752476out:2477req.center_freq = cpu_to_le16(center_freq);2478ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXDPD_CAL),2479&req, sizeof(req), true);24802481if ((chandef->width == NL80211_CHAN_WIDTH_80P80 ||2482chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) {2483req.is_freq2 = true;2484center_freq = freq2;2485goto again;2486}24872488return ret;2489}24902491int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev)2492{2493struct {2494u8 operation;2495u8 count;2496u8 _rsv[2];2497u8 index;2498u8 enable;2499__le16 etype;2500} req = {2501.operation = 1,2502.count = 1,2503.enable = 1,2504.etype = cpu_to_le16(ETH_P_PAE),2505};25062507return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS),2508&req, sizeof(req), false);2509}25102511int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,2512bool enable)2513{2514struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;2515struct {2516u8 bss_idx;2517u8 dtim_period;2518__le16 aid;2519__le16 bcn_interval;2520__le16 atim_window;2521u8 uapsd;2522u8 bmc_delivered_ac;2523u8 bmc_triggered_ac;2524u8 pad;2525} req = {2526.bss_idx = mvif->mt76.idx,2527.aid = cpu_to_le16(vif->cfg.aid),2528.dtim_period = vif->bss_conf.dtim_period,2529.bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int),2530};2531struct {2532u8 bss_idx;2533u8 pad[3];2534} req_hdr = {2535.bss_idx = mvif->mt76.idx,2536};2537int err;25382539if (vif->type != NL80211_IFTYPE_STATION)2540return 0;25412542err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT),2543&req_hdr, sizeof(req_hdr), false);2544if (err < 0 || !enable)2545return err;25462547return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_CONNECTED),2548&req, sizeof(req), false);2549}25502551int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,2552struct ieee80211_channel *chan, int duration)2553{2554struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;2555struct mt7615_dev *dev = phy->dev;2556struct mt7615_roc_tlv req = {2557.bss_idx = mvif->mt76.idx,2558.active = !chan,2559.max_interval = cpu_to_le32(duration),2560.primary_chan = chan ? chan->hw_value : 0,2561.band = chan ? chan->band : 0,2562.req_type = 2,2563};25642565phy->roc_grant = false;25662567return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_ROC),2568&req, sizeof(req), false);2569}257025712572