Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7915/mcu.c
48524 views
// SPDX-License-Identifier: ISC1/* Copyright (C) 2020 MediaTek Inc. */23#include <linux/fs.h>4#include "mt7915.h"5#include "mcu.h"6#include "mac.h"7#include "eeprom.h"89#define fw_name(_dev, name, ...) ({ \10char *_fw; \11switch (mt76_chip(&(_dev)->mt76)) { \12case 0x7915: \13_fw = MT7915_##name; \14break; \15case 0x7981: \16_fw = MT7981_##name; \17break; \18case 0x7986: \19_fw = MT7986_##name##__VA_ARGS__; \20break; \21default: \22_fw = MT7916_##name; \23break; \24} \25_fw; \26})2728#define fw_name_var(_dev, name) (mt7915_check_adie(dev, false) ? \29fw_name(_dev, name) : \30fw_name(_dev, name, _MT7975))3132#define MCU_PATCH_ADDRESS 0x2000003334#define HE_PHY(p, c) u8_get_bits(c, IEEE80211_HE_PHY_##p)35#define HE_MAC(m, c) u8_get_bits(c, IEEE80211_HE_MAC_##m)3637static bool sr_scene_detect = true;38module_param(sr_scene_detect, bool, 0644);39MODULE_PARM_DESC(sr_scene_detect, "Enable firmware scene detection algorithm");4041static u842mt7915_mcu_get_sta_nss(u16 mcs_map)43{44u8 nss;4546for (nss = 8; nss > 0; nss--) {47u8 nss_mcs = (mcs_map >> (2 * (nss - 1))) & 3;4849if (nss_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED)50break;51}5253return nss - 1;54}5556static void57mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,58u16 mcs_map)59{60struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;61struct mt7915_dev *dev = msta->vif->phy->dev;62enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band;63const u16 *mask = msta->vif->bitrate_mask.control[band].he_mcs;64int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;6566for (nss = 0; nss < max_nss; nss++) {67int mcs;6869switch ((mcs_map >> (2 * nss)) & 0x3) {70case IEEE80211_HE_MCS_SUPPORT_0_11:71mcs = GENMASK(11, 0);72break;73case IEEE80211_HE_MCS_SUPPORT_0_9:74mcs = GENMASK(9, 0);75break;76case IEEE80211_HE_MCS_SUPPORT_0_7:77mcs = GENMASK(7, 0);78break;79default:80mcs = 0;81}8283mcs = mcs ? fls(mcs & mask[nss]) - 1 : -1;8485switch (mcs) {86case 0 ... 7:87mcs = IEEE80211_HE_MCS_SUPPORT_0_7;88break;89case 8 ... 9:90mcs = IEEE80211_HE_MCS_SUPPORT_0_9;91break;92case 10 ... 11:93mcs = IEEE80211_HE_MCS_SUPPORT_0_11;94break;95default:96mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;97break;98}99mcs_map &= ~(0x3 << (nss * 2));100mcs_map |= mcs << (nss * 2);101102/* only support 2ss on 160MHz for mt7915 */103if (is_mt7915(&dev->mt76) && nss > 1 &&104sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)105break;106}107108*he_mcs = cpu_to_le16(mcs_map);109}110111static void112mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,113const u16 *mask)114{115struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;116struct mt7915_dev *dev = msta->vif->phy->dev;117u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);118int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;119u16 mcs;120121for (nss = 0; nss < max_nss; nss++, mcs_map >>= 2) {122switch (mcs_map & 0x3) {123case IEEE80211_VHT_MCS_SUPPORT_0_9:124mcs = GENMASK(9, 0);125break;126case IEEE80211_VHT_MCS_SUPPORT_0_8:127mcs = GENMASK(8, 0);128break;129case IEEE80211_VHT_MCS_SUPPORT_0_7:130mcs = GENMASK(7, 0);131break;132default:133mcs = 0;134}135136vht_mcs[nss] = cpu_to_le16(mcs & mask[nss]);137138/* only support 2ss on 160MHz for mt7915 */139if (is_mt7915(&dev->mt76) && nss > 1 &&140sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)141break;142}143}144145static void146mt7915_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs,147const u8 *mask)148{149int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;150151for (nss = 0; nss < max_nss; nss++)152ht_mcs[nss] = sta->deflink.ht_cap.mcs.rx_mask[nss] & mask[nss];153}154155static int156mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,157struct sk_buff *skb, int seq)158{159struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);160struct mt76_connac2_mcu_rxd *rxd;161int ret = 0;162163if (!skb) {164dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",165cmd, seq);166167if (!test_and_set_bit(MT76_MCU_RESET, &dev->mphy.state)) {168dev->recovery.restart = true;169wake_up(&dev->mt76.mcu.wait);170queue_work(dev->mt76.wq, &dev->reset_work);171wake_up(&dev->reset_wait);172}173174return -ETIMEDOUT;175}176177rxd = (struct mt76_connac2_mcu_rxd *)skb->data;178if (seq != rxd->seq &&179!(rxd->eid == MCU_CMD_EXT_CID &&180rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))181return -EAGAIN;182183if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {184skb_pull(skb, sizeof(*rxd) - 4);185ret = *skb->data;186} else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {187skb_pull(skb, sizeof(*rxd) + 4);188ret = le32_to_cpu(*(__le32 *)skb->data);189} else {190skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));191}192193return ret;194}195196static void197mt7915_mcu_set_timeout(struct mt76_dev *mdev, int cmd)198{199mdev->mcu.timeout = 5 * HZ;200201if ((cmd & __MCU_CMD_FIELD_ID) != MCU_CMD_EXT_CID)202return;203204switch (FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd)) {205case MCU_EXT_CMD_THERMAL_CTRL:206case MCU_EXT_CMD_GET_MIB_INFO:207case MCU_EXT_CMD_PHY_STAT_INFO:208case MCU_EXT_CMD_STA_REC_UPDATE:209case MCU_EXT_CMD_BSS_INFO_UPDATE:210mdev->mcu.timeout = 2 * HZ;211return;212case MCU_EXT_CMD_EFUSE_BUFFER_MODE:213mdev->mcu.timeout = 10 * HZ;214return;215default:216break;217}218}219220static int221mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,222int cmd, int *wait_seq)223{224struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);225enum mt76_mcuq_id qid;226227if (cmd == MCU_CMD(FW_SCATTER))228qid = MT_MCUQ_FWDL;229else if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))230qid = MT_MCUQ_WA;231else232qid = MT_MCUQ_WM;233234mt7915_mcu_set_timeout(mdev, cmd);235236return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[qid], skb, 0);237}238239int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)240{241struct {242__le32 args[3];243} req = {244.args = {245cpu_to_le32(a1),246cpu_to_le32(a2),247cpu_to_le32(a3),248},249};250251return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), false);252}253254static void255mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)256{257if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION)258return;259260ieee80211_csa_finish(vif, 0);261}262263static void264mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb)265{266struct mt76_phy *mphy = &dev->mt76.phy;267struct mt7915_mcu_csa_notify *c;268269c = (struct mt7915_mcu_csa_notify *)skb->data;270271if (c->band_idx > MT_BAND1)272return;273274if ((c->band_idx && !dev->phy.mt76->band_idx) &&275dev->mt76.phys[MT_BAND1])276mphy = dev->mt76.phys[MT_BAND1];277278ieee80211_iterate_active_interfaces_atomic(mphy->hw,279IEEE80211_IFACE_ITER_RESUME_ALL,280mt7915_mcu_csa_finish, mphy->hw);281}282283static void284mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb)285{286struct mt76_phy *mphy = &dev->mt76.phy;287struct mt7915_mcu_thermal_notify *t;288struct mt7915_phy *phy;289290t = (struct mt7915_mcu_thermal_notify *)skb->data;291if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE)292return;293294if (t->ctrl.band_idx > MT_BAND1)295return;296297if ((t->ctrl.band_idx && !dev->phy.mt76->band_idx) &&298dev->mt76.phys[MT_BAND1])299mphy = dev->mt76.phys[MT_BAND1];300301phy = mphy->priv;302phy->throttle_state = t->ctrl.duty.duty_cycle;303}304305static void306mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)307{308struct mt76_phy *mphy = &dev->mt76.phy;309struct mt7915_mcu_rdd_report *r;310u32 sku;311312r = (struct mt7915_mcu_rdd_report *)skb->data;313314switch (r->rdd_idx) {315case MT_RDD_IDX_BAND0:316break;317case MT_RDD_IDX_BAND1:318sku = mt7915_check_adie(dev, true);319/* the main phy is bound to band 1 for this sku */320if (is_mt7986(&dev->mt76) &&321(sku == MT7975_ONE_ADIE || sku == MT7976_ONE_ADIE))322break;323mphy = dev->mt76.phys[MT_BAND1];324break;325case MT_RDD_IDX_BACKGROUND:326if (!dev->rdd2_phy)327return;328mphy = dev->rdd2_phy->mt76;329break;330default:331dev_err(dev->mt76.dev, "Unknown RDD idx %d\n", r->rdd_idx);332return;333}334335if (!mphy)336return;337338if (r->rdd_idx == MT_RDD_IDX_BACKGROUND)339cfg80211_background_radar_event(mphy->hw->wiphy,340&dev->rdd2_chandef,341GFP_ATOMIC);342else343ieee80211_radar_detected(mphy->hw, NULL);344dev->hw_pattern++;345}346347static void348mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb)349{350struct mt76_connac2_mcu_rxd *rxd;351int len = skb->len - sizeof(*rxd);352const char *data, *type;353354rxd = (struct mt76_connac2_mcu_rxd *)skb->data;355data = (char *)&rxd[1];356357switch (rxd->s2d_index) {358case 0:359#if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS)360if (mt7915_debugfs_rx_log(dev, data, len))361return;362#endif363364type = "WM";365break;366case 2:367type = "WA";368break;369default:370type = "unknown";371break;372}373374wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, len, data);375}376377static void378mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)379{380if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)381return;382383ieee80211_color_change_finish(vif, 0);384}385386static void387mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb)388{389struct mt76_phy *mphy = &dev->mt76.phy;390struct mt7915_mcu_bcc_notify *b;391392b = (struct mt7915_mcu_bcc_notify *)skb->data;393394if (b->band_idx > MT_BAND1)395return;396397if ((b->band_idx && !dev->phy.mt76->band_idx) &&398dev->mt76.phys[MT_BAND1])399mphy = dev->mt76.phys[MT_BAND1];400401ieee80211_iterate_active_interfaces_atomic(mphy->hw,402IEEE80211_IFACE_ITER_RESUME_ALL,403mt7915_mcu_cca_finish, mphy->hw);404}405406static void407mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)408{409struct mt76_connac2_mcu_rxd *rxd;410411rxd = (struct mt76_connac2_mcu_rxd *)skb->data;412switch (rxd->ext_eid) {413case MCU_EXT_EVENT_THERMAL_PROTECT:414mt7915_mcu_rx_thermal_notify(dev, skb);415break;416case MCU_EXT_EVENT_RDD_REPORT:417mt7915_mcu_rx_radar_detected(dev, skb);418break;419case MCU_EXT_EVENT_CSA_NOTIFY:420mt7915_mcu_rx_csa_notify(dev, skb);421break;422case MCU_EXT_EVENT_FW_LOG_2_HOST:423mt7915_mcu_rx_log_message(dev, skb);424break;425case MCU_EXT_EVENT_BCC_NOTIFY:426mt7915_mcu_rx_bcc_notify(dev, skb);427break;428default:429break;430}431}432433static void434mt7915_mcu_rx_unsolicited_event(struct mt7915_dev *dev, struct sk_buff *skb)435{436struct mt76_connac2_mcu_rxd *rxd;437438rxd = (struct mt76_connac2_mcu_rxd *)skb->data;439switch (rxd->eid) {440case MCU_EVENT_EXT:441mt7915_mcu_rx_ext_event(dev, skb);442break;443default:444break;445}446dev_kfree_skb(skb);447}448449void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)450{451struct mt76_connac2_mcu_rxd *rxd;452453rxd = (struct mt76_connac2_mcu_rxd *)skb->data;454if ((rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||455rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||456rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||457rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||458rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||459!rxd->seq) &&460!(rxd->eid == MCU_CMD_EXT_CID &&461rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))462mt7915_mcu_rx_unsolicited_event(dev, skb);463else464mt76_mcu_rx_event(&dev->mt76, skb);465}466467static struct tlv *468mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len,469__le16 *sub_ntlv, __le16 *len)470{471struct tlv *ptlv, tlv = {472.tag = cpu_to_le16(sub_tag),473.len = cpu_to_le16(sub_len),474};475476ptlv = skb_put_zero(skb, sub_len);477memcpy(ptlv, &tlv, sizeof(tlv));478479le16_add_cpu(sub_ntlv, 1);480le16_add_cpu(len, sub_len);481482return ptlv;483}484485/** bss info **/486struct mt7915_he_obss_narrow_bw_ru_data {487bool tolerated;488};489490static void mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,491struct cfg80211_bss *bss,492void *_data)493{494struct mt7915_he_obss_narrow_bw_ru_data *data = _data;495const struct element *elem;496497rcu_read_lock();498elem = ieee80211_bss_get_elem(bss, WLAN_EID_EXT_CAPABILITY);499500if (!elem || elem->datalen <= 10 ||501!(elem->data[10] &502WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT))503data->tolerated = false;504505rcu_read_unlock();506}507508static bool mt7915_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw,509struct ieee80211_vif *vif)510{511struct mt7915_he_obss_narrow_bw_ru_data iter_data = {512.tolerated = true,513};514515if (!(vif->bss_conf.chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR))516return false;517518cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chanreq.oper,519mt7915_check_he_obss_narrow_bw_ru_iter,520&iter_data);521522/*523* If there is at least one AP on radar channel that cannot524* tolerate 26-tone RU UL OFDMA transmissions using HE TB PPDU.525*/526return !iter_data.tolerated;527}528529static void530mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,531struct mt7915_phy *phy)532{533struct cfg80211_chan_def *chandef = &phy->mt76->chandef;534struct bss_info_rf_ch *ch;535struct tlv *tlv;536int freq1 = chandef->center_freq1;537538tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_RF_CH, sizeof(*ch));539540ch = (struct bss_info_rf_ch *)tlv;541ch->pri_ch = chandef->chan->hw_value;542ch->center_ch0 = ieee80211_frequency_to_channel(freq1);543ch->bw = mt76_connac_chan_bw(chandef);544545if (chandef->width == NL80211_CHAN_WIDTH_80P80) {546int freq2 = chandef->center_freq2;547548ch->center_ch1 = ieee80211_frequency_to_channel(freq2);549}550551if (vif->bss_conf.he_support && vif->type == NL80211_IFTYPE_STATION) {552struct mt76_phy *mphy = phy->mt76;553554ch->he_ru26_block =555mt7915_check_he_obss_narrow_bw_ru(mphy->hw, vif);556ch->he_all_disable = false;557} else {558ch->he_all_disable = true;559}560}561562static void563mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,564struct mt7915_phy *phy)565{566int max_nss = hweight8(phy->mt76->antenna_mask);567struct bss_info_ra *ra;568struct tlv *tlv;569570tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_RA, sizeof(*ra));571572ra = (struct bss_info_ra *)tlv;573ra->op_mode = vif->type == NL80211_IFTYPE_AP;574ra->adhoc_en = vif->type == NL80211_IFTYPE_ADHOC;575ra->short_preamble = true;576ra->tx_streams = max_nss;577ra->rx_streams = max_nss;578ra->algo = 4;579ra->train_up_rule = 2;580ra->train_up_high_thres = 110;581ra->train_up_rule_rssi = -70;582ra->low_traffic_thres = 2;583ra->phy_cap = cpu_to_le32(0xfdf);584ra->interval = cpu_to_le32(500);585ra->fast_interval = cpu_to_le32(100);586}587588static void589mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,590struct mt7915_phy *phy)591{592#define DEFAULT_HE_PE_DURATION 4593#define DEFAULT_HE_DURATION_RTS_THRES 1023594const struct ieee80211_sta_he_cap *cap;595struct bss_info_he *he;596struct tlv *tlv;597598cap = mt76_connac_get_he_phy_cap(phy->mt76, vif);599600tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he));601602he = (struct bss_info_he *)tlv;603he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext;604if (!he->he_pe_duration)605he->he_pe_duration = DEFAULT_HE_PE_DURATION;606607he->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th);608if (!he->he_rts_thres)609he->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES);610611he->max_nss_mcs[CMD_HE_MCS_BW80] = cap->he_mcs_nss_supp.tx_mcs_80;612he->max_nss_mcs[CMD_HE_MCS_BW160] = cap->he_mcs_nss_supp.tx_mcs_160;613he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;614}615616static void617mt7915_mcu_bss_hw_amsdu_tlv(struct sk_buff *skb)618{619#define TXD_CMP_MAP1 GENMASK(15, 0)620#define TXD_CMP_MAP2 (GENMASK(31, 0) & ~BIT(23))621struct bss_info_hw_amsdu *amsdu;622struct tlv *tlv;623624tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HW_AMSDU, sizeof(*amsdu));625626amsdu = (struct bss_info_hw_amsdu *)tlv;627amsdu->cmp_bitmap_0 = cpu_to_le32(TXD_CMP_MAP1);628amsdu->cmp_bitmap_1 = cpu_to_le32(TXD_CMP_MAP2);629amsdu->trig_thres = cpu_to_le16(2);630amsdu->enable = true;631}632633static void634mt7915_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7915_phy *phy)635{636struct bss_info_bmc_rate *bmc;637struct cfg80211_chan_def *chandef = &phy->mt76->chandef;638enum nl80211_band band = chandef->chan->band;639struct tlv *tlv;640641tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BMC_RATE, sizeof(*bmc));642643bmc = (struct bss_info_bmc_rate *)tlv;644if (band == NL80211_BAND_2GHZ) {645bmc->short_preamble = true;646} else {647bmc->bc_trans = cpu_to_le16(0x2000);648bmc->mc_trans = cpu_to_le16(0x2080);649}650}651652static int653mt7915_mcu_muar_config(struct mt7915_phy *phy, struct ieee80211_vif *vif,654bool bssid, bool enable)655{656struct mt7915_dev *dev = phy->dev;657struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;658u32 idx = mvif->mt76.omac_idx - REPEATER_BSSID_START;659u32 mask = phy->omac_mask >> 32 & ~BIT(idx);660const u8 *addr = vif->addr;661struct {662u8 mode;663u8 force_clear;664u8 clear_bitmap[8];665u8 entry_count;666u8 write;667u8 band;668669u8 index;670u8 bssid;671u8 addr[ETH_ALEN];672} __packed req = {673.mode = !!mask || enable,674.entry_count = 1,675.write = 1,676.band = phy->mt76->band_idx,677.index = idx * 2 + bssid,678};679680if (bssid)681addr = vif->bss_conf.bssid;682683if (enable)684ether_addr_copy(req.addr, addr);685686return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MUAR_UPDATE), &req,687sizeof(req), true);688}689690int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,691struct ieee80211_vif *vif, int enable)692{693struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;694struct mt7915_dev *dev = phy->dev;695struct sk_buff *skb;696697if (mvif->mt76.omac_idx >= REPEATER_BSSID_START) {698mt7915_mcu_muar_config(phy, vif, false, enable);699mt7915_mcu_muar_config(phy, vif, true, enable);700}701702skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL,703MT7915_BSS_UPDATE_MAX_SIZE);704if (IS_ERR(skb))705return PTR_ERR(skb);706707/* bss_omac must be first */708if (enable)709mt76_connac_mcu_bss_omac_tlv(skb, vif);710711mt76_connac_mcu_bss_basic_tlv(skb, vif, NULL, phy->mt76,712mvif->sta.wcid.idx, enable);713714if (vif->type == NL80211_IFTYPE_MONITOR)715goto out;716717if (enable) {718mt7915_mcu_bss_rfch_tlv(skb, vif, phy);719mt7915_mcu_bss_bmc_tlv(skb, phy);720mt7915_mcu_bss_ra_tlv(skb, vif, phy);721mt7915_mcu_bss_hw_amsdu_tlv(skb);722723if (vif->bss_conf.he_support)724mt7915_mcu_bss_he_tlv(skb, vif, phy);725726if (mvif->mt76.omac_idx >= EXT_BSSID_START &&727mvif->mt76.omac_idx < REPEATER_BSSID_START)728mt76_connac_mcu_bss_ext_tlv(skb, &mvif->mt76);729}730out:731return mt76_mcu_skb_send_msg(&dev->mt76, skb,732MCU_EXT_CMD(BSS_INFO_UPDATE), true);733}734735/** starec & wtbl **/736int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev,737struct ieee80211_ampdu_params *params,738bool enable)739{740struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv;741struct mt7915_vif *mvif = msta->vif;742int ret;743744mt76_worker_disable(&dev->mt76.tx_worker);745if (enable && !params->amsdu)746msta->wcid.amsdu = false;747ret = mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,748MCU_EXT_CMD(STA_REC_UPDATE),749enable, true);750mt76_worker_enable(&dev->mt76.tx_worker);751752return ret;753}754755int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,756struct ieee80211_ampdu_params *params,757bool enable)758{759struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv;760struct mt7915_vif *mvif = msta->vif;761762return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,763MCU_EXT_CMD(STA_REC_UPDATE),764enable, false);765}766767static void768mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,769struct ieee80211_vif *vif)770{771struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;772struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;773struct ieee80211_he_mcs_nss_supp mcs_map;774struct sta_rec_he *he;775struct tlv *tlv;776u32 cap = 0;777778if (!sta->deflink.he_cap.has_he)779return;780781tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE, sizeof(*he));782783he = (struct sta_rec_he *)tlv;784785if (elem->mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_HTC_HE)786cap |= STA_REC_HE_CAP_HTC;787788if (elem->mac_cap_info[2] & IEEE80211_HE_MAC_CAP2_BSR)789cap |= STA_REC_HE_CAP_BSR;790791if (elem->mac_cap_info[3] & IEEE80211_HE_MAC_CAP3_OMI_CONTROL)792cap |= STA_REC_HE_CAP_OM;793794if (elem->mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU)795cap |= STA_REC_HE_CAP_AMSDU_IN_AMPDU;796797if (elem->mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_BQR)798cap |= STA_REC_HE_CAP_BQR;799800if (elem->phy_cap_info[0] &801(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G |802IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))803cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;804805if (mvif->cap.he_ldpc &&806(elem->phy_cap_info[1] &807IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))808cap |= STA_REC_HE_CAP_LDPC;809810if (elem->phy_cap_info[1] &811IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US)812cap |= STA_REC_HE_CAP_SU_PPDU_1LTF_8US_GI;813814if (elem->phy_cap_info[2] &815IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US)816cap |= STA_REC_HE_CAP_NDP_4LTF_3DOT2MS_GI;817818if (elem->phy_cap_info[2] &819IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ)820cap |= STA_REC_HE_CAP_LE_EQ_80M_TX_STBC;821822if (elem->phy_cap_info[2] &823IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)824cap |= STA_REC_HE_CAP_LE_EQ_80M_RX_STBC;825826if (elem->phy_cap_info[6] &827IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB)828cap |= STA_REC_HE_CAP_TRIG_CQI_FK;829830if (elem->phy_cap_info[6] &831IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE)832cap |= STA_REC_HE_CAP_PARTIAL_BW_EXT_RANGE;833834if (elem->phy_cap_info[7] &835IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI)836cap |= STA_REC_HE_CAP_SU_MU_PPDU_4LTF_8US_GI;837838if (elem->phy_cap_info[7] &839IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ)840cap |= STA_REC_HE_CAP_GT_80M_TX_STBC;841842if (elem->phy_cap_info[7] &843IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ)844cap |= STA_REC_HE_CAP_GT_80M_RX_STBC;845846if (elem->phy_cap_info[8] &847IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI)848cap |= STA_REC_HE_CAP_ER_SU_PPDU_4LTF_8US_GI;849850if (elem->phy_cap_info[8] &851IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI)852cap |= STA_REC_HE_CAP_ER_SU_PPDU_1LTF_8US_GI;853854if (elem->phy_cap_info[9] &855IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU)856cap |= STA_REC_HE_CAP_TX_1024QAM_UNDER_RU242;857858if (elem->phy_cap_info[9] &859IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU)860cap |= STA_REC_HE_CAP_RX_1024QAM_UNDER_RU242;861862he->he_cap = cpu_to_le32(cap);863864mcs_map = sta->deflink.he_cap.he_mcs_nss_supp;865switch (sta->deflink.bandwidth) {866case IEEE80211_STA_RX_BW_160:867if (elem->phy_cap_info[0] &868IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)869mt7915_mcu_set_sta_he_mcs(sta,870&he->max_nss_mcs[CMD_HE_MCS_BW8080],871le16_to_cpu(mcs_map.rx_mcs_80p80));872873mt7915_mcu_set_sta_he_mcs(sta,874&he->max_nss_mcs[CMD_HE_MCS_BW160],875le16_to_cpu(mcs_map.rx_mcs_160));876fallthrough;877default:878mt7915_mcu_set_sta_he_mcs(sta,879&he->max_nss_mcs[CMD_HE_MCS_BW80],880le16_to_cpu(mcs_map.rx_mcs_80));881break;882}883884he->t_frame_dur =885HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]);886he->max_ampdu_exp =887HE_MAC(CAP3_MAX_AMPDU_LEN_EXP_MASK, elem->mac_cap_info[3]);888889he->bw_set =890HE_PHY(CAP0_CHANNEL_WIDTH_SET_MASK, elem->phy_cap_info[0]);891he->device_class =892HE_PHY(CAP1_DEVICE_CLASS_A, elem->phy_cap_info[1]);893he->punc_pream_rx =894HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);895896he->dcm_tx_mode =897HE_PHY(CAP3_DCM_MAX_CONST_TX_MASK, elem->phy_cap_info[3]);898he->dcm_tx_max_nss =899HE_PHY(CAP3_DCM_MAX_TX_NSS_2, elem->phy_cap_info[3]);900he->dcm_rx_mode =901HE_PHY(CAP3_DCM_MAX_CONST_RX_MASK, elem->phy_cap_info[3]);902he->dcm_rx_max_nss =903HE_PHY(CAP3_DCM_MAX_RX_NSS_2, elem->phy_cap_info[3]);904he->dcm_rx_max_nss =905HE_PHY(CAP8_DCM_MAX_RU_MASK, elem->phy_cap_info[8]);906907he->pkt_ext = 2;908}909910static void911mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,912struct ieee80211_sta *sta, struct ieee80211_vif *vif)913{914struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;915struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;916struct sta_rec_muru *muru;917struct tlv *tlv;918919if (vif->type != NL80211_IFTYPE_STATION &&920vif->type != NL80211_IFTYPE_AP)921return;922923tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));924925muru = (struct sta_rec_muru *)tlv;926927muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||928mvif->cap.vht_mu_ebfer ||929mvif->cap.vht_mu_ebfee;930if (!is_mt7915(&dev->mt76))931muru->cfg.mimo_ul_en = true;932muru->cfg.ofdma_dl_en = true;933934if (sta->deflink.vht_cap.vht_supported)935muru->mimo_dl.vht_mu_bfee =936!!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);937938if (!sta->deflink.he_cap.has_he)939return;940941muru->mimo_dl.partial_bw_dl_mimo =942HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]);943944muru->mimo_ul.full_ul_mimo =945HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]);946muru->mimo_ul.partial_ul_mimo =947HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]);948949muru->ofdma_dl.punc_pream_rx =950HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);951muru->ofdma_dl.he_20m_in_40m_2g =952HE_PHY(CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G, elem->phy_cap_info[8]);953muru->ofdma_dl.he_20m_in_160m =954HE_PHY(CAP8_20MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);955muru->ofdma_dl.he_80m_in_160m =956HE_PHY(CAP8_80MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);957958muru->ofdma_ul.t_frame_dur =959HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]);960muru->ofdma_ul.mu_cascading =961HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);962muru->ofdma_ul.uo_ra =963HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);964muru->ofdma_ul.rx_ctrl_frame_to_mbss =965HE_MAC(CAP3_RX_CTRL_FRAME_TO_MULTIBSS, elem->mac_cap_info[3]);966}967968static void969mt7915_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)970{971struct sta_rec_ht *ht;972struct tlv *tlv;973974if (!sta->deflink.ht_cap.ht_supported)975return;976977tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht));978979ht = (struct sta_rec_ht *)tlv;980ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap);981}982983static void984mt7915_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)985{986struct sta_rec_vht *vht;987struct tlv *tlv;988989if (!sta->deflink.vht_cap.vht_supported)990return;991992tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht));993994vht = (struct sta_rec_vht *)tlv;995vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap);996vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map;997vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map;998}9991000static void1001mt7915_mcu_sta_amsdu_tlv(struct mt7915_dev *dev, struct sk_buff *skb,1002struct ieee80211_vif *vif, struct ieee80211_sta *sta)1003{1004struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;1005struct sta_rec_amsdu *amsdu;1006struct tlv *tlv;10071008if (vif->type != NL80211_IFTYPE_STATION &&1009vif->type != NL80211_IFTYPE_AP)1010return;10111012if (!sta->deflink.agg.max_amsdu_len)1013return;10141015tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu));1016amsdu = (struct sta_rec_amsdu *)tlv;1017amsdu->max_amsdu_num = 8;1018amsdu->amsdu_en = true;1019msta->wcid.amsdu = true;10201021switch (sta->deflink.agg.max_amsdu_len) {1022case IEEE80211_MAX_MPDU_LEN_VHT_11454:1023if (!is_mt7915(&dev->mt76)) {1024amsdu->max_mpdu_size =1025IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;1026return;1027}1028fallthrough;1029case IEEE80211_MAX_MPDU_LEN_HT_7935:1030case IEEE80211_MAX_MPDU_LEN_VHT_7991:1031amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;1032return;1033default:1034amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;1035return;1036}1037}10381039static int1040mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb,1041struct ieee80211_vif *vif, struct ieee80211_sta *sta)1042{1043struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1044struct mt7915_sta *msta;1045struct wtbl_req_hdr *wtbl_hdr;1046struct mt76_wcid *wcid;1047struct tlv *tlv;10481049msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta;1050wcid = sta ? &msta->wcid : NULL;10511052tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv));1053wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,1054WTBL_RESET_AND_SET, tlv,1055&skb);1056if (IS_ERR(wtbl_hdr))1057return PTR_ERR(wtbl_hdr);10581059mt76_connac_mcu_wtbl_generic_tlv(&dev->mt76, skb, vif, sta, tlv,1060wtbl_hdr);1061mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr);1062if (sta)1063mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv,1064wtbl_hdr, mvif->cap.ht_ldpc,1065mvif->cap.vht_ldpc);10661067return 0;1068}10691070static inline bool1071mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,1072struct ieee80211_sta *sta, bool bfee)1073{1074struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1075int sts = hweight16(phy->mt76->chainmask);10761077if (vif->type != NL80211_IFTYPE_STATION &&1078vif->type != NL80211_IFTYPE_AP)1079return false;10801081if (!bfee && sts < 2)1082return false;10831084if (sta->deflink.he_cap.has_he) {1085struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;10861087if (bfee)1088return mvif->cap.he_su_ebfee &&1089HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);1090else1091return mvif->cap.he_su_ebfer &&1092HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);1093}10941095if (sta->deflink.vht_cap.vht_supported) {1096u32 cap = sta->deflink.vht_cap.cap;10971098if (bfee)1099return mvif->cap.vht_su_ebfee &&1100(cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);1101else1102return mvif->cap.vht_su_ebfer &&1103(cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);1104}11051106return false;1107}11081109static void1110mt7915_mcu_sta_sounding_rate(struct sta_rec_bf *bf)1111{1112bf->sounding_phy = MT_PHY_TYPE_OFDM;1113bf->ndp_rate = 0; /* mcs0 */1114bf->ndpa_rate = MT7915_CFEND_RATE_DEFAULT; /* ofdm 24m */1115bf->rept_poll_rate = MT7915_CFEND_RATE_DEFAULT; /* ofdm 24m */1116}11171118static void1119mt7915_mcu_sta_bfer_ht(struct ieee80211_sta *sta, struct mt7915_phy *phy,1120struct sta_rec_bf *bf)1121{1122struct ieee80211_mcs_info *mcs = &sta->deflink.ht_cap.mcs;1123u8 n = 0;11241125bf->tx_mode = MT_PHY_TYPE_HT;11261127if ((mcs->tx_params & IEEE80211_HT_MCS_TX_RX_DIFF) &&1128(mcs->tx_params & IEEE80211_HT_MCS_TX_DEFINED))1129n = FIELD_GET(IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK,1130mcs->tx_params);1131else if (mcs->rx_mask[3])1132n = 3;1133else if (mcs->rx_mask[2])1134n = 2;1135else if (mcs->rx_mask[1])1136n = 1;11371138bf->nrow = hweight8(phy->mt76->chainmask) - 1;1139bf->ncol = min_t(u8, bf->nrow, n);1140bf->ibf_ncol = n;1141}11421143static void1144mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy,1145struct sta_rec_bf *bf, bool explicit)1146{1147struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap;1148struct ieee80211_sta_vht_cap *vc = &phy->mt76->sband_5g.sband.vht_cap;1149u16 mcs_map = le16_to_cpu(pc->vht_mcs.rx_mcs_map);1150u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);1151u8 tx_ant = hweight8(phy->mt76->chainmask) - 1;11521153bf->tx_mode = MT_PHY_TYPE_VHT;11541155if (explicit) {1156u8 sts, snd_dim;11571158mt7915_mcu_sta_sounding_rate(bf);11591160sts = FIELD_GET(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK,1161pc->cap);1162snd_dim = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,1163vc->cap);1164bf->nrow = min_t(u8, min_t(u8, snd_dim, sts), tx_ant);1165bf->ncol = min_t(u8, nss_mcs, bf->nrow);1166bf->ibf_ncol = bf->ncol;11671168if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)1169bf->nrow = 1;1170} else {1171bf->nrow = tx_ant;1172bf->ncol = min_t(u8, nss_mcs, bf->nrow);1173bf->ibf_ncol = nss_mcs;11741175if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)1176bf->ibf_nrow = 1;1177}1178}11791180static void1181mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif,1182struct mt7915_phy *phy, struct sta_rec_bf *bf)1183{1184struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap;1185struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;1186const struct ieee80211_sta_he_cap *vc =1187mt76_connac_get_he_phy_cap(phy->mt76, vif);1188const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem;1189u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80);1190u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);1191u8 snd_dim, sts;11921193bf->tx_mode = MT_PHY_TYPE_HE_SU;11941195mt7915_mcu_sta_sounding_rate(bf);11961197bf->trigger_su = HE_PHY(CAP6_TRIG_SU_BEAMFORMING_FB,1198pe->phy_cap_info[6]);1199bf->trigger_mu = HE_PHY(CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB,1200pe->phy_cap_info[6]);1201snd_dim = HE_PHY(CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,1202ve->phy_cap_info[5]);1203sts = HE_PHY(CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK,1204pe->phy_cap_info[4]);1205bf->nrow = min_t(u8, snd_dim, sts);1206bf->ncol = min_t(u8, nss_mcs, bf->nrow);1207bf->ibf_ncol = bf->ncol;12081209if (sta->deflink.bandwidth != IEEE80211_STA_RX_BW_160)1210return;12111212/* go over for 160MHz and 80p80 */1213if (pe->phy_cap_info[0] &1214IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) {1215mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_160);1216nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);12171218bf->ncol_gt_bw80 = nss_mcs;1219}12201221if (pe->phy_cap_info[0] &1222IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {1223mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80p80);1224nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);12251226if (bf->ncol_gt_bw80)1227bf->ncol_gt_bw80 = min_t(u8, bf->ncol_gt_bw80, nss_mcs);1228else1229bf->ncol_gt_bw80 = nss_mcs;1230}12311232snd_dim = HE_PHY(CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK,1233ve->phy_cap_info[5]);1234sts = HE_PHY(CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK,1235pe->phy_cap_info[4]);12361237bf->nrow_gt_bw80 = min_t(int, snd_dim, sts);1238}12391240static void1241mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,1242struct ieee80211_vif *vif, struct ieee80211_sta *sta)1243{1244struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1245struct mt7915_phy *phy = mvif->phy;1246int tx_ant = hweight8(phy->mt76->chainmask) - 1;1247struct sta_rec_bf *bf;1248struct tlv *tlv;1249static const u8 matrix[4][4] = {1250{0, 0, 0, 0},1251{1, 1, 0, 0}, /* 2x1, 2x2, 2x3, 2x4 */1252{2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */1253{3, 5, 6, 0} /* 4x1, 4x2, 4x3, 4x4 */1254};1255bool ebf;12561257if (!(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))1258return;12591260ebf = mt7915_is_ebf_supported(phy, vif, sta, false);1261if (!ebf && !dev->ibf)1262return;12631264tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf));1265bf = (struct sta_rec_bf *)tlv;12661267/* he: eBF only, in accordance with spec1268* vht: support eBF and iBF1269* ht: iBF only, since mac80211 lacks of eBF support1270*/1271if (sta->deflink.he_cap.has_he && ebf)1272mt7915_mcu_sta_bfer_he(sta, vif, phy, bf);1273else if (sta->deflink.vht_cap.vht_supported)1274mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf);1275else if (sta->deflink.ht_cap.ht_supported)1276mt7915_mcu_sta_bfer_ht(sta, phy, bf);1277else1278return;12791280bf->bf_cap = ebf ? ebf : dev->ibf << 1;1281bf->bw = sta->deflink.bandwidth;1282bf->ibf_dbw = sta->deflink.bandwidth;1283bf->ibf_nrow = tx_ant;12841285if (!ebf && sta->deflink.bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol)1286bf->ibf_timeout = 0x48;1287else1288bf->ibf_timeout = 0x18;12891290if (ebf && bf->nrow != tx_ant)1291bf->mem_20m = matrix[tx_ant][bf->ncol];1292else1293bf->mem_20m = matrix[bf->nrow][bf->ncol];12941295switch (sta->deflink.bandwidth) {1296case IEEE80211_STA_RX_BW_160:1297case IEEE80211_STA_RX_BW_80:1298bf->mem_total = bf->mem_20m * 2;1299break;1300case IEEE80211_STA_RX_BW_40:1301bf->mem_total = bf->mem_20m;1302break;1303case IEEE80211_STA_RX_BW_20:1304default:1305break;1306}1307}13081309static void1310mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb,1311struct ieee80211_vif *vif, struct ieee80211_sta *sta)1312{1313struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1314struct mt7915_phy *phy = mvif->phy;1315int tx_ant = hweight8(phy->mt76->chainmask) - 1;1316struct sta_rec_bfee *bfee;1317struct tlv *tlv;1318u8 nrow = 0;13191320if (!(sta->deflink.vht_cap.vht_supported || sta->deflink.he_cap.has_he))1321return;13221323if (!mt7915_is_ebf_supported(phy, vif, sta, true))1324return;13251326tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BFEE, sizeof(*bfee));1327bfee = (struct sta_rec_bfee *)tlv;13281329if (sta->deflink.he_cap.has_he) {1330struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;13311332nrow = HE_PHY(CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,1333pe->phy_cap_info[5]);1334} else if (sta->deflink.vht_cap.vht_supported) {1335struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap;13361337nrow = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,1338pc->cap);1339}13401341/* reply with identity matrix to avoid 2x2 BF negative gain */1342bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);1343}13441345static enum mcu_mmps_mode1346mt7915_mcu_get_mmps_mode(enum ieee80211_smps_mode smps)1347{1348switch (smps) {1349case IEEE80211_SMPS_OFF:1350return MCU_MMPS_DISABLE;1351case IEEE80211_SMPS_STATIC:1352return MCU_MMPS_STATIC;1353case IEEE80211_SMPS_DYNAMIC:1354return MCU_MMPS_DYNAMIC;1355default:1356return MCU_MMPS_DISABLE;1357}1358}13591360int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,1361struct ieee80211_vif *vif,1362struct ieee80211_sta *sta,1363void *data, u32 field)1364{1365struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1366struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;1367struct sta_phy *phy = data;1368struct sta_rec_ra_fixed *ra;1369struct sk_buff *skb;1370struct tlv *tlv;13711372skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,1373&msta->wcid);1374if (IS_ERR(skb))1375return PTR_ERR(skb);13761377tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));1378ra = (struct sta_rec_ra_fixed *)tlv;13791380switch (field) {1381case RATE_PARAM_AUTO:1382break;1383case RATE_PARAM_FIXED:1384case RATE_PARAM_FIXED_MCS:1385case RATE_PARAM_FIXED_GI:1386case RATE_PARAM_FIXED_HE_LTF:1387if (phy)1388ra->phy = *phy;1389break;1390case RATE_PARAM_MMPS_UPDATE:1391ra->mmps_mode = mt7915_mcu_get_mmps_mode(sta->deflink.smps_mode);1392break;1393case RATE_PARAM_SPE_UPDATE:1394ra->spe_idx = *(u8 *)data;1395break;1396default:1397break;1398}1399ra->field = cpu_to_le32(field);14001401return mt76_mcu_skb_send_msg(&dev->mt76, skb,1402MCU_EXT_CMD(STA_REC_UPDATE), true);1403}14041405int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,1406struct ieee80211_sta *sta)1407{1408struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1409struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;1410struct wtbl_req_hdr *wtbl_hdr;1411struct tlv *sta_wtbl;1412struct sk_buff *skb;1413int ret;14141415skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,1416&msta->wcid);1417if (IS_ERR(skb))1418return PTR_ERR(skb);14191420sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,1421sizeof(struct tlv));1422wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,1423WTBL_SET, sta_wtbl, &skb);1424if (IS_ERR(wtbl_hdr))1425return PTR_ERR(wtbl_hdr);14261427mt76_connac_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr);14281429ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,1430MCU_EXT_CMD(STA_REC_UPDATE), true);1431if (ret)1432return ret;14331434return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, NULL,1435RATE_PARAM_MMPS_UPDATE);1436}14371438static int1439mt7915_mcu_set_spe_idx(struct mt7915_dev *dev, struct ieee80211_vif *vif,1440struct ieee80211_sta *sta)1441{1442struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1443struct mt76_phy *mphy = mvif->phy->mt76;1444u8 spe_idx = mt76_connac_spe_idx(mphy->antenna_mask);14451446return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &spe_idx,1447RATE_PARAM_SPE_UPDATE);1448}14491450static int1451mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev,1452struct ieee80211_vif *vif,1453struct ieee80211_sta *sta)1454{1455struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1456struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;1457struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;1458enum nl80211_band band = chandef->chan->band;1459struct sta_phy phy = {};1460int ret, nrates = 0;14611462#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \1463do { \1464u8 i, gi = mask->control[band]._gi; \1465gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \1466for (i = 0; i <= sta->deflink.bandwidth; i++) { \1467phy.sgi |= gi << (i << (_he)); \1468phy.he_ltf |= mask->control[band].he_ltf << (i << (_he));\1469} \1470for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \1471if (!mask->control[band]._mcs[i]) \1472continue; \1473nrates += hweight16(mask->control[band]._mcs[i]); \1474phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \1475if (_ht) \1476phy.mcs += 8 * i; \1477} \1478} while (0)14791480if (sta->deflink.he_cap.has_he) {1481__sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);1482} else if (sta->deflink.vht_cap.vht_supported) {1483__sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);1484} else if (sta->deflink.ht_cap.ht_supported) {1485__sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);1486} else {1487nrates = hweight32(mask->control[band].legacy);1488phy.mcs = ffs(mask->control[band].legacy) - 1;1489}1490#undef __sta_phy_bitrate_mask_check14911492/* fall back to auto rate control */1493if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&1494mask->control[band].he_gi == GENMASK(7, 0) &&1495mask->control[band].he_ltf == GENMASK(7, 0) &&1496nrates != 1)1497return 0;14981499/* fixed single rate */1500if (nrates == 1) {1501ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,1502RATE_PARAM_FIXED_MCS);1503if (ret)1504return ret;1505}15061507/* fixed GI */1508if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||1509mask->control[band].he_gi != GENMASK(7, 0)) {1510struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;1511u32 addr;15121513/* firmware updates only TXCMD but doesn't take WTBL into1514* account, so driver should update here to reflect the1515* actual txrate hardware sends out.1516*/1517addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);1518if (sta->deflink.he_cap.has_he)1519mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);1520else1521mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);15221523ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,1524RATE_PARAM_FIXED_GI);1525if (ret)1526return ret;1527}15281529/* fixed HE_LTF */1530if (mask->control[band].he_ltf != GENMASK(7, 0)) {1531ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,1532RATE_PARAM_FIXED_HE_LTF);1533if (ret)1534return ret;1535}15361537return mt7915_mcu_set_spe_idx(dev, vif, sta);1538}15391540static void1541mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,1542struct ieee80211_vif *vif, struct ieee80211_sta *sta)1543{1544struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1545struct mt76_phy *mphy = mvif->phy->mt76;1546struct cfg80211_chan_def *chandef = &mphy->chandef;1547struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;1548enum nl80211_band band = chandef->chan->band;1549struct sta_rec_ra *ra;1550struct tlv *tlv;1551u32 supp_rate = sta->deflink.supp_rates[band];1552u32 cap = sta->wme ? STA_CAP_WMM : 0;15531554tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));1555ra = (struct sta_rec_ra *)tlv;15561557ra->valid = true;1558ra->auto_rate = true;1559ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, &sta->deflink);1560ra->channel = chandef->chan->hw_value;1561ra->bw = sta->deflink.bandwidth;1562ra->phy.bw = sta->deflink.bandwidth;1563ra->mmps_mode = mt7915_mcu_get_mmps_mode(sta->deflink.smps_mode);15641565if (supp_rate) {1566supp_rate &= mask->control[band].legacy;1567ra->rate_len = hweight32(supp_rate);15681569if (band == NL80211_BAND_2GHZ) {1570ra->supp_mode = MODE_CCK;1571ra->supp_cck_rate = supp_rate & GENMASK(3, 0);15721573if (ra->rate_len > 4) {1574ra->supp_mode |= MODE_OFDM;1575ra->supp_ofdm_rate = supp_rate >> 4;1576}1577} else {1578ra->supp_mode = MODE_OFDM;1579ra->supp_ofdm_rate = supp_rate;1580}1581}15821583if (sta->deflink.ht_cap.ht_supported) {1584ra->supp_mode |= MODE_HT;1585ra->af = sta->deflink.ht_cap.ampdu_factor;1586ra->ht_gf = !!(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);15871588cap |= STA_CAP_HT;1589if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20)1590cap |= STA_CAP_SGI_20;1591if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40)1592cap |= STA_CAP_SGI_40;1593if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)1594cap |= STA_CAP_TX_STBC;1595if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)1596cap |= STA_CAP_RX_STBC;1597if (mvif->cap.ht_ldpc &&1598(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))1599cap |= STA_CAP_LDPC;16001601mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs,1602mask->control[band].ht_mcs);1603ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;1604}16051606if (sta->deflink.vht_cap.vht_supported) {1607u8 af;16081609ra->supp_mode |= MODE_VHT;1610af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,1611sta->deflink.vht_cap.cap);1612ra->af = max_t(u8, ra->af, af);16131614cap |= STA_CAP_VHT;1615if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80)1616cap |= STA_CAP_VHT_SGI_80;1617if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160)1618cap |= STA_CAP_VHT_SGI_160;1619if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC)1620cap |= STA_CAP_VHT_TX_STBC;1621if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)1622cap |= STA_CAP_VHT_RX_STBC;1623if (mvif->cap.vht_ldpc &&1624(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))1625cap |= STA_CAP_VHT_LDPC;16261627mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs,1628mask->control[band].vht_mcs);1629}16301631if (sta->deflink.he_cap.has_he) {1632ra->supp_mode |= MODE_HE;1633cap |= STA_CAP_HE;16341635if (sta->deflink.he_6ghz_capa.capa)1636ra->af = le16_get_bits(sta->deflink.he_6ghz_capa.capa,1637IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);1638}16391640ra->sta_cap = cpu_to_le32(cap);1641}16421643int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,1644struct ieee80211_sta *sta, bool changed)1645{1646struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1647struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;1648struct sk_buff *skb;1649int ret;16501651skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,1652&msta->wcid);1653if (IS_ERR(skb))1654return PTR_ERR(skb);16551656/* firmware rc algorithm refers to sta_rec_he for HE control.1657* once dev->rc_work changes the settings driver should also1658* update sta_rec_he here.1659*/1660if (changed)1661mt7915_mcu_sta_he_tlv(skb, sta, vif);16621663/* sta_rec_ra accommodates BW, NSS and only MCS range format1664* i.e 0-{7,8,9} for VHT.1665*/1666mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);16671668ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,1669MCU_EXT_CMD(STA_REC_UPDATE), true);1670if (ret)1671return ret;16721673/* sta_rec_ra_fixed accommodates single rate, (HE)GI and HE_LTE,1674* and updates as peer fixed rate parameters, which overrides1675* sta_rec_ra and firmware rate control algorithm.1676*/1677return mt7915_mcu_add_rate_ctrl_fixed(dev, vif, sta);1678}16791680static int1681mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif,1682struct ieee80211_sta *sta)1683{1684#define MT_STA_BSS_GROUP 11685struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1686struct mt7915_sta *msta;1687struct {1688__le32 action;1689u8 wlan_idx_lo;1690u8 status;1691u8 wlan_idx_hi;1692u8 rsv0[5];1693__le32 val;1694u8 rsv1[8];1695} __packed req = {1696.action = cpu_to_le32(MT_STA_BSS_GROUP),1697.val = cpu_to_le32(mvif->mt76.idx % 16),1698};16991700msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta;1701req.wlan_idx_lo = to_wcid_lo(msta->wcid.idx);1702req.wlan_idx_hi = to_wcid_hi(msta->wcid.idx);17031704return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_DRR_CTRL), &req,1705sizeof(req), true);1706}17071708int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,1709struct ieee80211_sta *sta, int conn_state, bool newly)1710{1711struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1712struct ieee80211_link_sta *link_sta;1713struct mt7915_sta *msta;1714struct sk_buff *skb;1715int ret;17161717msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta;1718link_sta = sta ? &sta->deflink : NULL;17191720skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,1721&msta->wcid);1722if (IS_ERR(skb))1723return PTR_ERR(skb);17241725/* starec basic */1726mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, &vif->bss_conf, link_sta,1727conn_state, newly);1728/* tag order is in accordance with firmware dependency. */1729if (sta && conn_state != CONN_STATE_DISCONNECT) {1730/* starec bfer */1731mt7915_mcu_sta_bfer_tlv(dev, skb, vif, sta);1732/* starec ht */1733mt7915_mcu_sta_ht_tlv(skb, sta);1734/* starec vht */1735mt7915_mcu_sta_vht_tlv(skb, sta);1736/* starec uapsd */1737mt76_connac_mcu_sta_uapsd(skb, vif, sta);1738}17391740if (newly || conn_state != CONN_STATE_DISCONNECT) {1741ret = mt7915_mcu_sta_wtbl_tlv(dev, skb, vif, sta);1742if (ret) {1743dev_kfree_skb(skb);1744return ret;1745}1746}17471748if (conn_state == CONN_STATE_DISCONNECT)1749goto out;17501751if (sta) {1752/* starec amsdu */1753mt7915_mcu_sta_amsdu_tlv(dev, skb, vif, sta);1754/* starec he */1755mt7915_mcu_sta_he_tlv(skb, sta, vif);1756/* starec muru */1757mt7915_mcu_sta_muru_tlv(dev, skb, sta, vif);1758/* starec bfee */1759mt7915_mcu_sta_bfee_tlv(dev, skb, vif, sta);1760}17611762ret = mt7915_mcu_add_group(dev, vif, sta);1763if (ret) {1764dev_kfree_skb(skb);1765return ret;1766}1767out:1768ret = mt76_connac_mcu_sta_wed_update(&dev->mt76, skb);1769if (ret)1770return ret;17711772return mt76_mcu_skb_send_msg(&dev->mt76, skb,1773MCU_EXT_CMD(STA_REC_UPDATE), true);1774}17751776int mt7915_mcu_wed_enable_rx_stats(struct mt7915_dev *dev)1777{1778#ifdef CONFIG_NET_MEDIATEK_SOC_WED1779struct mtk_wed_device *wed = &dev->mt76.mmio.wed;1780struct {1781__le32 args[2];1782} req = {1783.args[0] = cpu_to_le32(1),1784.args[1] = cpu_to_le32(6),1785};17861787return mtk_wed_device_update_msg(wed, MTK_WED_WO_CMD_RXCNT_CTRL,1788&req, sizeof(req));1789#else1790return 0;1791#endif1792}17931794int mt7915_mcu_add_dev_info(struct mt7915_phy *phy,1795struct ieee80211_vif *vif, bool enable)1796{1797struct mt7915_dev *dev = phy->dev;1798struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1799struct {1800struct req_hdr {1801u8 omac_idx;1802u8 band_idx;1803__le16 tlv_num;1804u8 is_tlv_append;1805u8 rsv[3];1806} __packed hdr;1807struct req_tlv {1808__le16 tag;1809__le16 len;1810u8 active;1811u8 band_idx;1812u8 omac_addr[ETH_ALEN];1813} __packed tlv;1814} data = {1815.hdr = {1816.omac_idx = mvif->mt76.omac_idx,1817.band_idx = mvif->mt76.band_idx,1818.tlv_num = cpu_to_le16(1),1819.is_tlv_append = 1,1820},1821.tlv = {1822.tag = cpu_to_le16(DEV_INFO_ACTIVE),1823.len = cpu_to_le16(sizeof(struct req_tlv)),1824.active = enable,1825.band_idx = mvif->mt76.band_idx,1826},1827};18281829if (mvif->mt76.omac_idx >= REPEATER_BSSID_START)1830return mt7915_mcu_muar_config(phy, vif, false, enable);18311832memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN);1833return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(DEV_INFO_UPDATE),1834&data, sizeof(data), true);1835}18361837static void1838mt7915_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,1839struct sk_buff *skb, struct bss_info_bcn *bcn,1840struct ieee80211_mutable_offsets *offs)1841{1842struct bss_info_bcn_cntdwn *info;1843struct tlv *tlv;1844int sub_tag;18451846if (!offs->cntdwn_counter_offs[0])1847return;18481849sub_tag = vif->bss_conf.csa_active ? BSS_INFO_BCN_CSA : BSS_INFO_BCN_BCC;1850tlv = mt7915_mcu_add_nested_subtlv(rskb, sub_tag, sizeof(*info),1851&bcn->sub_ntlv, &bcn->len);1852info = (struct bss_info_bcn_cntdwn *)tlv;1853info->cnt = skb->data[offs->cntdwn_counter_offs[0]];1854}18551856static void1857mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,1858struct ieee80211_vif *vif, struct bss_info_bcn *bcn,1859struct ieee80211_mutable_offsets *offs)1860{1861struct bss_info_bcn_mbss *mbss;1862const struct element *elem;1863struct tlv *tlv;18641865if (!vif->bss_conf.bssid_indicator)1866return;18671868tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_MBSSID,1869sizeof(*mbss), &bcn->sub_ntlv,1870&bcn->len);18711872mbss = (struct bss_info_bcn_mbss *)tlv;1873mbss->offset[0] = cpu_to_le16(offs->tim_offset);1874mbss->bitmap = cpu_to_le32(1);18751876for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID,1877&skb->data[offs->mbssid_off],1878skb->len - offs->mbssid_off) {1879const struct element *sub_elem;18801881if (elem->datalen < 2)1882continue;18831884for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {1885const struct ieee80211_bssid_index *idx;1886const u8 *idx_ie;18871888if (sub_elem->id || sub_elem->datalen < 4)1889continue; /* not a valid BSS profile */18901891/* Find WLAN_EID_MULTI_BSSID_IDX1892* in the merged nontransmitted profile1893*/1894idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,1895sub_elem->data,1896sub_elem->datalen);1897if (!idx_ie || idx_ie[1] < sizeof(*idx))1898continue;18991900#if defined(__linux__)1901idx = (void *)(idx_ie + 2);1902#elif defined(__FreeBSD__)1903idx = (const void *)(idx_ie + 2);1904#endif1905if (!idx->bssid_index || idx->bssid_index > 31)1906continue;19071908mbss->offset[idx->bssid_index] =1909cpu_to_le16(idx_ie - skb->data);1910mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index));1911}1912}1913}19141915static void1916mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,1917struct sk_buff *rskb, struct sk_buff *skb,1918struct bss_info_bcn *bcn,1919struct ieee80211_mutable_offsets *offs)1920{1921struct mt76_wcid *wcid = &dev->mt76.global_wcid;1922struct bss_info_bcn_cont *cont;1923struct tlv *tlv;1924u8 *buf;1925int len = sizeof(*cont) + MT_TXD_SIZE + skb->len;19261927len = (len & 0x3) ? ((len | 0x3) + 1) : len;1928tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT,1929len, &bcn->sub_ntlv, &bcn->len);19301931cont = (struct bss_info_bcn_cont *)tlv;1932cont->pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);1933cont->tim_ofs = cpu_to_le16(offs->tim_offset);19341935if (offs->cntdwn_counter_offs[0]) {1936u16 offset = offs->cntdwn_counter_offs[0];19371938if (vif->bss_conf.csa_active)1939cont->csa_ofs = cpu_to_le16(offset - 4);1940if (vif->bss_conf.color_change_active)1941cont->bcc_ofs = cpu_to_le16(offset - 3);1942}19431944buf = (u8 *)tlv + sizeof(*cont);1945mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,19460, BSS_CHANGED_BEACON);1947memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);1948}19491950int1951mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,1952u32 changed)1953{1954#define OFFLOAD_TX_MODE_SU BIT(0)1955#define OFFLOAD_TX_MODE_MU BIT(1)1956struct ieee80211_hw *hw = mt76_hw(dev);1957struct mt7915_phy *phy = mt7915_hw_phy(hw);1958struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1959struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;1960enum nl80211_band band = chandef->chan->band;1961struct mt76_wcid *wcid = &dev->mt76.global_wcid;1962struct bss_info_bcn *bcn;1963struct bss_info_inband_discovery *discov;1964struct ieee80211_tx_info *info;1965struct sk_buff *rskb, *skb = NULL;1966struct tlv *tlv, *sub_tlv;1967bool ext_phy = phy != &dev->phy;1968u8 *buf, interval;1969int len;19701971if (vif->bss_conf.nontransmitted)1972return 0;19731974rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL,1975MT7915_MAX_BSS_OFFLOAD_SIZE);1976if (IS_ERR(rskb))1977return PTR_ERR(rskb);19781979tlv = mt76_connac_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));1980bcn = (struct bss_info_bcn *)tlv;1981bcn->enable = true;19821983if (changed & BSS_CHANGED_FILS_DISCOVERY) {1984interval = vif->bss_conf.fils_discovery.max_interval;1985skb = ieee80211_get_fils_discovery_tmpl(hw, vif);1986} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&1987vif->bss_conf.unsol_bcast_probe_resp_interval) {1988interval = vif->bss_conf.unsol_bcast_probe_resp_interval;1989skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);1990}19911992if (!skb) {1993dev_kfree_skb(rskb);1994return -EINVAL;1995}19961997info = IEEE80211_SKB_CB(skb);1998info->control.vif = vif;1999info->band = band;2000info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);20012002len = sizeof(*discov) + MT_TXD_SIZE + skb->len;2003len = (len & 0x3) ? ((len | 0x3) + 1) : len;20042005if (skb->len > MT7915_MAX_BEACON_SIZE) {2006dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");2007dev_kfree_skb(rskb);2008dev_kfree_skb(skb);2009return -EINVAL;2010}20112012sub_tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,2013len, &bcn->sub_ntlv, &bcn->len);2014discov = (struct bss_info_inband_discovery *)sub_tlv;2015discov->tx_mode = OFFLOAD_TX_MODE_SU;2016/* 0: UNSOL PROBE RESP, 1: FILS DISCOV */2017discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);2018discov->tx_interval = interval;2019discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);2020discov->enable = !!interval;20212022buf = (u8 *)sub_tlv + sizeof(*discov);20232024mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,20250, changed);2026memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);20272028dev_kfree_skb(skb);20292030return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,2031MCU_EXT_CMD(BSS_INFO_UPDATE), true);2032}20332034int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,2035int en, u32 changed)2036{2037struct mt7915_dev *dev = mt7915_hw_dev(hw);2038struct mt7915_phy *phy = mt7915_hw_phy(hw);2039struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;2040struct ieee80211_mutable_offsets offs;2041struct ieee80211_tx_info *info;2042struct sk_buff *skb, *rskb;2043struct tlv *tlv;2044struct bss_info_bcn *bcn;2045int len = MT7915_MAX_BSS_OFFLOAD_SIZE;2046bool ext_phy = phy != &dev->phy;20472048if (vif->bss_conf.nontransmitted)2049return 0;20502051rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,2052NULL, len);2053if (IS_ERR(rskb))2054return PTR_ERR(rskb);20552056tlv = mt76_connac_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));2057bcn = (struct bss_info_bcn *)tlv;2058bcn->enable = en;20592060if (!en)2061goto out;20622063skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);2064if (!skb) {2065dev_kfree_skb(rskb);2066return -EINVAL;2067}20682069if (skb->len > MT7915_MAX_BEACON_SIZE) {2070dev_err(dev->mt76.dev, "Bcn size limit exceed\n");2071dev_kfree_skb(rskb);2072dev_kfree_skb(skb);2073return -EINVAL;2074}20752076info = IEEE80211_SKB_CB(skb);2077info->hw_queue = FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);20782079mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs);2080mt7915_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);2081mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);2082dev_kfree_skb(skb);20832084out:2085return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,2086MCU_EXT_CMD(BSS_INFO_UPDATE), true);2087}20882089static int mt7915_driver_own(struct mt7915_dev *dev, u8 band)2090{2091mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(band), MT_TOP_LPCR_HOST_DRV_OWN);2092if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND(band),2093MT_TOP_LPCR_HOST_FW_OWN_STAT, 0, 500)) {2094dev_err(dev->mt76.dev, "Timeout for driver own\n");2095return -EIO;2096}20972098/* clear irq when the driver own success */2099mt76_wr(dev, MT_TOP_LPCR_HOST_BAND_IRQ_STAT(band),2100MT_TOP_LPCR_HOST_BAND_STAT);21012102return 0;2103}21042105static int2106mt7915_firmware_state(struct mt7915_dev *dev, bool wa)2107{2108u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE,2109wa ? FW_STATE_RDY : FW_STATE_FW_DOWNLOAD);21102111if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE,2112state, 1000)) {2113dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");2114return -EIO;2115}2116return 0;2117}21182119static int mt7915_load_firmware(struct mt7915_dev *dev)2120{2121int ret;21222123/* Release Semaphore if taken by previous failed attempt */2124ret = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);2125if (ret != PATCH_REL_SEM_SUCCESS) {2126dev_err(dev->mt76.dev, "Could not release semaphore\n");2127/* Continue anyways */2128}21292130/* Always restart MCU firmware */2131mt76_connac_mcu_restart(&dev->mt76);21322133/* Check if MCU is ready */2134ret = mt7915_firmware_state(dev, false);2135if (ret) {2136dev_err(dev->mt76.dev, "Firmware did not enter download state\n");2137return ret;2138}21392140ret = mt76_connac2_load_patch(&dev->mt76, fw_name_var(dev, ROM_PATCH));2141if (ret)2142return ret;21432144ret = mt76_connac2_load_ram(&dev->mt76, fw_name_var(dev, FIRMWARE_WM),2145fw_name(dev, FIRMWARE_WA));2146if (ret)2147return ret;21482149ret = mt7915_firmware_state(dev, true);2150if (ret)2151return ret;21522153mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);21542155dev_dbg(dev->mt76.dev, "Firmware init done\n");21562157return 0;2158}21592160int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl)2161{2162struct {2163u8 ctrl_val;2164u8 pad[3];2165} data = {2166.ctrl_val = ctrl2167};21682169if (type == MCU_FW_LOG_WA)2170return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(FW_LOG_2_HOST),2171&data, sizeof(data), true);21722173return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(FW_LOG_2_HOST), &data,2174sizeof(data), true);2175}21762177int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level)2178{2179struct {2180u8 ver;2181u8 pad;2182__le16 len;2183u8 level;2184u8 rsv[3];2185__le32 module_idx;2186} data = {2187.module_idx = cpu_to_le32(module),2188.level = level,2189};21902191return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(FW_DBG_CTRL), &data,2192sizeof(data), false);2193}21942195int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enabled)2196{2197struct {2198__le32 cmd;2199u8 enable;2200} data = {2201.cmd = cpu_to_le32(MURU_SET_TXC_TX_STATS_EN),2202.enable = enabled,2203};22042205return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &data,2206sizeof(data), false);2207}22082209int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy)2210{2211struct mt7915_dev *dev = phy->dev;2212struct sk_buff *skb;2213struct mt7915_mcu_muru_stats *mu_stats;2214int ret;22152216struct {2217__le32 cmd;2218u8 band_idx;2219} req = {2220.cmd = cpu_to_le32(MURU_GET_TXC_TX_STATS),2221.band_idx = phy->mt76->band_idx,2222};22232224ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL),2225&req, sizeof(req), true, &skb);2226if (ret)2227return ret;22282229mu_stats = (struct mt7915_mcu_muru_stats *)(skb->data);22302231/* accumulate stats, these are clear-on-read */2232#define __dl_u32(s) phy->mib.dl_##s += le32_to_cpu(mu_stats->dl.s)2233#define __ul_u32(s) phy->mib.ul_##s += le32_to_cpu(mu_stats->ul.s)2234__dl_u32(cck_cnt);2235__dl_u32(ofdm_cnt);2236__dl_u32(htmix_cnt);2237__dl_u32(htgf_cnt);2238__dl_u32(vht_su_cnt);2239__dl_u32(vht_2mu_cnt);2240__dl_u32(vht_3mu_cnt);2241__dl_u32(vht_4mu_cnt);2242__dl_u32(he_su_cnt);2243__dl_u32(he_2ru_cnt);2244__dl_u32(he_2mu_cnt);2245__dl_u32(he_3ru_cnt);2246__dl_u32(he_3mu_cnt);2247__dl_u32(he_4ru_cnt);2248__dl_u32(he_4mu_cnt);2249__dl_u32(he_5to8ru_cnt);2250__dl_u32(he_9to16ru_cnt);2251__dl_u32(he_gtr16ru_cnt);22522253__ul_u32(hetrig_su_cnt);2254__ul_u32(hetrig_2ru_cnt);2255__ul_u32(hetrig_3ru_cnt);2256__ul_u32(hetrig_4ru_cnt);2257__ul_u32(hetrig_5to8ru_cnt);2258__ul_u32(hetrig_9to16ru_cnt);2259__ul_u32(hetrig_gtr16ru_cnt);2260__ul_u32(hetrig_2mu_cnt);2261__ul_u32(hetrig_3mu_cnt);2262__ul_u32(hetrig_4mu_cnt);2263#undef __dl_u322264#undef __ul_u3222652266dev_kfree_skb(skb);22672268return 0;2269}22702271static int mt7915_mcu_set_mwds(struct mt7915_dev *dev, bool enabled)2272{2273struct {2274u8 enable;2275u8 _rsv[3];2276} __packed req = {2277.enable = enabled2278};22792280return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(MWDS_SUPPORT), &req,2281sizeof(req), false);2282}22832284int mt7915_mcu_set_muru_ctrl(struct mt7915_dev *dev, u32 cmd, u32 val)2285{2286struct {2287__le32 cmd;2288u8 val[4];2289} __packed req = {2290.cmd = cpu_to_le32(cmd),2291};22922293put_unaligned_le32(val, req.val);22942295return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req,2296sizeof(req), false);2297}22982299static int2300mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)2301{2302#define RX_AIRTIME_FEATURE_CTRL 12303#define RX_AIRTIME_BITWISE_CTRL 22304#define RX_AIRTIME_CLEAR_EN 12305struct {2306__le16 field;2307__le16 sub_field;2308__le32 set_status;2309__le32 get_status;2310u8 _rsv[12];23112312bool airtime_en;2313bool mibtime_en;2314bool earlyend_en;2315u8 _rsv1[9];23162317bool airtime_clear;2318bool mibtime_clear;2319u8 _rsv2[98];2320} __packed req = {2321.field = cpu_to_le16(RX_AIRTIME_BITWISE_CTRL),2322.sub_field = cpu_to_le16(RX_AIRTIME_CLEAR_EN),2323.airtime_clear = true,2324};2325int ret;23262327ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_AIRTIME_CTRL), &req,2328sizeof(req), true);2329if (ret)2330return ret;23312332req.field = cpu_to_le16(RX_AIRTIME_FEATURE_CTRL);2333req.sub_field = cpu_to_le16(RX_AIRTIME_CLEAR_EN);2334req.airtime_en = true;23352336return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_AIRTIME_CTRL), &req,2337sizeof(req), true);2338}23392340static int mt7915_red_set_watermark(struct mt7915_dev *dev)2341{2342#define RED_GLOBAL_TOKEN_WATERMARK 22343struct {2344__le32 args[3];2345u8 cmd;2346u8 version;2347u8 __rsv1[4];2348__le16 len;2349__le16 high_mark;2350__le16 low_mark;2351u8 __rsv2[12];2352} __packed req = {2353.args[0] = cpu_to_le32(MCU_WA_PARAM_RED_SETTING),2354.cmd = RED_GLOBAL_TOKEN_WATERMARK,2355.len = cpu_to_le16(sizeof(req) - sizeof(req.args)),2356.high_mark = cpu_to_le16(MT7915_HW_TOKEN_SIZE - 256),2357.low_mark = cpu_to_le16(MT7915_HW_TOKEN_SIZE - 256 - 1536),2358};23592360return mt76_mcu_send_msg(&dev->mt76, MCU_WA_PARAM_CMD(SET), &req,2361sizeof(req), false);2362}23632364static int mt7915_mcu_set_red(struct mt7915_dev *dev, bool enabled)2365{2366#define RED_DISABLE 02367#define RED_BY_WA_ENABLE 22368int ret;2369u32 red_type = enabled ? RED_BY_WA_ENABLE : RED_DISABLE;2370__le32 req = cpu_to_le32(red_type);23712372if (enabled) {2373ret = mt7915_red_set_watermark(dev);2374if (ret < 0)2375return ret;2376}23772378ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RED_ENABLE), &req,2379sizeof(req), false);2380if (ret < 0)2381return ret;23822383return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),2384MCU_WA_PARAM_RED, enabled, 0);2385}23862387int mt7915_mcu_init_firmware(struct mt7915_dev *dev)2388{2389int ret;23902391/* force firmware operation mode into normal state,2392* which should be set before firmware download stage.2393*/2394mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);23952396ret = mt7915_driver_own(dev, 0);2397if (ret)2398return ret;2399/* set driver own for band1 when two hif exist */2400if (dev->hif2) {2401ret = mt7915_driver_own(dev, 1);2402if (ret)2403return ret;2404}24052406ret = mt7915_load_firmware(dev);2407if (ret)2408return ret;24092410set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);2411ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, 0);2412if (ret)2413return ret;24142415ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, 0);2416if (ret)2417return ret;24182419mt76_connac_mcu_del_wtbl_all(&dev->mt76);24202421if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&2422is_mt7915(&dev->mt76)) ||2423!mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))2424mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);24252426ret = mt7915_mcu_set_mwds(dev, 1);2427if (ret)2428return ret;24292430ret = mt7915_mcu_set_muru_ctrl(dev, MURU_SET_PLATFORM_TYPE,2431MURU_PLATFORM_TYPE_PERF_LEVEL_2);2432if (ret)2433return ret;24342435ret = mt7915_mcu_init_rx_airtime(dev);2436if (ret)2437return ret;24382439return mt7915_mcu_set_red(dev, mtk_wed_device_active(&dev->mt76.mmio.wed));2440}24412442int mt7915_mcu_init(struct mt7915_dev *dev)2443{2444static const struct mt76_mcu_ops mt7915_mcu_ops = {2445.max_retry = 1,2446.headroom = sizeof(struct mt76_connac2_mcu_txd),2447.mcu_skb_prepare_msg = mt76_connac2_mcu_fill_message,2448.mcu_skb_send_msg = mt7915_mcu_send_message,2449.mcu_parse_response = mt7915_mcu_parse_response,2450};24512452dev->mt76.mcu_ops = &mt7915_mcu_ops;24532454return mt7915_mcu_init_firmware(dev);2455}24562457void mt7915_mcu_exit(struct mt7915_dev *dev)2458{2459mt76_connac_mcu_restart(&dev->mt76);2460if (mt7915_firmware_state(dev, false)) {2461dev_err(dev->mt76.dev, "Failed to exit mcu\n");2462goto out;2463}24642465mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(0), MT_TOP_LPCR_HOST_FW_OWN);2466if (dev->hif2)2467mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(1),2468MT_TOP_LPCR_HOST_FW_OWN);2469out:2470skb_queue_purge(&dev->mt76.mcu.res_q);2471}24722473static int2474mt7915_mcu_set_rx_hdr_trans_blacklist(struct mt7915_dev *dev, int band)2475{2476struct {2477u8 operation;2478u8 count;2479u8 _rsv[2];2480u8 index;2481u8 enable;2482__le16 etype;2483} req = {2484.operation = 1,2485.count = 1,2486.enable = 1,2487.etype = cpu_to_le16(ETH_P_PAE),2488};24892490return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS),2491&req, sizeof(req), false);2492}24932494int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band,2495bool enable, bool hdr_trans)2496{2497struct {2498u8 operation;2499u8 enable;2500u8 check_bssid;2501u8 insert_vlan;2502u8 remove_vlan;2503u8 tid;2504u8 mode;2505u8 rsv;2506} __packed req_trans = {2507.enable = hdr_trans,2508};2509struct {2510u8 enable;2511u8 band;2512u8 rsv[2];2513} __packed req_mac = {2514.enable = enable,2515.band = band,2516};2517int ret;25182519ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS),2520&req_trans, sizeof(req_trans), false);2521if (ret)2522return ret;25232524if (hdr_trans)2525mt7915_mcu_set_rx_hdr_trans_blacklist(dev, band);25262527return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MAC_INIT_CTRL),2528&req_mac, sizeof(req_mac), true);2529}25302531int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *param)2532{2533struct mt7915_mcu_tx *req = (struct mt7915_mcu_tx *)param;2534u8 num = req->total;2535size_t len = sizeof(*req) -2536(IEEE80211_NUM_ACS - num) * sizeof(struct edca);25372538return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EDCA_UPDATE), req,2539len, true);2540}25412542int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif)2543{2544#define TX_CMD_MODE 12545struct mt7915_mcu_tx req = {2546.valid = true,2547.mode = TX_CMD_MODE,2548.total = IEEE80211_NUM_ACS,2549};2550struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;2551int ac;25522553for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {2554struct ieee80211_tx_queue_params *q = &mvif->queue_params[ac];2555struct edca *e = &req.edca[ac];25562557e->set = WMM_PARAM_SET;2558e->queue = ac + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;2559e->aifs = q->aifs;2560e->txop = cpu_to_le16(q->txop);25612562if (q->cw_min)2563e->cw_min = fls(q->cw_min);2564else2565e->cw_min = 5;25662567if (q->cw_max)2568e->cw_max = cpu_to_le16(fls(q->cw_max));2569else2570e->cw_max = cpu_to_le16(10);2571}25722573return mt7915_mcu_update_edca(dev, &req);2574}25752576int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val)2577{2578struct {2579__le32 tag;2580__le16 min_lpn;2581u8 rsv[2];2582} __packed req = {2583.tag = cpu_to_le32(0x1),2584.min_lpn = cpu_to_le16(val),2585};25862587return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_TH), &req,2588sizeof(req), true);2589}25902591int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,2592const struct mt7915_dfs_pulse *pulse)2593{2594struct {2595__le32 tag;25962597__le32 max_width; /* us */2598__le32 max_pwr; /* dbm */2599__le32 min_pwr; /* dbm */2600__le32 min_stgr_pri; /* us */2601__le32 max_stgr_pri; /* us */2602__le32 min_cr_pri; /* us */2603__le32 max_cr_pri; /* us */2604} __packed req = {2605.tag = cpu_to_le32(0x3),26062607#define __req_field(field) .field = cpu_to_le32(pulse->field)2608__req_field(max_width),2609__req_field(max_pwr),2610__req_field(min_pwr),2611__req_field(min_stgr_pri),2612__req_field(max_stgr_pri),2613__req_field(min_cr_pri),2614__req_field(max_cr_pri),2615#undef __req_field2616};26172618return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_TH), &req,2619sizeof(req), true);2620}26212622int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,2623const struct mt7915_dfs_pattern *pattern)2624{2625struct {2626__le32 tag;2627__le16 radar_type;26282629u8 enb;2630u8 stgr;2631u8 min_crpn;2632u8 max_crpn;2633u8 min_crpr;2634u8 min_pw;2635__le32 min_pri;2636__le32 max_pri;2637u8 max_pw;2638u8 min_crbn;2639u8 max_crbn;2640u8 min_stgpn;2641u8 max_stgpn;2642u8 min_stgpr;2643u8 rsv[2];2644__le32 min_stgpr_diff;2645} __packed req = {2646.tag = cpu_to_le32(0x2),2647.radar_type = cpu_to_le16(index),26482649#define __req_field_u8(field) .field = pattern->field2650#define __req_field_u32(field) .field = cpu_to_le32(pattern->field)2651__req_field_u8(enb),2652__req_field_u8(stgr),2653__req_field_u8(min_crpn),2654__req_field_u8(max_crpn),2655__req_field_u8(min_crpr),2656__req_field_u8(min_pw),2657__req_field_u32(min_pri),2658__req_field_u32(max_pri),2659__req_field_u8(max_pw),2660__req_field_u8(min_crbn),2661__req_field_u8(max_crbn),2662__req_field_u8(min_stgpn),2663__req_field_u8(max_stgpn),2664__req_field_u8(min_stgpr),2665__req_field_u32(min_stgpr_diff),2666#undef __req_field_u82667#undef __req_field_u322668};26692670return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_TH), &req,2671sizeof(req), true);2672}26732674static int2675mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy,2676struct cfg80211_chan_def *chandef,2677int cmd)2678{2679struct mt7915_dev *dev = phy->dev;2680struct mt76_phy *mphy = phy->mt76;2681struct ieee80211_channel *chan = mphy->chandef.chan;2682int freq = mphy->chandef.center_freq1;2683struct mt7915_mcu_background_chain_ctrl req = {2684.monitor_scan_type = 2, /* simple rx */2685};26862687if (!chandef && cmd != CH_SWITCH_BACKGROUND_SCAN_STOP)2688return -EINVAL;26892690if (!cfg80211_chandef_valid(&mphy->chandef))2691return -EINVAL;26922693switch (cmd) {2694case CH_SWITCH_BACKGROUND_SCAN_START: {2695req.chan = chan->hw_value;2696req.central_chan = ieee80211_frequency_to_channel(freq);2697req.bw = mt76_connac_chan_bw(&mphy->chandef);2698req.monitor_chan = chandef->chan->hw_value;2699req.monitor_central_chan =2700ieee80211_frequency_to_channel(chandef->center_freq1);2701req.monitor_bw = mt76_connac_chan_bw(chandef);2702req.band_idx = phy->mt76->band_idx;2703req.scan_mode = 1;2704break;2705}2706case CH_SWITCH_BACKGROUND_SCAN_RUNNING:2707req.monitor_chan = chandef->chan->hw_value;2708req.monitor_central_chan =2709ieee80211_frequency_to_channel(chandef->center_freq1);2710req.band_idx = phy->mt76->band_idx;2711req.scan_mode = 2;2712break;2713case CH_SWITCH_BACKGROUND_SCAN_STOP:2714req.chan = chan->hw_value;2715req.central_chan = ieee80211_frequency_to_channel(freq);2716req.bw = mt76_connac_chan_bw(&mphy->chandef);2717req.tx_stream = hweight8(mphy->antenna_mask);2718req.rx_stream = mphy->antenna_mask;2719break;2720default:2721return -EINVAL;2722}2723req.band = chandef ? chandef->chan->band == NL80211_BAND_5GHZ : 1;27242725return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(OFFCH_SCAN_CTRL),2726&req, sizeof(req), false);2727}27282729int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,2730struct cfg80211_chan_def *chandef)2731{2732struct mt7915_dev *dev = phy->dev;2733int err, region, rdd_idx;27342735rdd_idx = mt7915_get_rdd_idx(phy, true);2736if (rdd_idx < 0)2737return -EINVAL;27382739if (!chandef) { /* disable offchain */2740err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, rdd_idx, 0, 0);2741if (err)2742return err;27432744return mt7915_mcu_background_chain_ctrl(phy, NULL,2745CH_SWITCH_BACKGROUND_SCAN_STOP);2746}27472748err = mt7915_mcu_background_chain_ctrl(phy, chandef,2749CH_SWITCH_BACKGROUND_SCAN_START);2750if (err)2751return err;27522753switch (dev->mt76.region) {2754case NL80211_DFS_ETSI:2755region = 0;2756break;2757case NL80211_DFS_JP:2758region = 2;2759break;2760case NL80211_DFS_FCC:2761default:2762region = 1;2763break;2764}27652766return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, rdd_idx, 0, region);2767}27682769int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)2770{2771static const u8 ch_band[] = {2772[NL80211_BAND_2GHZ] = 0,2773[NL80211_BAND_5GHZ] = 1,2774[NL80211_BAND_6GHZ] = 2,2775};2776struct mt7915_dev *dev = phy->dev;2777struct cfg80211_chan_def *chandef = &phy->mt76->chandef;2778int freq1 = chandef->center_freq1;2779u8 band = phy->mt76->band_idx;2780struct {2781u8 control_ch;2782u8 center_ch;2783u8 bw;2784u8 tx_path_num;2785u8 rx_path; /* mask or num */2786u8 switch_reason;2787u8 band_idx;2788u8 center_ch2; /* for 80+80 only */2789__le16 cac_case;2790u8 channel_band;2791u8 rsv0;2792__le32 outband_freq;2793u8 txpower_drop;2794u8 ap_bw;2795u8 ap_center_ch;2796u8 rsv1[57];2797} __packed req = {2798.control_ch = chandef->chan->hw_value,2799.center_ch = ieee80211_frequency_to_channel(freq1),2800.bw = mt76_connac_chan_bw(chandef),2801.tx_path_num = hweight16(phy->mt76->chainmask),2802.rx_path = phy->mt76->chainmask >> (dev->chainshift * band),2803.band_idx = band,2804.channel_band = ch_band[chandef->chan->band],2805};28062807#ifdef CONFIG_NL80211_TESTMODE2808if (phy->mt76->test.tx_antenna_mask &&2809mt76_testmode_enabled(phy->mt76)) {2810req.tx_path_num = fls(phy->mt76->test.tx_antenna_mask);2811req.rx_path = phy->mt76->test.tx_antenna_mask;2812}2813#endif28142815if (mt76_connac_spe_idx(phy->mt76->antenna_mask))2816req.tx_path_num = fls(phy->mt76->antenna_mask);28172818if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)2819req.switch_reason = CH_SWITCH_NORMAL;2820else if (phy->mt76->offchannel ||2821phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)2822req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;2823else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,2824NL80211_IFTYPE_AP))2825req.switch_reason = CH_SWITCH_DFS;2826else2827req.switch_reason = CH_SWITCH_NORMAL;28282829if (cmd == MCU_EXT_CMD(CHANNEL_SWITCH))2830req.rx_path = hweight8(req.rx_path);28312832if (chandef->width == NL80211_CHAN_WIDTH_80P80) {2833int freq2 = chandef->center_freq2;28342835req.center_ch2 = ieee80211_frequency_to_channel(freq2);2836}28372838return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);2839}28402841static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)2842{2843#define MAX_PAGE_IDX_MASK GENMASK(7, 5)2844#define PAGE_IDX_MASK GENMASK(4, 2)2845#define PER_PAGE_SIZE 0x4002846struct mt7915_mcu_eeprom req = { .buffer_mode = EE_MODE_BUFFER };2847u16 eeprom_size = mt7915_eeprom_size(dev);2848u8 total = DIV_ROUND_UP(eeprom_size, PER_PAGE_SIZE);2849u8 *eep = (u8 *)dev->mt76.eeprom.data;2850int eep_len;2851int i;28522853for (i = 0; i < total; i++, eep += eep_len) {2854struct sk_buff *skb;2855int ret;28562857if (i == total - 1 && !!(eeprom_size % PER_PAGE_SIZE))2858eep_len = eeprom_size % PER_PAGE_SIZE;2859else2860eep_len = PER_PAGE_SIZE;28612862skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,2863sizeof(req) + eep_len);2864if (!skb)2865return -ENOMEM;28662867req.format = FIELD_PREP(MAX_PAGE_IDX_MASK, total - 1) |2868FIELD_PREP(PAGE_IDX_MASK, i) | EE_FORMAT_WHOLE;2869req.len = cpu_to_le16(eep_len);28702871skb_put_data(skb, &req, sizeof(req));2872skb_put_data(skb, eep, eep_len);28732874ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,2875MCU_EXT_CMD(EFUSE_BUFFER_MODE), true);2876if (ret)2877return ret;2878}28792880return 0;2881}28822883int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)2884{2885struct mt7915_mcu_eeprom req = {2886.buffer_mode = EE_MODE_EFUSE,2887.format = EE_FORMAT_WHOLE,2888};28892890if (dev->flash_mode)2891return mt7915_mcu_set_eeprom_flash(dev);28922893return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),2894&req, sizeof(req), true);2895}28962897int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf)2898{2899struct mt7915_mcu_eeprom_info req = {2900.addr = cpu_to_le32(round_down(offset,2901MT7915_EEPROM_BLOCK_SIZE)),2902};2903struct mt7915_mcu_eeprom_info *res;2904struct sk_buff *skb;2905u8 *buf = read_buf;2906int ret;29072908ret = mt76_mcu_send_and_get_msg(&dev->mt76,2909MCU_EXT_QUERY(EFUSE_ACCESS),2910&req, sizeof(req), true, &skb);2911if (ret)2912return ret;29132914res = (struct mt7915_mcu_eeprom_info *)skb->data;2915if (!buf)2916#if defined(__linux__)2917buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);2918#elif defined(__FreeBSD__)2919buf = (u8 *)dev->mt76.eeprom.data + le32_to_cpu(res->addr);2920#endif2921memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);29222923dev_kfree_skb(skb);29242925return 0;2926}29272928int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num)2929{2930struct {2931u8 _rsv;2932u8 version;2933u8 die_idx;2934u8 _rsv2;2935} __packed req = {2936.version = 1,2937};2938struct sk_buff *skb;2939int ret;29402941ret = mt76_mcu_send_and_get_msg(&dev->mt76,2942MCU_EXT_QUERY(EFUSE_FREE_BLOCK),2943&req, sizeof(req), true, &skb);2944if (ret)2945return ret;29462947*block_num = *(u8 *)skb->data;2948dev_kfree_skb(skb);29492950return 0;2951}29522953static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,2954u8 *data, u32 len, int cmd)2955{2956struct {2957u8 dir;2958u8 valid;2959__le16 bitmap;2960s8 precal;2961u8 action;2962u8 band;2963u8 idx;2964u8 rsv[4];2965__le32 len;2966} req = {};2967struct sk_buff *skb;29682969skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req) + len);2970if (!skb)2971return -ENOMEM;29722973req.idx = idx;2974req.len = cpu_to_le32(len);2975skb_put_data(skb, &req, sizeof(req));2976skb_put_data(skb, data, len);29772978return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, false);2979}29802981int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)2982{2983u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;2984u32 total = mt7915_get_cal_group_size(dev);2985u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;29862987if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP))2988return 0;29892990/*2991* Items: Rx DCOC, RSSI DCOC, Tx TSSI DCOC, Tx LPFG2992* Tx FDIQ, Tx DCIQ, Rx FDIQ, Rx FIIQ, ADCDCOC2993*/2994while (total > 0) {2995int ret, len;29962997len = min_t(u32, total, MT_EE_CAL_UNIT);29982999ret = mt7915_mcu_set_pre_cal(dev, idx, cal, len,3000MCU_EXT_CMD(GROUP_PRE_CAL_INFO));3001if (ret)3002return ret;30033004total -= len;3005cal += len;3006idx++;3007}30083009return 0;3010}30113012static int mt7915_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)3013{3014int i;30153016for (i = 0; i < n_freqs; i++)3017if (cur == freqs[i])3018return i;30193020return -1;3021}30223023static int mt7915_dpd_freq_idx(struct mt7915_dev *dev, u16 freq, u8 bw)3024{3025static const u16 freq_list_v1[] = {30265180, 5200, 5220, 5240,30275260, 5280, 5300, 5320,30285500, 5520, 5540, 5560,30295580, 5600, 5620, 5640,30305660, 5680, 5700, 5745,30315765, 5785, 5805, 58253032};3033static const u16 freq_list_v2[] = {3034/* 6G BW20*/30355955, 5975, 5995, 6015,30366035, 6055, 6075, 6095,30376115, 6135, 6155, 6175,30386195, 6215, 6235, 6255,30396275, 6295, 6315, 6335,30406355, 6375, 6395, 6415,30416435, 6455, 6475, 6495,30426515, 6535, 6555, 6575,30436595, 6615, 6635, 6655,30446675, 6695, 6715, 6735,30456755, 6775, 6795, 6815,30466835, 6855, 6875, 6895,30476915, 6935, 6955, 6975,30486995, 7015, 7035, 7055,30497075, 7095, 7115,3050/* 6G BW160 */30516025, 6185, 6345, 6505,30526665, 6825, 6985,3053/* 5G BW20 */30545180, 5200, 5220, 5240,30555260, 5280, 5300, 5320,30565500, 5520, 5540, 5560,30575580, 5600, 5620, 5640,30585660, 5680, 5700, 5720,30595745, 5765, 5785, 5805,30605825, 5845, 5865, 5885,3061/* 5G BW160 */30625250, 5570, 58153063};3064static const u16 freq_list_v2_7981[] = {3065/* 5G BW20 */30665180, 5200, 5220, 5240,30675260, 5280, 5300, 5320,30685500, 5520, 5540, 5560,30695580, 5600, 5620, 5640,30705660, 5680, 5700, 5720,30715745, 5765, 5785, 5805,30725825, 5845, 5865, 5885,3073/* 5G BW160 */30745250, 5570, 58153075};3076const u16 *freq_list = freq_list_v1;3077int n_freqs = ARRAY_SIZE(freq_list_v1);3078int idx;30793080if (!is_mt7915(&dev->mt76)) {3081if (is_mt7981(&dev->mt76)) {3082freq_list = freq_list_v2_7981;3083n_freqs = ARRAY_SIZE(freq_list_v2_7981);3084} else {3085freq_list = freq_list_v2;3086n_freqs = ARRAY_SIZE(freq_list_v2);3087}3088}30893090if (freq < 4000) {3091if (freq < 2432)3092return n_freqs;3093if (freq < 2457)3094return n_freqs + 1;30953096return n_freqs + 2;3097}30983099if (bw == NL80211_CHAN_WIDTH_80P80)3100return -1;31013102if (bw != NL80211_CHAN_WIDTH_20) {3103idx = mt7915_find_freq_idx(freq_list, n_freqs, freq + 10);3104if (idx >= 0)3105return idx;31063107idx = mt7915_find_freq_idx(freq_list, n_freqs, freq - 10);3108if (idx >= 0)3109return idx;3110}31113112return mt7915_find_freq_idx(freq_list, n_freqs, freq);3113}31143115int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)3116{3117struct mt7915_dev *dev = phy->dev;3118struct cfg80211_chan_def *chandef = &phy->mt76->chandef;3119enum nl80211_band band = chandef->chan->band;3120u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;3121u16 center_freq = chandef->center_freq1;3122u8 *cal = dev->cal, *eep = dev->mt76.eeprom.data;3123u8 dpd_mask, cal_num = is_mt7915(&dev->mt76) ? 2 : 3;3124int idx;31253126switch (band) {3127case NL80211_BAND_2GHZ:3128dpd_mask = MT_EE_WIFI_CAL_DPD_2G;3129break;3130case NL80211_BAND_5GHZ:3131dpd_mask = MT_EE_WIFI_CAL_DPD_5G;3132break;3133case NL80211_BAND_6GHZ:3134dpd_mask = MT_EE_WIFI_CAL_DPD_6G;3135break;3136default:3137dpd_mask = 0;3138break;3139}31403141if (!(eep[offs] & dpd_mask))3142return 0;31433144idx = mt7915_dpd_freq_idx(dev, center_freq, chandef->width);3145if (idx < 0)3146return -EINVAL;31473148/* Items: Tx DPD, Tx Flatness */3149idx = idx * cal_num;3150cal += mt7915_get_cal_group_size(dev) + (idx * MT_EE_CAL_UNIT);31513152while (cal_num--) {3153int ret;31543155ret = mt7915_mcu_set_pre_cal(dev, idx, cal, MT_EE_CAL_UNIT,3156MCU_EXT_CMD(DPD_PRE_CAL_INFO));3157if (ret)3158return ret;31593160idx++;3161cal += MT_EE_CAL_UNIT;3162}31633164return 0;3165}31663167int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)3168{3169struct mt76_channel_state *state = phy->mt76->chan_state;3170struct mt76_channel_state *state_ts = &phy->state_ts;3171struct mt7915_dev *dev = phy->dev;3172struct mt7915_mcu_mib *res, req[5];3173struct sk_buff *skb;3174static const u32 *offs;3175int i, ret, len, offs_cc;3176u64 cc_tx;31773178/* strict order */3179if (is_mt7915(&dev->mt76)) {3180static const u32 chip_offs[] = {3181MIB_NON_WIFI_TIME,3182MIB_TX_TIME,3183MIB_RX_TIME,3184MIB_OBSS_AIRTIME,3185MIB_TXOP_INIT_COUNT,3186};3187len = ARRAY_SIZE(chip_offs);3188offs = chip_offs;3189offs_cc = 20;3190} else {3191static const u32 chip_offs[] = {3192MIB_NON_WIFI_TIME_V2,3193MIB_TX_TIME_V2,3194MIB_RX_TIME_V2,3195MIB_OBSS_AIRTIME_V23196};3197len = ARRAY_SIZE(chip_offs);3198offs = chip_offs;3199offs_cc = 0;3200}32013202for (i = 0; i < len; i++) {3203req[i].band = cpu_to_le32(phy->mt76->band_idx);3204req[i].offs = cpu_to_le32(offs[i]);3205}32063207ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO),3208req, len * sizeof(req[0]), true, &skb);3209if (ret)3210return ret;32113212res = (struct mt7915_mcu_mib *)(skb->data + offs_cc);32133214#define __res_u64(s) le64_to_cpu(res[s].data)3215/* subtract Tx backoff time from Tx duration for MT7915 */3216if (is_mt7915(&dev->mt76)) {3217u64 backoff = (__res_u64(4) & 0xffff) * 79; /* 16us + 9us * 7 */3218cc_tx = __res_u64(1) - backoff;3219} else {3220cc_tx = __res_u64(1);3221}32223223if (chan_switch)3224goto out;32253226state->cc_tx += cc_tx - state_ts->cc_tx;3227state->cc_bss_rx += __res_u64(2) - state_ts->cc_bss_rx;3228state->cc_rx += __res_u64(2) + __res_u64(3) - state_ts->cc_rx;3229state->cc_busy += __res_u64(0) + cc_tx + __res_u64(2) + __res_u64(3) -3230state_ts->cc_busy;32313232out:3233state_ts->cc_tx = cc_tx;3234state_ts->cc_bss_rx = __res_u64(2);3235state_ts->cc_rx = __res_u64(2) + __res_u64(3);3236state_ts->cc_busy = __res_u64(0) + cc_tx + __res_u64(2) + __res_u64(3);3237#undef __res_u6432383239dev_kfree_skb(skb);32403241return 0;3242}32433244int mt7915_mcu_get_temperature(struct mt7915_phy *phy)3245{3246struct mt7915_dev *dev = phy->dev;3247struct {3248u8 ctrl_id;3249u8 action;3250u8 band_idx;3251u8 rsv[5];3252} req = {3253.ctrl_id = THERMAL_SENSOR_TEMP_QUERY,3254.band_idx = phy->mt76->band_idx,3255};32563257return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), &req,3258sizeof(req), true);3259}32603261int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)3262{3263struct mt7915_dev *dev = phy->dev;3264struct mt7915_mcu_thermal_ctrl req = {3265.band_idx = phy->mt76->band_idx,3266.ctrl_id = THERMAL_PROTECT_DUTY_CONFIG,3267};3268int level, ret;32693270/* set duty cycle and level */3271for (level = 0; level < 4; level++) {3272req.duty.duty_level = level;3273req.duty.duty_cycle = state;3274state /= 2;32753276ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),3277&req, sizeof(req), false);3278if (ret)3279return ret;3280}3281return 0;3282}32833284int mt7915_mcu_set_thermal_protect(struct mt7915_phy *phy)3285{3286struct mt7915_dev *dev = phy->dev;3287struct {3288struct mt7915_mcu_thermal_ctrl ctrl;32893290__le32 trigger_temp;3291__le32 restore_temp;3292__le16 sustain_time;3293u8 rsv[2];3294} __packed req = {3295.ctrl = {3296.band_idx = phy->mt76->band_idx,3297.type.protect_type = 1,3298.type.trigger_type = 1,3299},3300};3301int ret;33023303req.ctrl.ctrl_id = THERMAL_PROTECT_DISABLE;3304ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),3305&req, sizeof(req.ctrl), false);33063307if (ret)3308return ret;33093310/* set high-temperature trigger threshold */3311req.ctrl.ctrl_id = THERMAL_PROTECT_ENABLE;3312/* add a safety margin ~10 */3313req.restore_temp = cpu_to_le32(phy->throttle_temp[0] - 10);3314req.trigger_temp = cpu_to_le32(phy->throttle_temp[1]);3315req.sustain_time = cpu_to_le16(10);33163317return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),3318&req, sizeof(req), false);3319}33203321int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower)3322{3323struct mt7915_dev *dev = phy->dev;3324struct {3325u8 format_id;3326u8 rsv;3327u8 band_idx;3328s8 txpower_min;3329} __packed req = {3330.format_id = TX_POWER_LIMIT_FRAME_MIN,3331.band_idx = phy->mt76->band_idx,3332.txpower_min = txpower * 2, /* 0.5db */3333};33343335return mt76_mcu_send_msg(&dev->mt76,3336MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,3337sizeof(req), true);3338}33393340int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,3341struct ieee80211_vif *vif,3342struct ieee80211_sta *sta, s8 txpower)3343{3344struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;3345struct mt7915_dev *dev = phy->dev;3346struct mt76_phy *mphy = phy->mt76;3347struct {3348u8 format_id;3349u8 rsv[3];3350u8 band_idx;3351s8 txpower_max;3352__le16 wcid;3353s8 txpower_offs[48];3354} __packed req = {3355.format_id = TX_POWER_LIMIT_FRAME,3356.band_idx = phy->mt76->band_idx,3357.txpower_max = DIV_ROUND_UP(mphy->txpower_cur, 2),3358.wcid = cpu_to_le16(msta->wcid.idx),3359};3360int ret;3361s8 txpower_sku[MT7915_SKU_RATE_NUM];33623363ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku));3364if (ret)3365return ret;33663367txpower = mt76_get_power_bound(mphy, txpower);3368if (txpower > mphy->txpower_cur || txpower < 0)3369return -EINVAL;33703371if (txpower) {3372u32 offs, len, i;33733374if (sta->deflink.ht_cap.ht_supported) {3375const u8 *sku_len = mt7915_sku_group_len;33763377offs = sku_len[SKU_CCK] + sku_len[SKU_OFDM];3378len = sku_len[SKU_HT_BW20] + sku_len[SKU_HT_BW40];33793380if (sta->deflink.vht_cap.vht_supported) {3381offs += len;3382len = sku_len[SKU_VHT_BW20] * 4;33833384if (sta->deflink.he_cap.has_he) {3385offs += len + sku_len[SKU_HE_RU26] * 3;3386len = sku_len[SKU_HE_RU242] * 4;3387}3388}3389} else {3390return -EINVAL;3391}33923393for (i = 0; i < len; i++, offs++)3394req.txpower_offs[i] =3395DIV_ROUND_UP(txpower - txpower_sku[offs], 2);3396}33973398return mt76_mcu_send_msg(&dev->mt76,3399MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,3400sizeof(req), true);3401}34023403int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)3404{3405struct mt7915_dev *dev = phy->dev;3406struct mt76_phy *mphy = phy->mt76;3407struct ieee80211_hw *hw = mphy->hw;3408struct mt7915_mcu_txpower_sku req = {3409.format_id = TX_POWER_LIMIT_TABLE,3410.band_idx = phy->mt76->band_idx,3411};3412struct mt76_power_limits limits_array;3413s8 *la = (s8 *)&limits_array;3414int i, idx;3415int tx_power;34163417tx_power = mt76_get_power_bound(mphy, hw->conf.power_level);3418tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,3419&limits_array, tx_power);3420mphy->txpower_cur = tx_power;34213422for (i = 0, idx = 0; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {3423u8 mcs_num, len = mt7915_sku_group_len[i];3424int j;34253426if (i >= SKU_HT_BW20 && i <= SKU_VHT_BW160) {3427mcs_num = 10;34283429if (i == SKU_HT_BW20 || i == SKU_VHT_BW20)3430la = (s8 *)&limits_array + 12;3431} else {3432mcs_num = len;3433}34343435for (j = 0; j < min_t(u8, mcs_num, len); j++)3436req.txpower_sku[idx + j] = la[j];34373438la += mcs_num;3439idx += len;3440}34413442return mt76_mcu_send_msg(&dev->mt76,3443MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,3444sizeof(req), true);3445}34463447int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)3448{3449#define RATE_POWER_INFO 23450struct mt7915_dev *dev = phy->dev;3451struct {3452u8 format_id;3453u8 category;3454u8 band_idx;3455u8 _rsv;3456} __packed req = {3457.format_id = TX_POWER_LIMIT_INFO,3458.category = RATE_POWER_INFO,3459.band_idx = phy->mt76->band_idx,3460};3461s8 txpower_sku[MT7915_SKU_RATE_NUM][2];3462struct sk_buff *skb;3463int ret, i;34643465ret = mt76_mcu_send_and_get_msg(&dev->mt76,3466MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),3467&req, sizeof(req), true, &skb);3468if (ret)3469return ret;34703471memcpy(txpower_sku, skb->data + 4, sizeof(txpower_sku));3472for (i = 0; i < len; i++)3473txpower[i] = txpower_sku[i][req.band_idx];34743475dev_kfree_skb(skb);34763477return 0;3478}34793480int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode,3481u8 en)3482{3483struct {3484u8 test_mode_en;3485u8 param_idx;3486u8 _rsv[2];34873488u8 enable;3489u8 _rsv2[3];34903491u8 pad[8];3492} __packed req = {3493.test_mode_en = test_mode,3494.param_idx = param,3495.enable = en,3496};34973498return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,3499sizeof(req), false);3500}35013502int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)3503{3504struct mt7915_dev *dev = phy->dev;3505struct mt7915_sku {3506u8 format_id;3507u8 sku_enable;3508u8 band_idx;3509u8 rsv;3510} __packed req = {3511.format_id = TX_POWER_LIMIT_ENABLE,3512.band_idx = phy->mt76->band_idx,3513.sku_enable = enable,3514};35153516return mt76_mcu_send_msg(&dev->mt76,3517MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,3518sizeof(req), true);3519}35203521int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)3522{3523struct {3524u8 action;3525u8 set;3526u8 band;3527u8 rsv;3528} req = {3529.action = action,3530.set = set,3531.band = band,3532};35333534return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SER_TRIGGER),3535&req, sizeof(req), false);3536}35373538int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)3539{3540struct {3541u8 action;3542union {3543struct {3544u8 snd_mode;3545u8 sta_num;3546u8 rsv;3547u8 wlan_idx[4];3548__le32 snd_period; /* ms */3549} __packed snd;3550struct {3551bool ebf;3552bool ibf;3553u8 rsv;3554} __packed type;3555struct {3556u8 bf_num;3557u8 bf_bitmap;3558u8 bf_sel[8];3559u8 rsv[5];3560} __packed mod;3561};3562} __packed req = {3563.action = action,3564};35653566#define MT_BF_PROCESSING 43567switch (action) {3568case MT_BF_SOUNDING_ON:3569req.snd.snd_mode = MT_BF_PROCESSING;3570break;3571case MT_BF_TYPE_UPDATE:3572req.type.ebf = true;3573req.type.ibf = dev->ibf;3574break;3575case MT_BF_MODULE_UPDATE:3576req.mod.bf_num = 2;3577req.mod.bf_bitmap = GENMASK(1, 0);3578break;3579default:3580return -EINVAL;3581}35823583return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,3584sizeof(req), true);3585}35863587static int3588mt7915_mcu_enable_obss_spr(struct mt7915_phy *phy, u8 action, u8 val)3589{3590struct mt7915_dev *dev = phy->dev;3591struct mt7915_mcu_sr_ctrl req = {3592.action = action,3593.argnum = 1,3594.band_idx = phy->mt76->band_idx,3595.val = cpu_to_le32(val),3596};35973598return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,3599sizeof(req), true);3600}36013602static int3603mt7915_mcu_set_obss_spr_pd(struct mt7915_phy *phy,3604struct ieee80211_he_obss_pd *he_obss_pd)3605{3606struct mt7915_dev *dev = phy->dev;3607struct {3608struct mt7915_mcu_sr_ctrl ctrl;3609struct {3610u8 pd_th_non_srg;3611u8 pd_th_srg;3612u8 period_offs;3613u8 rcpi_src;3614__le16 obss_pd_min;3615__le16 obss_pd_min_srg;3616u8 resp_txpwr_mode;3617u8 txpwr_restrict_mode;3618u8 txpwr_ref;3619u8 rsv[3];3620} __packed param;3621} __packed req = {3622.ctrl = {3623.action = SPR_SET_PARAM,3624.argnum = 9,3625.band_idx = phy->mt76->band_idx,3626},3627};3628int ret;3629u8 max_th = 82, non_srg_max_th = 62;36303631/* disable firmware dynamical PD asjustment */3632ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_DPD, false);3633if (ret)3634return ret;36353636if (he_obss_pd->sr_ctrl &3637IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED)3638req.param.pd_th_non_srg = max_th;3639else if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)3640req.param.pd_th_non_srg = max_th - he_obss_pd->non_srg_max_offset;3641else3642req.param.pd_th_non_srg = non_srg_max_th;36433644if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT)3645req.param.pd_th_srg = max_th - he_obss_pd->max_offset;36463647req.param.obss_pd_min = cpu_to_le16(82);3648req.param.obss_pd_min_srg = cpu_to_le16(82);3649req.param.txpwr_restrict_mode = 2;3650req.param.txpwr_ref = 21;36513652return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,3653sizeof(req), true);3654}36553656static int3657mt7915_mcu_set_obss_spr_siga(struct mt7915_phy *phy, struct ieee80211_vif *vif,3658struct ieee80211_he_obss_pd *he_obss_pd)3659{3660struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;3661struct mt7915_dev *dev = phy->dev;3662u8 omac = mvif->mt76.omac_idx;3663struct {3664struct mt7915_mcu_sr_ctrl ctrl;3665struct {3666u8 omac;3667u8 rsv[3];3668u8 flag[20];3669} __packed siga;3670} __packed req = {3671.ctrl = {3672.action = SPR_SET_SIGA,3673.argnum = 1,3674.band_idx = phy->mt76->band_idx,3675},3676.siga = {3677.omac = omac > HW_BSSID_MAX ? omac - 12 : omac,3678},3679};3680int ret;36813682if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED)3683req.siga.flag[req.siga.omac] = 0xf;3684else3685return 0;36863687/* switch to normal AP mode */3688ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_MODE, 0);3689if (ret)3690return ret;36913692return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,3693sizeof(req), true);3694}36953696static int3697mt7915_mcu_set_obss_spr_bitmap(struct mt7915_phy *phy,3698struct ieee80211_he_obss_pd *he_obss_pd)3699{3700struct mt7915_dev *dev = phy->dev;3701struct {3702struct mt7915_mcu_sr_ctrl ctrl;3703struct {3704__le32 color_l[2];3705__le32 color_h[2];3706__le32 bssid_l[2];3707__le32 bssid_h[2];3708} __packed bitmap;3709} __packed req = {3710.ctrl = {3711.action = SPR_SET_SRG_BITMAP,3712.argnum = 4,3713.band_idx = phy->mt76->band_idx,3714},3715};3716u32 bitmap;37173718memcpy(&bitmap, he_obss_pd->bss_color_bitmap, sizeof(bitmap));3719req.bitmap.color_l[req.ctrl.band_idx] = cpu_to_le32(bitmap);37203721memcpy(&bitmap, he_obss_pd->bss_color_bitmap + 4, sizeof(bitmap));3722req.bitmap.color_h[req.ctrl.band_idx] = cpu_to_le32(bitmap);37233724memcpy(&bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(bitmap));3725req.bitmap.bssid_l[req.ctrl.band_idx] = cpu_to_le32(bitmap);37263727memcpy(&bitmap, he_obss_pd->partial_bssid_bitmap + 4, sizeof(bitmap));3728req.bitmap.bssid_h[req.ctrl.band_idx] = cpu_to_le32(bitmap);37293730return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,3731sizeof(req), true);3732}37333734int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,3735struct ieee80211_he_obss_pd *he_obss_pd)3736{3737int ret;37383739/* enable firmware scene detection algorithms */3740ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_SD, sr_scene_detect);3741if (ret)3742return ret;37433744/* firmware dynamically adjusts PD threshold so skip manual control */3745if (sr_scene_detect && !he_obss_pd->enable)3746return 0;37473748/* enable spatial reuse */3749ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE, he_obss_pd->enable);3750if (ret)3751return ret;37523753if (sr_scene_detect || !he_obss_pd->enable)3754return 0;37553756ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_TX, true);3757if (ret)3758return ret;37593760/* set SRG/non-SRG OBSS PD threshold */3761ret = mt7915_mcu_set_obss_spr_pd(phy, he_obss_pd);3762if (ret)3763return ret;37643765/* Set SR prohibit */3766ret = mt7915_mcu_set_obss_spr_siga(phy, vif, he_obss_pd);3767if (ret)3768return ret;37693770/* set SRG BSS color/BSSID bitmap */3771return mt7915_mcu_set_obss_spr_bitmap(phy, he_obss_pd);3772}37733774int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,3775struct ieee80211_sta *sta, struct rate_info *rate)3776{3777struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;3778struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;3779struct mt7915_dev *dev = phy->dev;3780struct mt76_phy *mphy = phy->mt76;3781struct {3782u8 category;3783u8 band;3784__le16 wcid;3785} __packed req = {3786.category = MCU_PHY_STATE_CONTENTION_RX_RATE,3787.band = mvif->mt76.band_idx,3788.wcid = cpu_to_le16(msta->wcid.idx),3789};3790struct ieee80211_supported_band *sband;3791struct mt7915_mcu_phy_rx_info *res;3792struct sk_buff *skb;3793int ret;3794bool cck = false;37953796ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(PHY_STAT_INFO),3797&req, sizeof(req), true, &skb);3798if (ret)3799return ret;38003801res = (struct mt7915_mcu_phy_rx_info *)skb->data;38023803rate->mcs = res->rate;3804rate->nss = res->nsts + 1;38053806switch (res->mode) {3807case MT_PHY_TYPE_CCK:3808cck = true;3809fallthrough;3810case MT_PHY_TYPE_OFDM:3811if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)3812sband = &mphy->sband_5g.sband;3813else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)3814sband = &mphy->sband_6g.sband;3815else3816sband = &mphy->sband_2g.sband;38173818rate->mcs = mt76_get_rate(&dev->mt76, sband, rate->mcs, cck);3819rate->legacy = sband->bitrates[rate->mcs].bitrate;3820break;3821case MT_PHY_TYPE_HT:3822case MT_PHY_TYPE_HT_GF:3823if (rate->mcs > 31) {3824ret = -EINVAL;3825goto out;3826}38273828rate->flags = RATE_INFO_FLAGS_MCS;3829if (res->gi)3830rate->flags |= RATE_INFO_FLAGS_SHORT_GI;3831break;3832case MT_PHY_TYPE_VHT:3833if (rate->mcs > 9) {3834ret = -EINVAL;3835goto out;3836}38373838rate->flags = RATE_INFO_FLAGS_VHT_MCS;3839if (res->gi)3840rate->flags |= RATE_INFO_FLAGS_SHORT_GI;3841break;3842case MT_PHY_TYPE_HE_SU:3843case MT_PHY_TYPE_HE_EXT_SU:3844case MT_PHY_TYPE_HE_TB:3845case MT_PHY_TYPE_HE_MU:3846if (res->gi > NL80211_RATE_INFO_HE_GI_3_2 || rate->mcs > 11) {3847ret = -EINVAL;3848goto out;3849}3850rate->he_gi = res->gi;3851rate->flags = RATE_INFO_FLAGS_HE_MCS;3852break;3853default:3854ret = -EINVAL;3855goto out;3856}38573858switch (res->bw) {3859case IEEE80211_STA_RX_BW_160:3860rate->bw = RATE_INFO_BW_160;3861break;3862case IEEE80211_STA_RX_BW_80:3863rate->bw = RATE_INFO_BW_80;3864break;3865case IEEE80211_STA_RX_BW_40:3866rate->bw = RATE_INFO_BW_40;3867break;3868default:3869rate->bw = RATE_INFO_BW_20;3870break;3871}38723873out:3874dev_kfree_skb(skb);38753876return ret;3877}38783879int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,3880struct cfg80211_he_bss_color *he_bss_color)3881{3882int len = sizeof(struct sta_req_hdr) + sizeof(struct bss_info_color);3883struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;3884struct bss_info_color *bss_color;3885struct sk_buff *skb;3886struct tlv *tlv;38873888skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,3889NULL, len);3890if (IS_ERR(skb))3891return PTR_ERR(skb);38923893tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BSS_COLOR,3894sizeof(*bss_color));3895bss_color = (struct bss_info_color *)tlv;3896bss_color->disable = !he_bss_color->enabled;3897bss_color->color = he_bss_color->color;38983899return mt76_mcu_skb_send_msg(&dev->mt76, skb,3900MCU_EXT_CMD(BSS_INFO_UPDATE), true);3901}39023903#define TWT_AGRT_TRIGGER BIT(0)3904#define TWT_AGRT_ANNOUNCE BIT(1)3905#define TWT_AGRT_PROTECT BIT(2)39063907int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,3908struct mt7915_vif *mvif,3909struct mt7915_twt_flow *flow,3910int cmd)3911{3912struct {3913u8 tbl_idx;3914u8 cmd;3915u8 own_mac_idx;3916u8 flowid; /* 0xff for group id */3917__le16 peer_id; /* specify the peer_id (msb=0)3918* or group_id (msb=1)3919*/3920u8 duration; /* 256 us */3921u8 bss_idx;3922__le64 start_tsf;3923__le16 mantissa;3924u8 exponent;3925u8 is_ap;3926u8 agrt_params;3927u8 rsv[23];3928} __packed req = {3929.tbl_idx = flow->table_id,3930.cmd = cmd,3931.own_mac_idx = mvif->mt76.omac_idx,3932.flowid = flow->id,3933.peer_id = cpu_to_le16(flow->wcid),3934.duration = flow->duration,3935.bss_idx = mvif->mt76.idx,3936.start_tsf = cpu_to_le64(flow->tsf),3937.mantissa = flow->mantissa,3938.exponent = flow->exp,3939.is_ap = true,3940};39413942if (flow->protection)3943req.agrt_params |= TWT_AGRT_PROTECT;3944if (!flow->flowtype)3945req.agrt_params |= TWT_AGRT_ANNOUNCE;3946if (flow->trigger)3947req.agrt_params |= TWT_AGRT_TRIGGER;39483949return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TWT_AGRT_UPDATE),3950&req, sizeof(req), true);3951}39523953int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)3954{3955struct {3956__le32 cmd;3957__le32 arg0;3958__le32 arg1;3959__le16 arg2;3960} __packed req = {3961.cmd = cpu_to_le32(0x15),3962};3963struct mt7915_mcu_wa_tx_stat {3964__le16 wcid;3965u8 __rsv2[2];39663967/* tx_bytes is deprecated since WA byte counter uses u32,3968* which easily leads to overflow.3969*/3970__le32 tx_bytes;3971__le32 tx_packets;3972} __packed *res;3973struct mt76_wcid *wcid;3974struct sk_buff *skb;3975int ret, len;3976u16 ret_wcid;39773978if (is_mt7915(&dev->mt76)) {3979req.arg0 = cpu_to_le32(wlan_idx);3980len = sizeof(req) - sizeof(req.arg2);3981} else {3982req.arg0 = cpu_to_le32(1);3983req.arg2 = cpu_to_le16(wlan_idx);3984len = sizeof(req);3985}39863987ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY),3988&req, len, true, &skb);3989if (ret)3990return ret;39913992if (!is_mt7915(&dev->mt76))3993skb_pull(skb, 4);39943995res = (struct mt7915_mcu_wa_tx_stat *)skb->data;39963997ret_wcid = le16_to_cpu(res->wcid);3998if (is_mt7915(&dev->mt76))3999ret_wcid &= 0xff;40004001if (ret_wcid != wlan_idx) {4002ret = -EINVAL;4003goto out;4004}40054006rcu_read_lock();40074008wcid = mt76_wcid_ptr(dev, wlan_idx);4009if (wcid)4010wcid->stats.tx_packets += le32_to_cpu(res->tx_packets);4011else4012ret = -EINVAL;40134014rcu_read_unlock();4015out:4016dev_kfree_skb(skb);40174018return ret;4019}40204021int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)4022{4023struct {4024__le32 idx;4025__le32 ofs;4026__le32 data;4027} __packed req = {4028.idx = cpu_to_le32(u32_get_bits(regidx, GENMASK(31, 24))),4029.ofs = cpu_to_le32(u32_get_bits(regidx, GENMASK(23, 0))),4030.data = set ? cpu_to_le32(*val) : 0,4031};4032struct sk_buff *skb;4033int ret;40344035if (set)4036return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_REG_ACCESS),4037&req, sizeof(req), false);40384039ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(RF_REG_ACCESS),4040&req, sizeof(req), true, &skb);4041if (ret)4042return ret;40434044*val = le32_to_cpu(*(__le32 *)(skb->data + 8));4045dev_kfree_skb(skb);40464047return 0;4048}404940504051