Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7921/mcu.c
107787 views
// SPDX-License-Identifier: BSD-3-Clause-Clear1/* Copyright (C) 2020 MediaTek Inc. */23#if defined(__FreeBSD__)4#define LINUXKPI_PARAM_PREFIX mt7921_5#endif67#include <linux/fs.h>8#include <linux/firmware.h>9#include "mt7921.h"10#include "mcu.h"11#include "../mt76_connac2_mac.h"12#include "../mt792x_trace.h"1314#define MT_STA_BFER BIT(0)15#define MT_STA_BFEE BIT(1)1617static bool mt7921_disable_clc;18module_param_named(disable_clc, mt7921_disable_clc, bool, 0644);19MODULE_PARM_DESC(disable_clc, "disable CLC support");2021int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,22struct sk_buff *skb, int seq)23{24int mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);25struct mt76_connac2_mcu_rxd *rxd;26int ret = 0;2728if (!skb) {29dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",30cmd, seq);31mt792x_reset(mdev);3233return -ETIMEDOUT;34}3536rxd = (struct mt76_connac2_mcu_rxd *)skb->data;37if (seq != rxd->seq)38return -EAGAIN;3940if (cmd == MCU_CMD(PATCH_SEM_CONTROL) ||41cmd == MCU_CMD(PATCH_FINISH_REQ)) {42skb_pull(skb, sizeof(*rxd) - 4);43ret = *skb->data;44} else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {45skb_pull(skb, sizeof(*rxd) + 4);46ret = le32_to_cpu(*(__le32 *)skb->data);47} else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) ||48cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) ||49cmd == MCU_UNI_CMD(STA_REC_UPDATE) ||50cmd == MCU_UNI_CMD(HIF_CTRL) ||51cmd == MCU_UNI_CMD(OFFLOAD) ||52cmd == MCU_UNI_CMD(SUSPEND)) {53struct mt76_connac_mcu_uni_event *event;5455skb_pull(skb, sizeof(*rxd));56event = (struct mt76_connac_mcu_uni_event *)skb->data;57ret = le32_to_cpu(event->status);58/* skip invalid event */59if (mcu_cmd != event->cid)60ret = -EAGAIN;61} else if (cmd == MCU_CE_QUERY(REG_READ)) {62struct mt76_connac_mcu_reg_event *event;6364skb_pull(skb, sizeof(*rxd));65event = (struct mt76_connac_mcu_reg_event *)skb->data;66ret = (int)le32_to_cpu(event->val);67} else if (cmd == MCU_EXT_CMD(WF_RF_PIN_CTRL)) {68struct mt7921_wf_rf_pin_ctrl_event *event;6970skb_pull(skb, sizeof(*rxd));71event = (struct mt7921_wf_rf_pin_ctrl_event *)skb->data;72ret = (int)event->result;73} else {74skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));75}7677return ret;78}79EXPORT_SYMBOL_GPL(mt7921_mcu_parse_response);8081static int mt7921_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val)82{83struct mt7921_mcu_eeprom_info *res, req = {84.addr = cpu_to_le32(round_down(offset,85MT7921_EEPROM_BLOCK_SIZE)),86};87struct sk_buff *skb;88int ret;8990ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(EFUSE_ACCESS),91&req, sizeof(req), true, &skb);92if (ret)93return ret;9495res = (struct mt7921_mcu_eeprom_info *)skb->data;96*val = res->data[offset % MT7921_EEPROM_BLOCK_SIZE];97dev_kfree_skb(skb);9899return 0;100}101102#ifdef CONFIG_PM103104static int105mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev,106struct ieee80211_vif *vif, bool suspend)107{108struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;109struct {110struct {111u8 bss_idx;112u8 pad[3];113} __packed hdr;114struct mt76_connac_arpns_tlv arpns;115} req = {116.hdr = {117.bss_idx = mvif->bss_conf.mt76.idx,118},119.arpns = {120.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND),121.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)),122.mode = suspend,123},124};125126return mt76_mcu_send_msg(dev, MCU_UNI_CMD_OFFLOAD, &req, sizeof(req),127true);128}129130void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)131{132if (IS_ENABLED(CONFIG_IPV6)) {133struct mt76_phy *phy = priv;134135mt7921_mcu_set_ipv6_ns_filter(phy->dev, vif,136!test_bit(MT76_STATE_RUNNING,137&phy->state));138}139140mt76_connac_mcu_set_suspend_iter(priv, mac, vif);141}142143#endif /* CONFIG_PM */144145static void146mt7921_mcu_uni_roc_event(struct mt792x_dev *dev, struct sk_buff *skb)147{148struct mt7921_roc_grant_tlv *grant;149struct mt76_connac2_mcu_rxd *rxd;150int duration;151152rxd = (struct mt76_connac2_mcu_rxd *)skb->data;153grant = (struct mt7921_roc_grant_tlv *)(rxd->tlv + 4);154155/* should never happen */156WARN_ON_ONCE((le16_to_cpu(grant->tag) != UNI_EVENT_ROC_GRANT));157158if (grant->reqtype == MT7921_ROC_REQ_ROC)159ieee80211_ready_on_channel(dev->mt76.phy.hw);160161dev->phy.roc_grant = true;162wake_up(&dev->phy.roc_wait);163duration = le32_to_cpu(grant->max_interval);164mod_timer(&dev->phy.roc_timer,165jiffies + msecs_to_jiffies(duration));166}167168static void169mt7921_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb)170{171struct mt76_phy *mphy = &dev->mt76.phy;172struct mt792x_phy *phy = mphy->priv;173174spin_lock_bh(&dev->mt76.lock);175__skb_queue_tail(&phy->scan_event_list, skb);176spin_unlock_bh(&dev->mt76.lock);177178ieee80211_queue_delayed_work(mphy->hw, &phy->scan_work,179MT792x_HW_SCAN_TIMEOUT);180}181182static void183mt7921_mcu_connection_loss_iter(void *priv, u8 *mac,184struct ieee80211_vif *vif)185{186struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;187struct mt76_connac_beacon_loss_event *event = priv;188189if (mvif->idx != event->bss_idx)190return;191192if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER) ||193vif->type != NL80211_IFTYPE_STATION)194return;195196ieee80211_connection_loss(vif);197}198199static void200mt7921_mcu_connection_loss_event(struct mt792x_dev *dev, struct sk_buff *skb)201{202struct mt76_connac_beacon_loss_event *event;203struct mt76_phy *mphy = &dev->mt76.phy;204205skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));206event = (struct mt76_connac_beacon_loss_event *)skb->data;207208ieee80211_iterate_active_interfaces_atomic(mphy->hw,209IEEE80211_IFACE_ITER_RESUME_ALL,210mt7921_mcu_connection_loss_iter, event);211}212213static void214mt7921_mcu_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb)215{216struct mt7921_debug_msg {217__le16 id;218u8 type;219u8 flag;220__le32 value;221__le16 len;222u8 content[512];223} __packed * msg;224225skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));226msg = (struct mt7921_debug_msg *)skb->data;227228if (msg->type == 3) { /* fw log */229u16 len = min_t(u16, le16_to_cpu(msg->len), 512);230int i;231232for (i = 0 ; i < len; i++) {233if (!msg->content[i])234msg->content[i] = ' ';235}236wiphy_info(mt76_hw(dev)->wiphy, "%.*s", len, msg->content);237}238}239240static void241mt7921_mcu_low_power_event(struct mt792x_dev *dev, struct sk_buff *skb)242{243struct mt7921_mcu_lp_event {244u8 state;245u8 reserved[3];246} __packed * event;247248skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));249event = (struct mt7921_mcu_lp_event *)skb->data;250251trace_lp_event(dev, event->state);252}253254static void255mt7921_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb)256{257struct mt7921_mcu_tx_done_event *event;258259skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));260event = (struct mt7921_mcu_tx_done_event *)skb->data;261262mt7921_mac_add_txs(dev, event->txs);263}264265static void266mt7921_mcu_rssi_monitor_iter(void *priv, u8 *mac,267struct ieee80211_vif *vif)268{269struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;270struct mt76_connac_rssi_notify_event *event = priv;271enum nl80211_cqm_rssi_threshold_event nl_event;272s32 rssi = le32_to_cpu(event->rssi[mvif->bss_conf.mt76.idx]);273274if (!rssi)275return;276277if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))278return;279280if (rssi > vif->bss_conf.cqm_rssi_thold)281nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;282else283nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;284285ieee80211_cqm_rssi_notify(vif, nl_event, rssi, GFP_KERNEL);286}287288static void289mt7921_mcu_rssi_monitor_event(struct mt792x_dev *dev, struct sk_buff *skb)290{291struct mt76_connac_rssi_notify_event *event;292293skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));294event = (struct mt76_connac_rssi_notify_event *)skb->data;295296ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),297IEEE80211_IFACE_ITER_RESUME_ALL,298mt7921_mcu_rssi_monitor_iter, event);299}300301static void302mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb)303{304struct mt76_connac2_mcu_rxd *rxd;305306rxd = (struct mt76_connac2_mcu_rxd *)skb->data;307switch (rxd->eid) {308case MCU_EVENT_BSS_BEACON_LOSS:309mt7921_mcu_connection_loss_event(dev, skb);310break;311case MCU_EVENT_SCHED_SCAN_DONE:312case MCU_EVENT_SCAN_DONE:313mt7921_mcu_scan_event(dev, skb);314return;315case MCU_EVENT_DBG_MSG:316mt7921_mcu_debug_msg_event(dev, skb);317break;318case MCU_EVENT_COREDUMP:319dev->fw_assert = true;320mt76_connac_mcu_coredump_event(&dev->mt76, skb,321&dev->coredump);322return;323case MCU_EVENT_LP_INFO:324mt7921_mcu_low_power_event(dev, skb);325break;326case MCU_EVENT_TX_DONE:327mt7921_mcu_tx_done_event(dev, skb);328break;329case MCU_EVENT_RSSI_NOTIFY:330mt7921_mcu_rssi_monitor_event(dev, skb);331break;332default:333break;334}335dev_kfree_skb(skb);336}337338static void339mt7921_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev,340struct sk_buff *skb)341{342struct mt76_connac2_mcu_rxd *rxd;343344rxd = (struct mt76_connac2_mcu_rxd *)skb->data;345346switch (rxd->eid) {347case MCU_UNI_EVENT_ROC:348mt7921_mcu_uni_roc_event(dev, skb);349break;350default:351break;352}353dev_kfree_skb(skb);354}355356void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)357{358struct mt76_connac2_mcu_rxd *rxd;359360if (skb_linearize(skb))361return;362363rxd = (struct mt76_connac2_mcu_rxd *)skb->data;364365if (rxd->option & MCU_UNI_CMD_UNSOLICITED_EVENT) {366mt7921_mcu_uni_rx_unsolicited_event(dev, skb);367return;368}369370if (rxd->eid == 0x6) {371mt76_mcu_rx_event(&dev->mt76, skb);372return;373}374375if (rxd->ext_eid == MCU_EXT_EVENT_RATE_REPORT ||376rxd->eid == MCU_EVENT_BSS_BEACON_LOSS ||377rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||378rxd->eid == MCU_EVENT_RSSI_NOTIFY ||379rxd->eid == MCU_EVENT_SCAN_DONE ||380rxd->eid == MCU_EVENT_TX_DONE ||381rxd->eid == MCU_EVENT_DBG_MSG ||382rxd->eid == MCU_EVENT_COREDUMP ||383rxd->eid == MCU_EVENT_LP_INFO ||384!rxd->seq)385mt7921_mcu_rx_unsolicited_event(dev, skb);386else387mt76_mcu_rx_event(&dev->mt76, skb);388}389390/** starec & wtbl **/391int mt7921_mcu_uni_tx_ba(struct mt792x_dev *dev,392struct ieee80211_ampdu_params *params,393bool enable)394{395struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;396397if (enable && !params->amsdu)398msta->deflink.wcid.amsdu = false;399400return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->bss_conf.mt76, params,401MCU_UNI_CMD(STA_REC_UPDATE),402enable, true);403}404405int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev,406struct ieee80211_ampdu_params *params,407bool enable)408{409struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;410411return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->bss_conf.mt76, params,412MCU_UNI_CMD(STA_REC_UPDATE),413enable, false);414}415416static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)417{418const struct mt76_connac2_fw_trailer *hdr;419const struct mt76_connac2_fw_region *region;420const struct mt7921_clc *clc;421struct mt76_dev *mdev = &dev->mt76;422struct mt792x_phy *phy = &dev->phy;423const struct firmware *fw;424int ret, i, len, offset = 0;425#if defined(__linux__)426u8 *clc_base = NULL, hw_encap = 0;427#elif defined(__FreeBSD__)428const u8 *clc_base = NULL;429u8 hw_encap = 0;430#endif431432dev->phy.clc_chan_conf = 0xff;433if (mt7921_disable_clc ||434mt76_is_usb(&dev->mt76))435return 0;436437if (mt76_is_mmio(&dev->mt76)) {438ret = mt7921_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap);439if (ret)440return ret;441hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP);442}443444ret = request_firmware(&fw, fw_name, mdev->dev);445if (ret)446return ret;447448if (!fw || !fw->data || fw->size < sizeof(*hdr)) {449dev_err(mdev->dev, "Invalid firmware\n");450ret = -EINVAL;451goto out;452}453454hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));455for (i = 0; i < hdr->n_region; i++) {456region = (const void *)((const u8 *)hdr -457(hdr->n_region - i) * sizeof(*region));458len = le32_to_cpu(region->len);459460/* check if we have valid buffer size */461if (offset + len > fw->size) {462dev_err(mdev->dev, "Invalid firmware region\n");463ret = -EINVAL;464goto out;465}466467if ((region->feature_set & FW_FEATURE_NON_DL) &&468region->type == FW_TYPE_CLC) {469#if defined(__linux__)470clc_base = (u8 *)(fw->data + offset);471#elif defined(__FreeBSD__)472clc_base = (const u8 *)(fw->data + offset);473#endif474break;475}476offset += len;477}478479if (!clc_base)480goto out;481482for (offset = 0; offset < len; offset += le32_to_cpu(clc->len)) {483clc = (const struct mt7921_clc *)(clc_base + offset);484485/* do not init buf again if chip reset triggered */486if (phy->clc[clc->idx])487continue;488489/* header content sanity */490if (clc->idx == MT7921_CLC_POWER &&491u8_get_bits(clc->type, MT_EE_HW_TYPE_ENCAP) != hw_encap)492continue;493494phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc,495le32_to_cpu(clc->len),496GFP_KERNEL);497498if (!phy->clc[clc->idx]) {499ret = -ENOMEM;500goto out;501}502}503ret = mt7921_mcu_set_clc(dev, "00", ENVIRON_INDOOR);504out:505release_firmware(fw);506507return ret;508}509510static void mt7921_mcu_parse_tx_resource(struct mt76_dev *dev,511struct sk_buff *skb)512{513struct mt76_sdio *sdio = &dev->sdio;514struct mt7921_tx_resource {515__le32 version;516__le32 pse_data_quota;517__le32 pse_mcu_quota;518__le32 ple_data_quota;519__le32 ple_mcu_quota;520__le16 pse_page_size;521__le16 ple_page_size;522u8 pp_padding;523u8 pad[3];524} __packed * tx_res;525526tx_res = (struct mt7921_tx_resource *)skb->data;527sdio->sched.pse_data_quota = le32_to_cpu(tx_res->pse_data_quota);528sdio->pse_mcu_quota_max = le32_to_cpu(tx_res->pse_mcu_quota);529/* The mcu quota usage of this function itself must be taken into consideration */530sdio->sched.pse_mcu_quota =531sdio->sched.pse_mcu_quota ? sdio->pse_mcu_quota_max : sdio->pse_mcu_quota_max - 1;532sdio->sched.ple_data_quota = le32_to_cpu(tx_res->ple_data_quota);533sdio->sched.pse_page_size = le16_to_cpu(tx_res->pse_page_size);534sdio->sched.deficit = tx_res->pp_padding;535}536537static void mt7921_mcu_parse_phy_cap(struct mt76_dev *dev,538struct sk_buff *skb)539{540struct mt7921_phy_cap {541u8 ht;542u8 vht;543u8 _5g;544u8 max_bw;545u8 nss;546u8 dbdc;547u8 tx_ldpc;548u8 rx_ldpc;549u8 tx_stbc;550u8 rx_stbc;551u8 hw_path;552u8 he;553} __packed * cap;554555enum {556WF0_24G,557WF0_5G558};559560cap = (struct mt7921_phy_cap *)skb->data;561562dev->phy.antenna_mask = BIT(cap->nss) - 1;563dev->phy.chainmask = dev->phy.antenna_mask;564dev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);565dev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);566}567568static int mt7921_mcu_get_nic_capability(struct mt792x_phy *mphy)569{570struct mt76_connac_cap_hdr {571__le16 n_element;572u8 rsv[2];573} __packed * hdr;574struct sk_buff *skb;575struct mt76_phy *phy = mphy->mt76;576int ret, i;577578ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CE_CMD(GET_NIC_CAPAB),579NULL, 0, true, &skb);580if (ret)581return ret;582583hdr = (struct mt76_connac_cap_hdr *)skb->data;584if (skb->len < sizeof(*hdr)) {585ret = -EINVAL;586goto out;587}588589skb_pull(skb, sizeof(*hdr));590591for (i = 0; i < le16_to_cpu(hdr->n_element); i++) {592struct tlv_hdr {593__le32 type;594__le32 len;595} __packed * tlv = (struct tlv_hdr *)skb->data;596int len;597598if (skb->len < sizeof(*tlv))599break;600601skb_pull(skb, sizeof(*tlv));602603len = le32_to_cpu(tlv->len);604if (skb->len < len)605break;606607switch (le32_to_cpu(tlv->type)) {608case MT_NIC_CAP_6G:609phy->cap.has_6ghz = skb->data[0];610break;611case MT_NIC_CAP_MAC_ADDR:612memcpy(phy->macaddr, (void *)skb->data, ETH_ALEN);613break;614case MT_NIC_CAP_PHY:615mt7921_mcu_parse_phy_cap(phy->dev, skb);616break;617case MT_NIC_CAP_TX_RESOURCE:618if (mt76_is_sdio(phy->dev))619mt7921_mcu_parse_tx_resource(phy->dev,620skb);621break;622case MT_NIC_CAP_CHIP_CAP:623memcpy(&mphy->chip_cap, (void *)skb->data, sizeof(u64));624break;625default:626break;627}628skb_pull(skb, len);629}630out:631dev_kfree_skb(skb);632633return ret;634}635636int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl)637{638struct {639u8 ctrl_val;640u8 pad[3];641} data = {642.ctrl_val = ctrl643};644645return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(FWLOG_2_HOST),646&data, sizeof(data), false);647}648649int mt7921_run_firmware(struct mt792x_dev *dev)650{651int err;652653err = mt792x_load_firmware(dev);654if (err)655return err;656657err = mt7921_mcu_get_nic_capability(&dev->phy);658if (err)659return err;660661err = mt7921_load_clc(dev, mt792x_ram_name(dev));662if (err)663return err;664set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);665666return mt7921_mcu_fw_log_2_host(dev, 1);667}668EXPORT_SYMBOL_GPL(mt7921_run_firmware);669670int mt7921_mcu_radio_led_ctrl(struct mt792x_dev *dev, u8 value)671{672struct {673u8 ctrlid;674u8 rsv[3];675} __packed req = {676.ctrlid = value,677};678679return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ID_RADIO_ON_OFF_CTRL),680&req, sizeof(req), false);681}682EXPORT_SYMBOL_GPL(mt7921_mcu_radio_led_ctrl);683684int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif)685{686struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;687struct edca {688__le16 cw_min;689__le16 cw_max;690__le16 txop;691__le16 aifs;692u8 guardtime;693u8 acm;694} __packed;695struct mt7921_mcu_tx {696struct edca edca[IEEE80211_NUM_ACS];697u8 bss_idx;698u8 qos;699u8 wmm_idx;700u8 pad;701} __packed req = {702.bss_idx = mvif->bss_conf.mt76.idx,703.qos = vif->bss_conf.qos,704.wmm_idx = mvif->bss_conf.mt76.wmm_idx,705};706struct mu_edca {707u8 cw_min;708u8 cw_max;709u8 aifsn;710u8 acm;711u8 timer;712u8 padding[3];713};714struct mt7921_mcu_mu_tx {715u8 ver;716u8 pad0;717__le16 len;718u8 bss_idx;719u8 qos;720u8 wmm_idx;721u8 pad1;722struct mu_edca edca[IEEE80211_NUM_ACS];723u8 pad3[32];724} __packed req_mu = {725.bss_idx = mvif->bss_conf.mt76.idx,726.qos = vif->bss_conf.qos,727.wmm_idx = mvif->bss_conf.mt76.wmm_idx,728};729static const int to_aci[] = { 1, 0, 2, 3 };730int ac, ret;731732for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {733struct ieee80211_tx_queue_params *q = &mvif->bss_conf.queue_params[ac];734struct edca *e = &req.edca[to_aci[ac]];735736e->aifs = cpu_to_le16(q->aifs);737e->txop = cpu_to_le16(q->txop);738739if (q->cw_min)740e->cw_min = cpu_to_le16(q->cw_min);741else742e->cw_min = cpu_to_le16(5);743744if (q->cw_max)745e->cw_max = cpu_to_le16(q->cw_max);746else747e->cw_max = cpu_to_le16(10);748}749750ret = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_EDCA_PARMS), &req,751sizeof(req), false);752if (ret)753return ret;754755if (!vif->bss_conf.he_support)756return 0;757758for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {759struct ieee80211_he_mu_edca_param_ac_rec *q;760struct mu_edca *e;761762if (!mvif->bss_conf.queue_params[ac].mu_edca)763break;764765q = &mvif->bss_conf.queue_params[ac].mu_edca_param_rec;766e = &(req_mu.edca[to_aci[ac]]);767768e->cw_min = q->ecw_min_max & 0xf;769e->cw_max = (q->ecw_min_max & 0xf0) >> 4;770e->aifsn = q->aifsn;771e->timer = q->mu_edca_timer;772}773774return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_MU_EDCA_PARMS),775&req_mu, sizeof(req_mu), false);776}777778int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,779struct ieee80211_channel *chan, int duration,780enum mt7921_roc_req type, u8 token_id)781{782int center_ch = ieee80211_frequency_to_channel(chan->center_freq);783struct mt792x_dev *dev = phy->dev;784struct {785struct {786u8 rsv[4];787} __packed hdr;788struct roc_acquire_tlv {789__le16 tag;790__le16 len;791u8 bss_idx;792u8 tokenid;793u8 control_channel;794u8 sco;795u8 band;796u8 bw;797u8 center_chan;798u8 center_chan2;799u8 bw_from_ap;800u8 center_chan_from_ap;801u8 center_chan2_from_ap;802u8 reqtype;803__le32 maxinterval;804u8 dbdcband;805u8 rsv[3];806} __packed roc;807} __packed req = {808.roc = {809.tag = cpu_to_le16(UNI_ROC_ACQUIRE),810.len = cpu_to_le16(sizeof(struct roc_acquire_tlv)),811.tokenid = token_id,812.reqtype = type,813.maxinterval = cpu_to_le32(duration),814.bss_idx = vif->bss_conf.mt76.idx,815.control_channel = chan->hw_value,816.bw = CMD_CBW_20MHZ,817.bw_from_ap = CMD_CBW_20MHZ,818.center_chan = center_ch,819.center_chan_from_ap = center_ch,820.dbdcband = 0xff, /* auto */821},822};823824if (chan->hw_value < center_ch)825req.roc.sco = 1; /* SCA */826else if (chan->hw_value > center_ch)827req.roc.sco = 3; /* SCB */828829switch (chan->band) {830case NL80211_BAND_6GHZ:831req.roc.band = 3;832break;833case NL80211_BAND_5GHZ:834req.roc.band = 2;835break;836default:837req.roc.band = 1;838break;839}840841return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),842&req, sizeof(req), false);843}844845int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,846u8 token_id)847{848struct mt792x_dev *dev = phy->dev;849struct {850struct {851u8 rsv[4];852} __packed hdr;853struct roc_abort_tlv {854__le16 tag;855__le16 len;856u8 bss_idx;857u8 tokenid;858u8 dbdcband;859u8 rsv[5];860} __packed abort;861} __packed req = {862.abort = {863.tag = cpu_to_le16(UNI_ROC_ABORT),864.len = cpu_to_le16(sizeof(struct roc_abort_tlv)),865.tokenid = token_id,866.bss_idx = vif->bss_conf.mt76.idx,867.dbdcband = 0xff, /* auto*/868},869};870871return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),872&req, sizeof(req), false);873}874875int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd)876{877struct mt792x_dev *dev = phy->dev;878struct cfg80211_chan_def *chandef = &phy->mt76->chandef;879int freq1 = chandef->center_freq1;880struct {881u8 control_ch;882u8 center_ch;883u8 bw;884u8 tx_streams_num;885u8 rx_streams; /* mask or num */886u8 switch_reason;887u8 band_idx;888u8 center_ch2; /* for 80+80 only */889__le16 cac_case;890u8 channel_band;891u8 rsv0;892__le32 outband_freq;893u8 txpower_drop;894u8 ap_bw;895u8 ap_center_ch;896u8 rsv1[57];897} __packed req = {898.control_ch = chandef->chan->hw_value,899.center_ch = ieee80211_frequency_to_channel(freq1),900.bw = mt76_connac_chan_bw(chandef),901.tx_streams_num = hweight8(phy->mt76->antenna_mask),902.rx_streams = phy->mt76->antenna_mask,903.band_idx = phy != &dev->phy,904};905906if (chandef->chan->band == NL80211_BAND_6GHZ)907req.channel_band = 2;908else909req.channel_band = chandef->chan->band;910911if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||912dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)913req.switch_reason = CH_SWITCH_NORMAL;914else if (phy->mt76->offchannel)915req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;916else if (!cfg80211_reg_can_beacon(dev->mt76.hw->wiphy, chandef,917NL80211_IFTYPE_AP))918req.switch_reason = CH_SWITCH_DFS;919else920req.switch_reason = CH_SWITCH_NORMAL;921922if (cmd == MCU_EXT_CMD(CHANNEL_SWITCH))923req.rx_streams = hweight8(req.rx_streams);924925if (chandef->width == NL80211_CHAN_WIDTH_80P80) {926int freq2 = chandef->center_freq2;927928req.center_ch2 = ieee80211_frequency_to_channel(freq2);929}930931return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);932}933934int mt7921_mcu_set_eeprom(struct mt792x_dev *dev)935{936struct req_hdr {937u8 buffer_mode;938u8 format;939__le16 len;940} __packed req = {941.buffer_mode = EE_MODE_EFUSE,942.format = EE_FORMAT_WHOLE,943};944945return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),946&req, sizeof(req), true);947}948EXPORT_SYMBOL_GPL(mt7921_mcu_set_eeprom);949950int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif)951{952struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;953struct {954struct {955u8 bss_idx;956u8 pad[3];957} __packed hdr;958struct ps_tlv {959__le16 tag;960__le16 len;961u8 ps_state; /* 0: device awake962* 1: static power save963* 2: dynamic power saving964* 3: enter TWT power saving965* 4: leave TWT power saving966*/967u8 pad[3];968} __packed ps;969} __packed ps_req = {970.hdr = {971.bss_idx = mvif->bss_conf.mt76.idx,972},973.ps = {974.tag = cpu_to_le16(UNI_BSS_INFO_PS),975.len = cpu_to_le16(sizeof(struct ps_tlv)),976.ps_state = vif->cfg.ps ? 2 : 0,977},978};979980if (vif->type != NL80211_IFTYPE_STATION)981return -EOPNOTSUPP;982983return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),984&ps_req, sizeof(ps_req), true);985}986987static int988mt7921_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif,989bool enable)990{991struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;992struct {993struct {994u8 bss_idx;995u8 pad[3];996} __packed hdr;997struct bcnft_tlv {998__le16 tag;999__le16 len;1000__le16 bcn_interval;1001u8 dtim_period;1002u8 pad;1003} __packed bcnft;1004} __packed bcnft_req = {1005.hdr = {1006.bss_idx = mvif->bss_conf.mt76.idx,1007},1008.bcnft = {1009.tag = cpu_to_le16(UNI_BSS_INFO_BCNFT),1010.len = cpu_to_le16(sizeof(struct bcnft_tlv)),1011.bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int),1012.dtim_period = vif->bss_conf.dtim_period,1013},1014};10151016if (vif->type != NL80211_IFTYPE_STATION)1017return 0;10181019return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),1020&bcnft_req, sizeof(bcnft_req), true);1021}10221023int1024mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif,1025bool enable)1026{1027struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1028struct {1029u8 bss_idx;1030u8 dtim_period;1031__le16 aid;1032__le16 bcn_interval;1033__le16 atim_window;1034u8 uapsd;1035u8 bmc_delivered_ac;1036u8 bmc_triggered_ac;1037u8 pad;1038} req = {1039.bss_idx = mvif->bss_conf.mt76.idx,1040.aid = cpu_to_le16(vif->cfg.aid),1041.dtim_period = vif->bss_conf.dtim_period,1042.bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int),1043};1044struct {1045u8 bss_idx;1046u8 pad[3];1047} req_hdr = {1048.bss_idx = mvif->bss_conf.mt76.idx,1049};1050int err;10511052err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT),1053&req_hdr, sizeof(req_hdr), false);1054if (err < 0 || !enable)1055return err;10561057return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_CONNECTED),1058&req, sizeof(req), false);1059}10601061int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta,1062struct ieee80211_vif *vif, bool enable,1063enum mt76_sta_info_state state)1064{1065struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1066int rssi = -ewma_rssi_read(&mvif->bss_conf.rssi);1067struct mt76_sta_cmd_info info = {1068.sta = sta,1069.vif = vif,1070.enable = enable,1071.cmd = MCU_UNI_CMD(STA_REC_UPDATE),1072.state = state,1073.offload_fw = true,1074.rcpi = to_rcpi(rssi),1075};1076struct mt792x_sta *msta;10771078msta = sta ? (struct mt792x_sta *)sta->drv_priv : NULL;1079info.wcid = msta ? &msta->deflink.wcid : &mvif->sta.deflink.wcid;1080info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true;10811082return mt76_connac_mcu_sta_cmd(&dev->mphy, &info);1083}10841085int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev,1086struct ieee80211_vif *vif,1087bool enable)1088{1089#define MT7921_FIF_BIT_CLR BIT(1)1090#define MT7921_FIF_BIT_SET BIT(0)1091int err;10921093if (enable) {1094err = mt7921_mcu_uni_bss_bcnft(dev, vif, true);1095if (err)1096return err;10971098err = mt7921_mcu_set_rxfilter(dev, 0,1099MT7921_FIF_BIT_SET,1100MT_WF_RFCR_DROP_OTHER_BEACON);1101if (err)1102return err;11031104return 0;1105}11061107err = mt7921_mcu_set_bss_pm(dev, vif, false);1108if (err)1109return err;11101111err = mt7921_mcu_set_rxfilter(dev, 0,1112MT7921_FIF_BIT_CLR,1113MT_WF_RFCR_DROP_OTHER_BEACON);1114if (err)1115return err;11161117return 0;1118}11191120int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr)1121{1122struct mt7921_txpwr_event *event;1123struct mt7921_txpwr_req req = {1124.dbdc_idx = 0,1125};1126struct sk_buff *skb;1127int ret;11281129ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CE_CMD(GET_TXPWR),1130&req, sizeof(req), true, &skb);1131if (ret)1132return ret;11331134event = (struct mt7921_txpwr_event *)skb->data;1135WARN_ON(skb->len != le16_to_cpu(event->len));1136memcpy(txpwr, &event->txpwr, sizeof(event->txpwr));11371138dev_kfree_skb(skb);11391140return 0;1141}11421143int mt7921_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,1144bool enable)1145{1146struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;1147struct {1148struct {1149u8 band_idx;1150u8 pad[3];1151} __packed hdr;1152struct sniffer_enable_tlv {1153__le16 tag;1154__le16 len;1155u8 enable;1156u8 pad[3];1157} __packed enable;1158} req = {1159.hdr = {1160.band_idx = mvif->band_idx,1161},1162.enable = {1163.tag = cpu_to_le16(0),1164.len = cpu_to_le16(sizeof(struct sniffer_enable_tlv)),1165.enable = enable,1166},1167};11681169return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req),1170true);1171}11721173int mt7921_mcu_config_sniffer(struct mt792x_vif *vif,1174struct ieee80211_chanctx_conf *ctx)1175{1176struct cfg80211_chan_def *chandef = &ctx->def;1177int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;1178static const u8 ch_band[] = {1179[NL80211_BAND_2GHZ] = 1,1180[NL80211_BAND_5GHZ] = 2,1181[NL80211_BAND_6GHZ] = 3,1182};1183static const u8 ch_width[] = {1184[NL80211_CHAN_WIDTH_20_NOHT] = 0,1185[NL80211_CHAN_WIDTH_20] = 0,1186[NL80211_CHAN_WIDTH_40] = 0,1187[NL80211_CHAN_WIDTH_80] = 1,1188[NL80211_CHAN_WIDTH_160] = 2,1189[NL80211_CHAN_WIDTH_80P80] = 3,1190[NL80211_CHAN_WIDTH_5] = 4,1191[NL80211_CHAN_WIDTH_10] = 5,1192[NL80211_CHAN_WIDTH_320] = 6,1193};1194struct {1195struct {1196u8 band_idx;1197u8 pad[3];1198} __packed hdr;1199struct config_tlv {1200__le16 tag;1201__le16 len;1202u16 aid;1203u8 ch_band;1204u8 bw;1205u8 control_ch;1206u8 sco;1207u8 center_ch;1208u8 center_ch2;1209u8 drop_err;1210u8 pad[3];1211} __packed tlv;1212} __packed req = {1213.hdr = {1214.band_idx = vif->bss_conf.mt76.band_idx,1215},1216.tlv = {1217.tag = cpu_to_le16(1),1218.len = cpu_to_le16(sizeof(req.tlv)),1219.control_ch = chandef->chan->hw_value,1220.center_ch = ieee80211_frequency_to_channel(freq1),1221.drop_err = 1,1222},1223};1224if (chandef->chan->band < ARRAY_SIZE(ch_band))1225req.tlv.ch_band = ch_band[chandef->chan->band];1226if (chandef->width < ARRAY_SIZE(ch_width))1227req.tlv.bw = ch_width[chandef->width];12281229if (freq2)1230req.tlv.center_ch2 = ieee80211_frequency_to_channel(freq2);12311232if (req.tlv.control_ch < req.tlv.center_ch)1233req.tlv.sco = 1; /* SCA */1234else if (req.tlv.control_ch > req.tlv.center_ch)1235req.tlv.sco = 3; /* SCB */12361237return mt76_mcu_send_msg(vif->phy->mt76->dev, MCU_UNI_CMD(SNIFFER),1238&req, sizeof(req), true);1239}12401241int1242mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev,1243struct ieee80211_hw *hw,1244struct ieee80211_vif *vif,1245bool enable)1246{1247struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1248struct mt76_wcid *wcid = &dev->mt76.global_wcid;1249struct ieee80211_mutable_offsets offs;1250struct {1251struct req_hdr {1252u8 bss_idx;1253u8 pad[3];1254} __packed hdr;1255struct bcn_content_tlv {1256__le16 tag;1257__le16 len;1258__le16 tim_ie_pos;1259__le16 csa_ie_pos;1260__le16 bcc_ie_pos;1261/* 0: disable beacon offload1262* 1: enable beacon offload1263* 2: update probe respond offload1264*/1265u8 enable;1266/* 0: legacy format (TXD + payload)1267* 1: only cap field IE1268*/1269u8 type;1270__le16 pkt_len;1271u8 pkt[512];1272} __packed beacon_tlv;1273} req = {1274.hdr = {1275.bss_idx = mvif->bss_conf.mt76.idx,1276},1277.beacon_tlv = {1278.tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT),1279.len = cpu_to_le16(sizeof(struct bcn_content_tlv)),1280.enable = enable,1281},1282};1283struct sk_buff *skb;12841285/* support enable/update process only1286* disable flow would be handled in bss stop handler automatically1287*/1288if (!enable)1289return -EOPNOTSUPP;12901291skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0);1292if (!skb)1293return -EINVAL;12941295if (skb->len > 512 - MT_TXD_SIZE) {1296dev_err(dev->mt76.dev, "beacon size limit exceed\n");1297dev_kfree_skb(skb);1298return -EINVAL;1299}13001301mt76_connac2_mac_write_txwi(&dev->mt76, (__le32 *)(req.beacon_tlv.pkt),1302skb, wcid, NULL, 0, 0, BSS_CHANGED_BEACON);1303memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);1304req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);1305req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);13061307if (offs.cntdwn_counter_offs[0]) {1308u16 csa_offs;13091310csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;1311req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs);1312}1313dev_kfree_skb(skb);13141315return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),1316&req, sizeof(req), true);1317}13181319static1320int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,1321enum environment_cap env_cap,1322struct mt7921_clc *clc,1323u8 idx)1324{1325#define CLC_CAP_EVT_EN BIT(0)1326#define CLC_CAP_DTS_EN BIT(1)1327struct sk_buff *skb, *ret_skb = NULL;1328struct {1329u8 ver;1330u8 pad0;1331__le16 len;1332u8 idx;1333u8 env;1334u8 acpi_conf;1335u8 cap;1336u8 alpha2[2];1337u8 type[2];1338u8 env_6g;1339u8 mtcl_conf;1340u8 rsvd[62];1341} __packed req = {1342.ver = 1,1343.idx = idx,1344.env = env_cap,1345.env_6g = dev->phy.power_type,1346.acpi_conf = mt792x_acpi_get_flags(&dev->phy),1347.mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2),1348};1349int ret, valid_cnt = 0;1350u32 buf_len = 0;1351u8 *pos;13521353if (!clc)1354return 0;13551356if (dev->phy.chip_cap & MT792x_CHIP_CAP_CLC_EVT_EN)1357req.cap |= CLC_CAP_EVT_EN;1358if (mt76_find_power_limits_node(&dev->mt76))1359req.cap |= CLC_CAP_DTS_EN;13601361buf_len = le32_to_cpu(clc->len) - sizeof(*clc);1362pos = clc->data;1363while (buf_len > 16) {1364struct mt7921_clc_rule *rule = (struct mt7921_clc_rule *)pos;1365u16 len = le16_to_cpu(rule->len);1366u16 offset = len + sizeof(*rule);13671368pos += offset;1369buf_len -= offset;1370if (rule->alpha2[0] != alpha2[0] ||1371rule->alpha2[1] != alpha2[1])1372continue;13731374memcpy(req.alpha2, rule->alpha2, 2);1375memcpy(req.type, rule->type, 2);13761377req.len = cpu_to_le16(sizeof(req) + len);1378skb = __mt76_mcu_msg_alloc(&dev->mt76, &req,1379le16_to_cpu(req.len),1380sizeof(req), GFP_KERNEL);1381if (!skb)1382return -ENOMEM;1383skb_put_data(skb, rule->data, len);13841385ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,1386MCU_CE_CMD(SET_CLC),1387!!(req.cap & CLC_CAP_EVT_EN),1388&ret_skb);1389if (ret < 0)1390return ret;13911392if (ret_skb) {1393struct mt7921_clc_info_tlv *info;13941395info = (struct mt7921_clc_info_tlv *)(ret_skb->data + 4);1396dev->phy.clc_chan_conf = info->chan_conf;1397dev_kfree_skb(ret_skb);1398}13991400valid_cnt++;1401}14021403if (!valid_cnt)1404return -ENOENT;14051406return 0;1407}14081409int mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,1410enum environment_cap env_cap)1411{1412struct mt792x_phy *phy = (struct mt792x_phy *)&dev->phy;1413int i, ret;14141415/* submit all clc config */1416for (i = 0; i < ARRAY_SIZE(phy->clc); i++) {1417ret = __mt7921_mcu_set_clc(dev, alpha2, env_cap,1418phy->clc[i], i);14191420/* If no country found, set "00" as default */1421if (ret == -ENOENT)1422ret = __mt7921_mcu_set_clc(dev, "00",1423ENVIRON_INDOOR,1424phy->clc[i], i);1425if (ret < 0)1426return ret;1427}1428return 0;1429}14301431int mt7921_mcu_get_temperature(struct mt792x_phy *phy)1432{1433struct mt792x_dev *dev = phy->dev;1434struct {1435u8 ctrl_id;1436u8 action;1437u8 band_idx;1438u8 rsv[5];1439} req = {1440.ctrl_id = THERMAL_SENSOR_TEMP_QUERY,1441.band_idx = phy->mt76->band_idx,1442};14431444return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), &req,1445sizeof(req), true);1446}14471448int mt7921_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy, u8 action)1449{1450struct mt792x_dev *dev = phy->dev;1451struct {1452u8 action;1453u8 value;1454} req = {1455.action = action,1456.value = 0,1457};14581459return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(WF_RF_PIN_CTRL), &req,1460sizeof(req), action ? true : false);1461}14621463int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,1464u8 bit_op, u32 bit_map)1465{1466struct {1467u8 rsv[4];1468u8 mode;1469u8 rsv2[3];1470__le32 fif;1471__le32 bit_map; /* bit_* for bitmap update */1472u8 bit_op;1473u8 pad[51];1474} __packed data = {1475.mode = fif ? 1 : 2,1476.fif = cpu_to_le32(fif),1477.bit_map = cpu_to_le32(bit_map),1478.bit_op = bit_op,1479};14801481return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_RX_FILTER),1482&data, sizeof(data), false);1483}14841485int mt7921_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif)1486{1487struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1488struct {1489u8 enable;1490s8 cqm_rssi_high;1491s8 cqm_rssi_low;1492u8 bss_idx;1493u16 duration;1494u8 rsv2[2];1495} __packed data = {1496.enable = vif->cfg.assoc,1497.cqm_rssi_high = vif->bss_conf.cqm_rssi_thold + vif->bss_conf.cqm_rssi_hyst,1498.cqm_rssi_low = vif->bss_conf.cqm_rssi_thold - vif->bss_conf.cqm_rssi_hyst,1499.bss_idx = mvif->bss_conf.mt76.idx,1500};15011502return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(RSSI_MONITOR),1503&data, sizeof(data), false);1504}150515061507