Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7921/mcu.c
48524 views
// SPDX-License-Identifier: ISC1/* Copyright (C) 2020 MediaTek Inc. */23#include <linux/fs.h>4#include <linux/firmware.h>5#include "mt7921.h"6#include "mcu.h"7#include "../mt76_connac2_mac.h"8#include "../mt792x_trace.h"910#define MT_STA_BFER BIT(0)11#define MT_STA_BFEE BIT(1)1213static bool mt7921_disable_clc;14module_param_named(disable_clc, mt7921_disable_clc, bool, 0644);15MODULE_PARM_DESC(disable_clc, "disable CLC support");1617int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,18struct sk_buff *skb, int seq)19{20int mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);21struct mt76_connac2_mcu_rxd *rxd;22int ret = 0;2324if (!skb) {25dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",26cmd, seq);27mt792x_reset(mdev);2829return -ETIMEDOUT;30}3132rxd = (struct mt76_connac2_mcu_rxd *)skb->data;33if (seq != rxd->seq)34return -EAGAIN;3536if (cmd == MCU_CMD(PATCH_SEM_CONTROL) ||37cmd == MCU_CMD(PATCH_FINISH_REQ)) {38skb_pull(skb, sizeof(*rxd) - 4);39ret = *skb->data;40} else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {41skb_pull(skb, sizeof(*rxd) + 4);42ret = le32_to_cpu(*(__le32 *)skb->data);43} else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) ||44cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) ||45cmd == MCU_UNI_CMD(STA_REC_UPDATE) ||46cmd == MCU_UNI_CMD(HIF_CTRL) ||47cmd == MCU_UNI_CMD(OFFLOAD) ||48cmd == MCU_UNI_CMD(SUSPEND)) {49struct mt76_connac_mcu_uni_event *event;5051skb_pull(skb, sizeof(*rxd));52event = (struct mt76_connac_mcu_uni_event *)skb->data;53ret = le32_to_cpu(event->status);54/* skip invalid event */55if (mcu_cmd != event->cid)56ret = -EAGAIN;57} else if (cmd == MCU_CE_QUERY(REG_READ)) {58struct mt76_connac_mcu_reg_event *event;5960skb_pull(skb, sizeof(*rxd));61event = (struct mt76_connac_mcu_reg_event *)skb->data;62ret = (int)le32_to_cpu(event->val);63} else if (cmd == MCU_EXT_CMD(WF_RF_PIN_CTRL)) {64struct mt7921_wf_rf_pin_ctrl_event *event;6566skb_pull(skb, sizeof(*rxd));67event = (struct mt7921_wf_rf_pin_ctrl_event *)skb->data;68ret = (int)event->result;69} else {70skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));71}7273return ret;74}75EXPORT_SYMBOL_GPL(mt7921_mcu_parse_response);7677static int mt7921_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val)78{79struct mt7921_mcu_eeprom_info *res, req = {80.addr = cpu_to_le32(round_down(offset,81MT7921_EEPROM_BLOCK_SIZE)),82};83struct sk_buff *skb;84int ret;8586ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(EFUSE_ACCESS),87&req, sizeof(req), true, &skb);88if (ret)89return ret;9091res = (struct mt7921_mcu_eeprom_info *)skb->data;92*val = res->data[offset % MT7921_EEPROM_BLOCK_SIZE];93dev_kfree_skb(skb);9495return 0;96}9798#ifdef CONFIG_PM99100static int101mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev,102struct ieee80211_vif *vif, bool suspend)103{104struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;105struct {106struct {107u8 bss_idx;108u8 pad[3];109} __packed hdr;110struct mt76_connac_arpns_tlv arpns;111} req = {112.hdr = {113.bss_idx = mvif->bss_conf.mt76.idx,114},115.arpns = {116.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND),117.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)),118.mode = suspend,119},120};121122return mt76_mcu_send_msg(dev, MCU_UNI_CMD_OFFLOAD, &req, sizeof(req),123true);124}125126void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)127{128if (IS_ENABLED(CONFIG_IPV6)) {129struct mt76_phy *phy = priv;130131mt7921_mcu_set_ipv6_ns_filter(phy->dev, vif,132!test_bit(MT76_STATE_RUNNING,133&phy->state));134}135136mt76_connac_mcu_set_suspend_iter(priv, mac, vif);137}138139#endif /* CONFIG_PM */140141static void142mt7921_mcu_uni_roc_event(struct mt792x_dev *dev, struct sk_buff *skb)143{144struct mt7921_roc_grant_tlv *grant;145struct mt76_connac2_mcu_rxd *rxd;146int duration;147148rxd = (struct mt76_connac2_mcu_rxd *)skb->data;149grant = (struct mt7921_roc_grant_tlv *)(rxd->tlv + 4);150151/* should never happen */152WARN_ON_ONCE((le16_to_cpu(grant->tag) != UNI_EVENT_ROC_GRANT));153154if (grant->reqtype == MT7921_ROC_REQ_ROC)155ieee80211_ready_on_channel(dev->mt76.phy.hw);156157dev->phy.roc_grant = true;158wake_up(&dev->phy.roc_wait);159duration = le32_to_cpu(grant->max_interval);160mod_timer(&dev->phy.roc_timer,161jiffies + msecs_to_jiffies(duration));162}163164static void165mt7921_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb)166{167struct mt76_phy *mphy = &dev->mt76.phy;168struct mt792x_phy *phy = mphy->priv;169170spin_lock_bh(&dev->mt76.lock);171__skb_queue_tail(&phy->scan_event_list, skb);172spin_unlock_bh(&dev->mt76.lock);173174ieee80211_queue_delayed_work(mphy->hw, &phy->scan_work,175MT792x_HW_SCAN_TIMEOUT);176}177178static void179mt7921_mcu_connection_loss_iter(void *priv, u8 *mac,180struct ieee80211_vif *vif)181{182struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;183struct mt76_connac_beacon_loss_event *event = priv;184185if (mvif->idx != event->bss_idx)186return;187188if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER) ||189vif->type != NL80211_IFTYPE_STATION)190return;191192ieee80211_connection_loss(vif);193}194195static void196mt7921_mcu_connection_loss_event(struct mt792x_dev *dev, struct sk_buff *skb)197{198struct mt76_connac_beacon_loss_event *event;199struct mt76_phy *mphy = &dev->mt76.phy;200201skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));202event = (struct mt76_connac_beacon_loss_event *)skb->data;203204ieee80211_iterate_active_interfaces_atomic(mphy->hw,205IEEE80211_IFACE_ITER_RESUME_ALL,206mt7921_mcu_connection_loss_iter, event);207}208209static void210mt7921_mcu_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb)211{212struct mt7921_debug_msg {213__le16 id;214u8 type;215u8 flag;216__le32 value;217__le16 len;218u8 content[512];219} __packed * msg;220221skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));222msg = (struct mt7921_debug_msg *)skb->data;223224if (msg->type == 3) { /* fw log */225u16 len = min_t(u16, le16_to_cpu(msg->len), 512);226int i;227228for (i = 0 ; i < len; i++) {229if (!msg->content[i])230msg->content[i] = ' ';231}232wiphy_info(mt76_hw(dev)->wiphy, "%.*s", len, msg->content);233}234}235236static void237mt7921_mcu_low_power_event(struct mt792x_dev *dev, struct sk_buff *skb)238{239struct mt7921_mcu_lp_event {240u8 state;241u8 reserved[3];242} __packed * event;243244skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));245event = (struct mt7921_mcu_lp_event *)skb->data;246247trace_lp_event(dev, event->state);248}249250static void251mt7921_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb)252{253struct mt7921_mcu_tx_done_event *event;254255skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));256event = (struct mt7921_mcu_tx_done_event *)skb->data;257258mt7921_mac_add_txs(dev, event->txs);259}260261static void262mt7921_mcu_rssi_monitor_iter(void *priv, u8 *mac,263struct ieee80211_vif *vif)264{265struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;266struct mt76_connac_rssi_notify_event *event = priv;267enum nl80211_cqm_rssi_threshold_event nl_event;268s32 rssi = le32_to_cpu(event->rssi[mvif->bss_conf.mt76.idx]);269270if (!rssi)271return;272273if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))274return;275276if (rssi > vif->bss_conf.cqm_rssi_thold)277nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;278else279nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;280281ieee80211_cqm_rssi_notify(vif, nl_event, rssi, GFP_KERNEL);282}283284static void285mt7921_mcu_rssi_monitor_event(struct mt792x_dev *dev, struct sk_buff *skb)286{287struct mt76_connac_rssi_notify_event *event;288289skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));290event = (struct mt76_connac_rssi_notify_event *)skb->data;291292ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),293IEEE80211_IFACE_ITER_RESUME_ALL,294mt7921_mcu_rssi_monitor_iter, event);295}296297static void298mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb)299{300struct mt76_connac2_mcu_rxd *rxd;301302rxd = (struct mt76_connac2_mcu_rxd *)skb->data;303switch (rxd->eid) {304case MCU_EVENT_BSS_BEACON_LOSS:305mt7921_mcu_connection_loss_event(dev, skb);306break;307case MCU_EVENT_SCHED_SCAN_DONE:308case MCU_EVENT_SCAN_DONE:309mt7921_mcu_scan_event(dev, skb);310return;311case MCU_EVENT_DBG_MSG:312mt7921_mcu_debug_msg_event(dev, skb);313break;314case MCU_EVENT_COREDUMP:315dev->fw_assert = true;316mt76_connac_mcu_coredump_event(&dev->mt76, skb,317&dev->coredump);318return;319case MCU_EVENT_LP_INFO:320mt7921_mcu_low_power_event(dev, skb);321break;322case MCU_EVENT_TX_DONE:323mt7921_mcu_tx_done_event(dev, skb);324break;325case MCU_EVENT_RSSI_NOTIFY:326mt7921_mcu_rssi_monitor_event(dev, skb);327break;328default:329break;330}331dev_kfree_skb(skb);332}333334static void335mt7921_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev,336struct sk_buff *skb)337{338struct mt76_connac2_mcu_rxd *rxd;339340rxd = (struct mt76_connac2_mcu_rxd *)skb->data;341342switch (rxd->eid) {343case MCU_UNI_EVENT_ROC:344mt7921_mcu_uni_roc_event(dev, skb);345break;346default:347break;348}349dev_kfree_skb(skb);350}351352void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)353{354struct mt76_connac2_mcu_rxd *rxd;355356if (skb_linearize(skb))357return;358359rxd = (struct mt76_connac2_mcu_rxd *)skb->data;360361if (rxd->option & MCU_UNI_CMD_UNSOLICITED_EVENT) {362mt7921_mcu_uni_rx_unsolicited_event(dev, skb);363return;364}365366if (rxd->eid == 0x6) {367mt76_mcu_rx_event(&dev->mt76, skb);368return;369}370371if (rxd->ext_eid == MCU_EXT_EVENT_RATE_REPORT ||372rxd->eid == MCU_EVENT_BSS_BEACON_LOSS ||373rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||374rxd->eid == MCU_EVENT_RSSI_NOTIFY ||375rxd->eid == MCU_EVENT_SCAN_DONE ||376rxd->eid == MCU_EVENT_TX_DONE ||377rxd->eid == MCU_EVENT_DBG_MSG ||378rxd->eid == MCU_EVENT_COREDUMP ||379rxd->eid == MCU_EVENT_LP_INFO ||380!rxd->seq)381mt7921_mcu_rx_unsolicited_event(dev, skb);382else383mt76_mcu_rx_event(&dev->mt76, skb);384}385386/** starec & wtbl **/387int mt7921_mcu_uni_tx_ba(struct mt792x_dev *dev,388struct ieee80211_ampdu_params *params,389bool enable)390{391struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;392393if (enable && !params->amsdu)394msta->deflink.wcid.amsdu = false;395396return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->bss_conf.mt76, params,397MCU_UNI_CMD(STA_REC_UPDATE),398enable, true);399}400401int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev,402struct ieee80211_ampdu_params *params,403bool enable)404{405struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;406407return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->bss_conf.mt76, params,408MCU_UNI_CMD(STA_REC_UPDATE),409enable, false);410}411412static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)413{414const struct mt76_connac2_fw_trailer *hdr;415const struct mt76_connac2_fw_region *region;416const struct mt7921_clc *clc;417struct mt76_dev *mdev = &dev->mt76;418struct mt792x_phy *phy = &dev->phy;419const struct firmware *fw;420int ret, i, len, offset = 0;421#if defined(__linux__)422u8 *clc_base = NULL, hw_encap = 0;423#elif defined(__FreeBSD__)424const u8 *clc_base = NULL;425u8 hw_encap = 0;426#endif427428dev->phy.clc_chan_conf = 0xff;429if (mt7921_disable_clc ||430mt76_is_usb(&dev->mt76))431return 0;432433if (mt76_is_mmio(&dev->mt76)) {434ret = mt7921_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap);435if (ret)436return ret;437hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP);438}439440ret = request_firmware(&fw, fw_name, mdev->dev);441if (ret)442return ret;443444if (!fw || !fw->data || fw->size < sizeof(*hdr)) {445dev_err(mdev->dev, "Invalid firmware\n");446ret = -EINVAL;447goto out;448}449450hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));451for (i = 0; i < hdr->n_region; i++) {452region = (const void *)((const u8 *)hdr -453(hdr->n_region - i) * sizeof(*region));454len = le32_to_cpu(region->len);455456/* check if we have valid buffer size */457if (offset + len > fw->size) {458dev_err(mdev->dev, "Invalid firmware region\n");459ret = -EINVAL;460goto out;461}462463if ((region->feature_set & FW_FEATURE_NON_DL) &&464region->type == FW_TYPE_CLC) {465#if defined(__linux__)466clc_base = (u8 *)(fw->data + offset);467#elif defined(__FreeBSD__)468clc_base = (const u8 *)(fw->data + offset);469#endif470break;471}472offset += len;473}474475if (!clc_base)476goto out;477478for (offset = 0; offset < len; offset += le32_to_cpu(clc->len)) {479clc = (const struct mt7921_clc *)(clc_base + offset);480481/* do not init buf again if chip reset triggered */482if (phy->clc[clc->idx])483continue;484485/* header content sanity */486if (clc->idx == MT7921_CLC_POWER &&487u8_get_bits(clc->type, MT_EE_HW_TYPE_ENCAP) != hw_encap)488continue;489490phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc,491le32_to_cpu(clc->len),492GFP_KERNEL);493494if (!phy->clc[clc->idx]) {495ret = -ENOMEM;496goto out;497}498}499ret = mt7921_mcu_set_clc(dev, "00", ENVIRON_INDOOR);500out:501release_firmware(fw);502503return ret;504}505506static void mt7921_mcu_parse_tx_resource(struct mt76_dev *dev,507struct sk_buff *skb)508{509struct mt76_sdio *sdio = &dev->sdio;510struct mt7921_tx_resource {511__le32 version;512__le32 pse_data_quota;513__le32 pse_mcu_quota;514__le32 ple_data_quota;515__le32 ple_mcu_quota;516__le16 pse_page_size;517__le16 ple_page_size;518u8 pp_padding;519u8 pad[3];520} __packed * tx_res;521522tx_res = (struct mt7921_tx_resource *)skb->data;523sdio->sched.pse_data_quota = le32_to_cpu(tx_res->pse_data_quota);524sdio->pse_mcu_quota_max = le32_to_cpu(tx_res->pse_mcu_quota);525/* The mcu quota usage of this function itself must be taken into consideration */526sdio->sched.pse_mcu_quota =527sdio->sched.pse_mcu_quota ? sdio->pse_mcu_quota_max : sdio->pse_mcu_quota_max - 1;528sdio->sched.ple_data_quota = le32_to_cpu(tx_res->ple_data_quota);529sdio->sched.pse_page_size = le16_to_cpu(tx_res->pse_page_size);530sdio->sched.deficit = tx_res->pp_padding;531}532533static void mt7921_mcu_parse_phy_cap(struct mt76_dev *dev,534struct sk_buff *skb)535{536struct mt7921_phy_cap {537u8 ht;538u8 vht;539u8 _5g;540u8 max_bw;541u8 nss;542u8 dbdc;543u8 tx_ldpc;544u8 rx_ldpc;545u8 tx_stbc;546u8 rx_stbc;547u8 hw_path;548u8 he;549} __packed * cap;550551enum {552WF0_24G,553WF0_5G554};555556cap = (struct mt7921_phy_cap *)skb->data;557558dev->phy.antenna_mask = BIT(cap->nss) - 1;559dev->phy.chainmask = dev->phy.antenna_mask;560dev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);561dev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);562}563564static int mt7921_mcu_get_nic_capability(struct mt792x_phy *mphy)565{566struct mt76_connac_cap_hdr {567__le16 n_element;568u8 rsv[2];569} __packed * hdr;570struct sk_buff *skb;571struct mt76_phy *phy = mphy->mt76;572int ret, i;573574ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CE_CMD(GET_NIC_CAPAB),575NULL, 0, true, &skb);576if (ret)577return ret;578579hdr = (struct mt76_connac_cap_hdr *)skb->data;580if (skb->len < sizeof(*hdr)) {581ret = -EINVAL;582goto out;583}584585skb_pull(skb, sizeof(*hdr));586587for (i = 0; i < le16_to_cpu(hdr->n_element); i++) {588struct tlv_hdr {589__le32 type;590__le32 len;591} __packed * tlv = (struct tlv_hdr *)skb->data;592int len;593594if (skb->len < sizeof(*tlv))595break;596597skb_pull(skb, sizeof(*tlv));598599len = le32_to_cpu(tlv->len);600if (skb->len < len)601break;602603switch (le32_to_cpu(tlv->type)) {604case MT_NIC_CAP_6G:605phy->cap.has_6ghz = skb->data[0];606break;607case MT_NIC_CAP_MAC_ADDR:608memcpy(phy->macaddr, (void *)skb->data, ETH_ALEN);609break;610case MT_NIC_CAP_PHY:611mt7921_mcu_parse_phy_cap(phy->dev, skb);612break;613case MT_NIC_CAP_TX_RESOURCE:614if (mt76_is_sdio(phy->dev))615mt7921_mcu_parse_tx_resource(phy->dev,616skb);617break;618case MT_NIC_CAP_CHIP_CAP:619memcpy(&mphy->chip_cap, (void *)skb->data, sizeof(u64));620break;621default:622break;623}624skb_pull(skb, len);625}626out:627dev_kfree_skb(skb);628629return ret;630}631632int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl)633{634struct {635u8 ctrl_val;636u8 pad[3];637} data = {638.ctrl_val = ctrl639};640641return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(FWLOG_2_HOST),642&data, sizeof(data), false);643}644645int mt7921_run_firmware(struct mt792x_dev *dev)646{647int err;648649err = mt792x_load_firmware(dev);650if (err)651return err;652653err = mt7921_mcu_get_nic_capability(&dev->phy);654if (err)655return err;656657set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);658err = mt7921_load_clc(dev, mt792x_ram_name(dev));659if (err)660return err;661662return mt7921_mcu_fw_log_2_host(dev, 1);663}664EXPORT_SYMBOL_GPL(mt7921_run_firmware);665666int mt7921_mcu_radio_led_ctrl(struct mt792x_dev *dev, u8 value)667{668struct {669u8 ctrlid;670u8 rsv[3];671} __packed req = {672.ctrlid = value,673};674675return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ID_RADIO_ON_OFF_CTRL),676&req, sizeof(req), false);677}678EXPORT_SYMBOL_GPL(mt7921_mcu_radio_led_ctrl);679680int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif)681{682struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;683struct edca {684__le16 cw_min;685__le16 cw_max;686__le16 txop;687__le16 aifs;688u8 guardtime;689u8 acm;690} __packed;691struct mt7921_mcu_tx {692struct edca edca[IEEE80211_NUM_ACS];693u8 bss_idx;694u8 qos;695u8 wmm_idx;696u8 pad;697} __packed req = {698.bss_idx = mvif->bss_conf.mt76.idx,699.qos = vif->bss_conf.qos,700.wmm_idx = mvif->bss_conf.mt76.wmm_idx,701};702struct mu_edca {703u8 cw_min;704u8 cw_max;705u8 aifsn;706u8 acm;707u8 timer;708u8 padding[3];709};710struct mt7921_mcu_mu_tx {711u8 ver;712u8 pad0;713__le16 len;714u8 bss_idx;715u8 qos;716u8 wmm_idx;717u8 pad1;718struct mu_edca edca[IEEE80211_NUM_ACS];719u8 pad3[32];720} __packed req_mu = {721.bss_idx = mvif->bss_conf.mt76.idx,722.qos = vif->bss_conf.qos,723.wmm_idx = mvif->bss_conf.mt76.wmm_idx,724};725static const int to_aci[] = { 1, 0, 2, 3 };726int ac, ret;727728for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {729struct ieee80211_tx_queue_params *q = &mvif->bss_conf.queue_params[ac];730struct edca *e = &req.edca[to_aci[ac]];731732e->aifs = cpu_to_le16(q->aifs);733e->txop = cpu_to_le16(q->txop);734735if (q->cw_min)736e->cw_min = cpu_to_le16(q->cw_min);737else738e->cw_min = cpu_to_le16(5);739740if (q->cw_max)741e->cw_max = cpu_to_le16(q->cw_max);742else743e->cw_max = cpu_to_le16(10);744}745746ret = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_EDCA_PARMS), &req,747sizeof(req), false);748if (ret)749return ret;750751if (!vif->bss_conf.he_support)752return 0;753754for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {755struct ieee80211_he_mu_edca_param_ac_rec *q;756struct mu_edca *e;757758if (!mvif->bss_conf.queue_params[ac].mu_edca)759break;760761q = &mvif->bss_conf.queue_params[ac].mu_edca_param_rec;762e = &(req_mu.edca[to_aci[ac]]);763764e->cw_min = q->ecw_min_max & 0xf;765e->cw_max = (q->ecw_min_max & 0xf0) >> 4;766e->aifsn = q->aifsn;767e->timer = q->mu_edca_timer;768}769770return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_MU_EDCA_PARMS),771&req_mu, sizeof(req_mu), false);772}773774int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,775struct ieee80211_channel *chan, int duration,776enum mt7921_roc_req type, u8 token_id)777{778int center_ch = ieee80211_frequency_to_channel(chan->center_freq);779struct mt792x_dev *dev = phy->dev;780struct {781struct {782u8 rsv[4];783} __packed hdr;784struct roc_acquire_tlv {785__le16 tag;786__le16 len;787u8 bss_idx;788u8 tokenid;789u8 control_channel;790u8 sco;791u8 band;792u8 bw;793u8 center_chan;794u8 center_chan2;795u8 bw_from_ap;796u8 center_chan_from_ap;797u8 center_chan2_from_ap;798u8 reqtype;799__le32 maxinterval;800u8 dbdcband;801u8 rsv[3];802} __packed roc;803} __packed req = {804.roc = {805.tag = cpu_to_le16(UNI_ROC_ACQUIRE),806.len = cpu_to_le16(sizeof(struct roc_acquire_tlv)),807.tokenid = token_id,808.reqtype = type,809.maxinterval = cpu_to_le32(duration),810.bss_idx = vif->bss_conf.mt76.idx,811.control_channel = chan->hw_value,812.bw = CMD_CBW_20MHZ,813.bw_from_ap = CMD_CBW_20MHZ,814.center_chan = center_ch,815.center_chan_from_ap = center_ch,816.dbdcband = 0xff, /* auto */817},818};819820if (chan->hw_value < center_ch)821req.roc.sco = 1; /* SCA */822else if (chan->hw_value > center_ch)823req.roc.sco = 3; /* SCB */824825switch (chan->band) {826case NL80211_BAND_6GHZ:827req.roc.band = 3;828break;829case NL80211_BAND_5GHZ:830req.roc.band = 2;831break;832default:833req.roc.band = 1;834break;835}836837return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),838&req, sizeof(req), false);839}840841int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,842u8 token_id)843{844struct mt792x_dev *dev = phy->dev;845struct {846struct {847u8 rsv[4];848} __packed hdr;849struct roc_abort_tlv {850__le16 tag;851__le16 len;852u8 bss_idx;853u8 tokenid;854u8 dbdcband;855u8 rsv[5];856} __packed abort;857} __packed req = {858.abort = {859.tag = cpu_to_le16(UNI_ROC_ABORT),860.len = cpu_to_le16(sizeof(struct roc_abort_tlv)),861.tokenid = token_id,862.bss_idx = vif->bss_conf.mt76.idx,863.dbdcband = 0xff, /* auto*/864},865};866867return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),868&req, sizeof(req), false);869}870871int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd)872{873struct mt792x_dev *dev = phy->dev;874struct cfg80211_chan_def *chandef = &phy->mt76->chandef;875int freq1 = chandef->center_freq1;876struct {877u8 control_ch;878u8 center_ch;879u8 bw;880u8 tx_streams_num;881u8 rx_streams; /* mask or num */882u8 switch_reason;883u8 band_idx;884u8 center_ch2; /* for 80+80 only */885__le16 cac_case;886u8 channel_band;887u8 rsv0;888__le32 outband_freq;889u8 txpower_drop;890u8 ap_bw;891u8 ap_center_ch;892u8 rsv1[57];893} __packed req = {894.control_ch = chandef->chan->hw_value,895.center_ch = ieee80211_frequency_to_channel(freq1),896.bw = mt76_connac_chan_bw(chandef),897.tx_streams_num = hweight8(phy->mt76->antenna_mask),898.rx_streams = phy->mt76->antenna_mask,899.band_idx = phy != &dev->phy,900};901902if (chandef->chan->band == NL80211_BAND_6GHZ)903req.channel_band = 2;904else905req.channel_band = chandef->chan->band;906907if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||908dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)909req.switch_reason = CH_SWITCH_NORMAL;910else if (phy->mt76->offchannel)911req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;912else if (!cfg80211_reg_can_beacon(dev->mt76.hw->wiphy, chandef,913NL80211_IFTYPE_AP))914req.switch_reason = CH_SWITCH_DFS;915else916req.switch_reason = CH_SWITCH_NORMAL;917918if (cmd == MCU_EXT_CMD(CHANNEL_SWITCH))919req.rx_streams = hweight8(req.rx_streams);920921if (chandef->width == NL80211_CHAN_WIDTH_80P80) {922int freq2 = chandef->center_freq2;923924req.center_ch2 = ieee80211_frequency_to_channel(freq2);925}926927return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);928}929930int mt7921_mcu_set_eeprom(struct mt792x_dev *dev)931{932struct req_hdr {933u8 buffer_mode;934u8 format;935__le16 len;936} __packed req = {937.buffer_mode = EE_MODE_EFUSE,938.format = EE_FORMAT_WHOLE,939};940941return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),942&req, sizeof(req), true);943}944EXPORT_SYMBOL_GPL(mt7921_mcu_set_eeprom);945946int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif)947{948struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;949struct {950struct {951u8 bss_idx;952u8 pad[3];953} __packed hdr;954struct ps_tlv {955__le16 tag;956__le16 len;957u8 ps_state; /* 0: device awake958* 1: static power save959* 2: dynamic power saving960* 3: enter TWT power saving961* 4: leave TWT power saving962*/963u8 pad[3];964} __packed ps;965} __packed ps_req = {966.hdr = {967.bss_idx = mvif->bss_conf.mt76.idx,968},969.ps = {970.tag = cpu_to_le16(UNI_BSS_INFO_PS),971.len = cpu_to_le16(sizeof(struct ps_tlv)),972.ps_state = vif->cfg.ps ? 2 : 0,973},974};975976if (vif->type != NL80211_IFTYPE_STATION)977return -EOPNOTSUPP;978979return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),980&ps_req, sizeof(ps_req), true);981}982983static int984mt7921_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif,985bool enable)986{987struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;988struct {989struct {990u8 bss_idx;991u8 pad[3];992} __packed hdr;993struct bcnft_tlv {994__le16 tag;995__le16 len;996__le16 bcn_interval;997u8 dtim_period;998u8 pad;999} __packed bcnft;1000} __packed bcnft_req = {1001.hdr = {1002.bss_idx = mvif->bss_conf.mt76.idx,1003},1004.bcnft = {1005.tag = cpu_to_le16(UNI_BSS_INFO_BCNFT),1006.len = cpu_to_le16(sizeof(struct bcnft_tlv)),1007.bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int),1008.dtim_period = vif->bss_conf.dtim_period,1009},1010};10111012if (vif->type != NL80211_IFTYPE_STATION)1013return 0;10141015return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),1016&bcnft_req, sizeof(bcnft_req), true);1017}10181019int1020mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif,1021bool enable)1022{1023struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1024struct {1025u8 bss_idx;1026u8 dtim_period;1027__le16 aid;1028__le16 bcn_interval;1029__le16 atim_window;1030u8 uapsd;1031u8 bmc_delivered_ac;1032u8 bmc_triggered_ac;1033u8 pad;1034} req = {1035.bss_idx = mvif->bss_conf.mt76.idx,1036.aid = cpu_to_le16(vif->cfg.aid),1037.dtim_period = vif->bss_conf.dtim_period,1038.bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int),1039};1040struct {1041u8 bss_idx;1042u8 pad[3];1043} req_hdr = {1044.bss_idx = mvif->bss_conf.mt76.idx,1045};1046int err;10471048err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT),1049&req_hdr, sizeof(req_hdr), false);1050if (err < 0 || !enable)1051return err;10521053return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_CONNECTED),1054&req, sizeof(req), false);1055}10561057int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta,1058struct ieee80211_vif *vif, bool enable,1059enum mt76_sta_info_state state)1060{1061struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1062int rssi = -ewma_rssi_read(&mvif->bss_conf.rssi);1063struct mt76_sta_cmd_info info = {1064.sta = sta,1065.vif = vif,1066.enable = enable,1067.cmd = MCU_UNI_CMD(STA_REC_UPDATE),1068.state = state,1069.offload_fw = true,1070.rcpi = to_rcpi(rssi),1071};1072struct mt792x_sta *msta;10731074msta = sta ? (struct mt792x_sta *)sta->drv_priv : NULL;1075info.wcid = msta ? &msta->deflink.wcid : &mvif->sta.deflink.wcid;1076info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true;10771078return mt76_connac_mcu_sta_cmd(&dev->mphy, &info);1079}10801081int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev,1082struct ieee80211_vif *vif,1083bool enable)1084{1085#define MT7921_FIF_BIT_CLR BIT(1)1086#define MT7921_FIF_BIT_SET BIT(0)1087int err;10881089if (enable) {1090err = mt7921_mcu_uni_bss_bcnft(dev, vif, true);1091if (err)1092return err;10931094err = mt7921_mcu_set_rxfilter(dev, 0,1095MT7921_FIF_BIT_SET,1096MT_WF_RFCR_DROP_OTHER_BEACON);1097if (err)1098return err;10991100return 0;1101}11021103err = mt7921_mcu_set_bss_pm(dev, vif, false);1104if (err)1105return err;11061107err = mt7921_mcu_set_rxfilter(dev, 0,1108MT7921_FIF_BIT_CLR,1109MT_WF_RFCR_DROP_OTHER_BEACON);1110if (err)1111return err;11121113return 0;1114}11151116int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr)1117{1118struct mt7921_txpwr_event *event;1119struct mt7921_txpwr_req req = {1120.dbdc_idx = 0,1121};1122struct sk_buff *skb;1123int ret;11241125ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CE_CMD(GET_TXPWR),1126&req, sizeof(req), true, &skb);1127if (ret)1128return ret;11291130event = (struct mt7921_txpwr_event *)skb->data;1131WARN_ON(skb->len != le16_to_cpu(event->len));1132memcpy(txpwr, &event->txpwr, sizeof(event->txpwr));11331134dev_kfree_skb(skb);11351136return 0;1137}11381139int mt7921_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,1140bool enable)1141{1142struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;1143struct {1144struct {1145u8 band_idx;1146u8 pad[3];1147} __packed hdr;1148struct sniffer_enable_tlv {1149__le16 tag;1150__le16 len;1151u8 enable;1152u8 pad[3];1153} __packed enable;1154} req = {1155.hdr = {1156.band_idx = mvif->band_idx,1157},1158.enable = {1159.tag = cpu_to_le16(0),1160.len = cpu_to_le16(sizeof(struct sniffer_enable_tlv)),1161.enable = enable,1162},1163};11641165return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req),1166true);1167}11681169int mt7921_mcu_config_sniffer(struct mt792x_vif *vif,1170struct ieee80211_chanctx_conf *ctx)1171{1172struct cfg80211_chan_def *chandef = &ctx->def;1173int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;1174static const u8 ch_band[] = {1175[NL80211_BAND_2GHZ] = 1,1176[NL80211_BAND_5GHZ] = 2,1177[NL80211_BAND_6GHZ] = 3,1178};1179static const u8 ch_width[] = {1180[NL80211_CHAN_WIDTH_20_NOHT] = 0,1181[NL80211_CHAN_WIDTH_20] = 0,1182[NL80211_CHAN_WIDTH_40] = 0,1183[NL80211_CHAN_WIDTH_80] = 1,1184[NL80211_CHAN_WIDTH_160] = 2,1185[NL80211_CHAN_WIDTH_80P80] = 3,1186[NL80211_CHAN_WIDTH_5] = 4,1187[NL80211_CHAN_WIDTH_10] = 5,1188[NL80211_CHAN_WIDTH_320] = 6,1189};1190struct {1191struct {1192u8 band_idx;1193u8 pad[3];1194} __packed hdr;1195struct config_tlv {1196__le16 tag;1197__le16 len;1198u16 aid;1199u8 ch_band;1200u8 bw;1201u8 control_ch;1202u8 sco;1203u8 center_ch;1204u8 center_ch2;1205u8 drop_err;1206u8 pad[3];1207} __packed tlv;1208} __packed req = {1209.hdr = {1210.band_idx = vif->bss_conf.mt76.band_idx,1211},1212.tlv = {1213.tag = cpu_to_le16(1),1214.len = cpu_to_le16(sizeof(req.tlv)),1215.control_ch = chandef->chan->hw_value,1216.center_ch = ieee80211_frequency_to_channel(freq1),1217.drop_err = 1,1218},1219};1220if (chandef->chan->band < ARRAY_SIZE(ch_band))1221req.tlv.ch_band = ch_band[chandef->chan->band];1222if (chandef->width < ARRAY_SIZE(ch_width))1223req.tlv.bw = ch_width[chandef->width];12241225if (freq2)1226req.tlv.center_ch2 = ieee80211_frequency_to_channel(freq2);12271228if (req.tlv.control_ch < req.tlv.center_ch)1229req.tlv.sco = 1; /* SCA */1230else if (req.tlv.control_ch > req.tlv.center_ch)1231req.tlv.sco = 3; /* SCB */12321233return mt76_mcu_send_msg(vif->phy->mt76->dev, MCU_UNI_CMD(SNIFFER),1234&req, sizeof(req), true);1235}12361237int1238mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev,1239struct ieee80211_hw *hw,1240struct ieee80211_vif *vif,1241bool enable)1242{1243struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1244struct mt76_wcid *wcid = &dev->mt76.global_wcid;1245struct ieee80211_mutable_offsets offs;1246struct {1247struct req_hdr {1248u8 bss_idx;1249u8 pad[3];1250} __packed hdr;1251struct bcn_content_tlv {1252__le16 tag;1253__le16 len;1254__le16 tim_ie_pos;1255__le16 csa_ie_pos;1256__le16 bcc_ie_pos;1257/* 0: disable beacon offload1258* 1: enable beacon offload1259* 2: update probe respond offload1260*/1261u8 enable;1262/* 0: legacy format (TXD + payload)1263* 1: only cap field IE1264*/1265u8 type;1266__le16 pkt_len;1267u8 pkt[512];1268} __packed beacon_tlv;1269} req = {1270.hdr = {1271.bss_idx = mvif->bss_conf.mt76.idx,1272},1273.beacon_tlv = {1274.tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT),1275.len = cpu_to_le16(sizeof(struct bcn_content_tlv)),1276.enable = enable,1277},1278};1279struct sk_buff *skb;12801281/* support enable/update process only1282* disable flow would be handled in bss stop handler automatically1283*/1284if (!enable)1285return -EOPNOTSUPP;12861287skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0);1288if (!skb)1289return -EINVAL;12901291if (skb->len > 512 - MT_TXD_SIZE) {1292dev_err(dev->mt76.dev, "beacon size limit exceed\n");1293dev_kfree_skb(skb);1294return -EINVAL;1295}12961297mt76_connac2_mac_write_txwi(&dev->mt76, (__le32 *)(req.beacon_tlv.pkt),1298skb, wcid, NULL, 0, 0, BSS_CHANGED_BEACON);1299memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);1300req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);1301req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);13021303if (offs.cntdwn_counter_offs[0]) {1304u16 csa_offs;13051306csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;1307req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs);1308}1309dev_kfree_skb(skb);13101311return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),1312&req, sizeof(req), true);1313}13141315static1316int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,1317enum environment_cap env_cap,1318struct mt7921_clc *clc,1319u8 idx)1320{1321#define CLC_CAP_EVT_EN BIT(0)1322#define CLC_CAP_DTS_EN BIT(1)1323struct sk_buff *skb, *ret_skb = NULL;1324struct {1325u8 ver;1326u8 pad0;1327__le16 len;1328u8 idx;1329u8 env;1330u8 acpi_conf;1331u8 cap;1332u8 alpha2[2];1333u8 type[2];1334u8 env_6g;1335u8 mtcl_conf;1336u8 rsvd[62];1337} __packed req = {1338.ver = 1,1339.idx = idx,1340.env = env_cap,1341.env_6g = dev->phy.power_type,1342.acpi_conf = mt792x_acpi_get_flags(&dev->phy),1343.mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2),1344};1345int ret, valid_cnt = 0;1346u32 buf_len = 0;1347u8 *pos;13481349if (!clc)1350return 0;13511352if (dev->phy.chip_cap & MT792x_CHIP_CAP_CLC_EVT_EN)1353req.cap |= CLC_CAP_EVT_EN;1354if (mt76_find_power_limits_node(&dev->mt76))1355req.cap |= CLC_CAP_DTS_EN;13561357buf_len = le32_to_cpu(clc->len) - sizeof(*clc);1358pos = clc->data;1359while (buf_len > 16) {1360struct mt7921_clc_rule *rule = (struct mt7921_clc_rule *)pos;1361u16 len = le16_to_cpu(rule->len);1362u16 offset = len + sizeof(*rule);13631364pos += offset;1365buf_len -= offset;1366if (rule->alpha2[0] != alpha2[0] ||1367rule->alpha2[1] != alpha2[1])1368continue;13691370memcpy(req.alpha2, rule->alpha2, 2);1371memcpy(req.type, rule->type, 2);13721373req.len = cpu_to_le16(sizeof(req) + len);1374skb = __mt76_mcu_msg_alloc(&dev->mt76, &req,1375le16_to_cpu(req.len),1376sizeof(req), GFP_KERNEL);1377if (!skb)1378return -ENOMEM;1379skb_put_data(skb, rule->data, len);13801381ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,1382MCU_CE_CMD(SET_CLC),1383!!(req.cap & CLC_CAP_EVT_EN),1384&ret_skb);1385if (ret < 0)1386return ret;13871388if (ret_skb) {1389struct mt7921_clc_info_tlv *info;13901391info = (struct mt7921_clc_info_tlv *)(ret_skb->data + 4);1392dev->phy.clc_chan_conf = info->chan_conf;1393dev_kfree_skb(ret_skb);1394}13951396valid_cnt++;1397}13981399if (!valid_cnt)1400return -ENOENT;14011402return 0;1403}14041405int mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,1406enum environment_cap env_cap)1407{1408struct mt792x_phy *phy = (struct mt792x_phy *)&dev->phy;1409int i, ret;14101411/* submit all clc config */1412for (i = 0; i < ARRAY_SIZE(phy->clc); i++) {1413ret = __mt7921_mcu_set_clc(dev, alpha2, env_cap,1414phy->clc[i], i);14151416/* If no country found, set "00" as default */1417if (ret == -ENOENT)1418ret = __mt7921_mcu_set_clc(dev, "00",1419ENVIRON_INDOOR,1420phy->clc[i], i);1421if (ret < 0)1422return ret;1423}1424return 0;1425}14261427int mt7921_mcu_get_temperature(struct mt792x_phy *phy)1428{1429struct mt792x_dev *dev = phy->dev;1430struct {1431u8 ctrl_id;1432u8 action;1433u8 band_idx;1434u8 rsv[5];1435} req = {1436.ctrl_id = THERMAL_SENSOR_TEMP_QUERY,1437.band_idx = phy->mt76->band_idx,1438};14391440return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), &req,1441sizeof(req), true);1442}14431444int mt7921_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy, u8 action)1445{1446struct mt792x_dev *dev = phy->dev;1447struct {1448u8 action;1449u8 value;1450} req = {1451.action = action,1452.value = 0,1453};14541455return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(WF_RF_PIN_CTRL), &req,1456sizeof(req), action ? true : false);1457}14581459int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,1460u8 bit_op, u32 bit_map)1461{1462struct {1463u8 rsv[4];1464u8 mode;1465u8 rsv2[3];1466__le32 fif;1467__le32 bit_map; /* bit_* for bitmap update */1468u8 bit_op;1469u8 pad[51];1470} __packed data = {1471.mode = fif ? 1 : 2,1472.fif = cpu_to_le32(fif),1473.bit_map = cpu_to_le32(bit_map),1474.bit_op = bit_op,1475};14761477return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_RX_FILTER),1478&data, sizeof(data), false);1479}14801481int mt7921_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif)1482{1483struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1484struct {1485u8 enable;1486s8 cqm_rssi_high;1487s8 cqm_rssi_low;1488u8 bss_idx;1489u16 duration;1490u8 rsv2[2];1491} __packed data = {1492.enable = vif->cfg.assoc,1493.cqm_rssi_high = vif->bss_conf.cqm_rssi_thold + vif->bss_conf.cqm_rssi_hyst,1494.cqm_rssi_low = vif->bss_conf.cqm_rssi_thold - vif->bss_conf.cqm_rssi_hyst,1495.bss_idx = mvif->bss_conf.mt76.idx,1496};14971498return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(RSSI_MONITOR),1499&data, sizeof(data), false);1500}150115021503