Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7925/main.c
48525 views
// SPDX-License-Identifier: ISC1/* Copyright (C) 2023 MediaTek Inc. */23#include <linux/etherdevice.h>4#include <linux/platform_device.h>5#include <linux/pci.h>6#include <linux/module.h>7#include <linux/ctype.h>8#include <net/ipv6.h>9#include "mt7925.h"10#include "mcu.h"11#include "mac.h"1213static void14mt7925_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band,15struct ieee80211_sband_iftype_data *data,16enum nl80211_iftype iftype)17{18struct ieee80211_sta_he_cap *he_cap = &data->he_cap;19struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem;20struct ieee80211_he_mcs_nss_supp *he_mcs = &he_cap->he_mcs_nss_supp;21int i, nss = hweight8(phy->mt76->antenna_mask);22u16 mcs_map = 0;2324for (i = 0; i < 8; i++) {25if (i < nss)26mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));27else28mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));29}3031he_cap->has_he = true;3233he_cap_elem->mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE;34he_cap_elem->mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_OMI_CONTROL |35IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3;36he_cap_elem->mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU;3738if (band == NL80211_BAND_2GHZ)39he_cap_elem->phy_cap_info[0] =40IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;41else42he_cap_elem->phy_cap_info[0] =43IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |44IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;4546he_cap_elem->phy_cap_info[1] =47IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;48he_cap_elem->phy_cap_info[2] =49IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |50IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |51IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |52IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |53IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;5455switch (iftype) {56case NL80211_IFTYPE_AP:57he_cap_elem->mac_cap_info[2] |=58IEEE80211_HE_MAC_CAP2_BSR;59he_cap_elem->mac_cap_info[4] |=60IEEE80211_HE_MAC_CAP4_BQR;61he_cap_elem->mac_cap_info[5] |=62IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX;63he_cap_elem->phy_cap_info[3] |=64IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |65IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;66he_cap_elem->phy_cap_info[6] |=67IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |68IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;69he_cap_elem->phy_cap_info[9] |=70IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |71IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;72break;73case NL80211_IFTYPE_STATION:74he_cap_elem->mac_cap_info[1] |=75IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;7677if (band == NL80211_BAND_2GHZ)78he_cap_elem->phy_cap_info[0] |=79IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;80else81he_cap_elem->phy_cap_info[0] |=82IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;8384he_cap_elem->phy_cap_info[1] |=85IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |86IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US;87he_cap_elem->phy_cap_info[3] |=88IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |89IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;90he_cap_elem->phy_cap_info[4] |=91IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |92IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 |93IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;94he_cap_elem->phy_cap_info[5] |=95IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK |96IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;97he_cap_elem->phy_cap_info[6] |=98IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |99IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |100IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |101IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |102IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;103he_cap_elem->phy_cap_info[7] |=104IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |105IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;106he_cap_elem->phy_cap_info[8] |=107IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |108IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |109IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |110IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;111he_cap_elem->phy_cap_info[9] |=112IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |113IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |114IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |115IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |116IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |117IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;118break;119default:120break;121}122123he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);124he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);125he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map);126he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map);127128memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));129130if (he_cap_elem->phy_cap_info[6] &131IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {132mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss, band);133} else {134he_cap_elem->phy_cap_info[9] |=135u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,136IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);137}138139if (band == NL80211_BAND_6GHZ) {140u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |141IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;142143cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_0_5,144IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |145u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,146IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |147u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,148IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);149150data->he_6ghz_capa.capa = cpu_to_le16(cap);151}152}153154static void155mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,156struct ieee80211_sband_iftype_data *data)157{158struct ieee80211_sta_eht_cap *eht_cap = &data->eht_cap;159struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;160struct ieee80211_eht_mcs_nss_supp *eht_nss = &eht_cap->eht_mcs_nss_supp;161enum nl80211_chan_width width = phy->mt76->chandef.width;162int nss = hweight8(phy->mt76->antenna_mask);163int sts = hweight16(phy->mt76->chainmask);164u8 val;165166if (!phy->dev->has_eht)167return;168169eht_cap->has_eht = true;170171eht_cap_elem->mac_cap_info[0] =172IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |173IEEE80211_EHT_MAC_CAP0_OM_CONTROL;174175eht_cap_elem->phy_cap_info[0] =176IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |177IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |178IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;179180eht_cap_elem->phy_cap_info[0] |=181u8_encode_bits(u8_get_bits(sts - 1, BIT(0)),182IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK);183184eht_cap_elem->phy_cap_info[1] =185u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)),186IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) |187u8_encode_bits(sts - 1,188IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK);189190eht_cap_elem->phy_cap_info[2] =191u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK) |192u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK);193194eht_cap_elem->phy_cap_info[3] =195IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |196IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |197IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |198IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |199IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK |200IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |201IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK;202203eht_cap_elem->phy_cap_info[4] =204u8_encode_bits(min_t(int, sts - 1, 2),205IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK);206207eht_cap_elem->phy_cap_info[5] =208IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |209u8_encode_bits(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US,210IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK) |211u8_encode_bits(u8_get_bits(0x11, GENMASK(1, 0)),212IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK);213214val = width == NL80211_CHAN_WIDTH_160 ? 0x7 :215width == NL80211_CHAN_WIDTH_80 ? 0x3 : 0x1;216eht_cap_elem->phy_cap_info[6] =217u8_encode_bits(u8_get_bits(0x11, GENMASK(4, 2)),218IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK) |219u8_encode_bits(val, IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK);220221eht_cap_elem->phy_cap_info[7] =222IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |223IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |224IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |225IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ;226227val = u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_RX) |228u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_TX);229230eht_nss->bw._80.rx_tx_mcs9_max_nss = val;231eht_nss->bw._80.rx_tx_mcs11_max_nss = val;232eht_nss->bw._80.rx_tx_mcs13_max_nss = val;233eht_nss->bw._160.rx_tx_mcs9_max_nss = val;234eht_nss->bw._160.rx_tx_mcs11_max_nss = val;235eht_nss->bw._160.rx_tx_mcs13_max_nss = val;236}237238int mt7925_init_mlo_caps(struct mt792x_phy *phy)239{240struct wiphy *wiphy = phy->mt76->hw->wiphy;241static const u8 ext_capa_sta[] = {242[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,243};244static struct wiphy_iftype_ext_capab ext_capab[] = {245{246.iftype = NL80211_IFTYPE_STATION,247.extended_capabilities = ext_capa_sta,248.extended_capabilities_mask = ext_capa_sta,249.extended_capabilities_len = sizeof(ext_capa_sta),250},251};252253if (!(phy->chip_cap & MT792x_CHIP_CAP_MLO_EN))254return 0;255256ext_capab[0].eml_capabilities = phy->eml_cap;257ext_capab[0].mld_capa_and_ops =258u16_encode_bits(0, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS);259260wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;261wiphy->iftype_ext_capab = ext_capab;262wiphy->num_iftype_ext_capab = ARRAY_SIZE(ext_capab);263264return 0;265}266267static void268__mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy,269struct ieee80211_supported_band *sband,270enum nl80211_band band)271{272struct ieee80211_sband_iftype_data *data = phy->iftype[band];273int i, n = 0;274275for (i = 0; i < NUM_NL80211_IFTYPES; i++) {276switch (i) {277case NL80211_IFTYPE_STATION:278case NL80211_IFTYPE_AP:279break;280default:281continue;282}283284data[n].types_mask = BIT(i);285mt7925_init_he_caps(phy, band, &data[n], i);286mt7925_init_eht_caps(phy, band, &data[n]);287288n++;289}290291_ieee80211_set_sband_iftype_data(sband, data, n);292}293294void mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy)295{296if (phy->mt76->cap.has_2ghz)297__mt7925_set_stream_he_eht_caps(phy, &phy->mt76->sband_2g.sband,298NL80211_BAND_2GHZ);299300if (phy->mt76->cap.has_5ghz)301__mt7925_set_stream_he_eht_caps(phy, &phy->mt76->sband_5g.sband,302NL80211_BAND_5GHZ);303304if (phy->mt76->cap.has_6ghz)305__mt7925_set_stream_he_eht_caps(phy, &phy->mt76->sband_6g.sband,306NL80211_BAND_6GHZ);307}308309int __mt7925_start(struct mt792x_phy *phy)310{311struct mt76_phy *mphy = phy->mt76;312struct mt792x_dev *dev = phy->dev;313int err;314315err = mt7925_mcu_set_channel_domain(mphy);316if (err)317return err;318319err = mt7925_mcu_set_rts_thresh(phy, 0x92b);320if (err)321return err;322323if (!dev->sar_inited) {324err = mt7925_set_tx_sar_pwr(mphy->hw, NULL);325if (err)326return err;327dev->sar_inited = true;328}329330mt792x_mac_reset_counters(phy);331set_bit(MT76_STATE_RUNNING, &mphy->state);332333ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,334MT792x_WATCHDOG_TIME);335336if (phy->chip_cap & MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN)337wiphy_rfkill_start_polling(mphy->hw->wiphy);338339return 0;340}341EXPORT_SYMBOL_GPL(__mt7925_start);342343static int mt7925_start(struct ieee80211_hw *hw)344{345struct mt792x_phy *phy = mt792x_hw_phy(hw);346int err;347348mt792x_mutex_acquire(phy->dev);349err = __mt7925_start(phy);350mt792x_mutex_release(phy->dev);351352return err;353}354355static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,356struct ieee80211_bss_conf *link_conf,357struct mt792x_link_sta *mlink)358{359struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);360struct ieee80211_vif *vif = link_conf->vif;361struct mt792x_vif *mvif = mconf->vif;362struct mt76_txq *mtxq;363int idx, ret = 0;364365if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {366mconf->mt76.idx = MT792x_MAX_INTERFACES;367} else {368mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask);369370if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) {371ret = -ENOSPC;372goto out;373}374}375376mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ?3770 : mconf->mt76.idx;378mconf->mt76.band_idx = 0xff;379mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ?3800 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS;381mconf->mt76.link_idx = hweight16(mvif->valid_links);382383if (mvif->phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)384mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4;385else386mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL;387388dev->mt76.vif_mask |= BIT_ULL(mconf->mt76.idx);389mvif->phy->omac_mask |= BIT_ULL(mconf->mt76.omac_idx);390391idx = MT792x_WTBL_RESERVED - mconf->mt76.idx;392393mlink->wcid.idx = idx;394mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET;395mt76_wcid_init(&mlink->wcid, 0);396397mt7925_mac_wtbl_update(dev, idx,398MT_WTBL_UPDATE_ADM_COUNT_CLEAR);399400ewma_rssi_init(&mconf->rssi);401402rcu_assign_pointer(dev->mt76.wcid[idx], &mlink->wcid);403404ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf, &mconf->mt76,405&mlink->wcid, true);406if (ret)407goto out;408409if (vif->txq) {410mtxq = (struct mt76_txq *)vif->txq->drv_priv;411mtxq->wcid = idx;412}413414out:415return ret;416}417418static int419mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)420{421struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;422struct mt792x_dev *dev = mt792x_hw_dev(hw);423struct mt792x_phy *phy = mt792x_hw_phy(hw);424int ret = 0;425426mt792x_mutex_acquire(dev);427428mvif->phy = phy;429mvif->bss_conf.vif = mvif;430mvif->sta.vif = mvif;431mvif->deflink_id = IEEE80211_LINK_UNSPECIFIED;432mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC;433434ret = mt7925_mac_link_bss_add(dev, &vif->bss_conf, &mvif->sta.deflink);435if (ret < 0)436goto out;437438vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;439out:440mt792x_mutex_release(dev);441442return ret;443}444445static void mt7925_roc_iter(void *priv, u8 *mac,446struct ieee80211_vif *vif)447{448struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;449struct mt792x_phy *phy = priv;450451mt7925_mcu_abort_roc(phy, &mvif->bss_conf, phy->roc_token_id);452}453454void mt7925_roc_abort_sync(struct mt792x_dev *dev)455{456struct mt792x_phy *phy = &dev->phy;457458timer_delete_sync(&phy->roc_timer);459cancel_work_sync(&phy->roc_work);460if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))461ieee80211_iterate_interfaces(mt76_hw(dev),462IEEE80211_IFACE_ITER_RESUME_ALL,463mt7925_roc_iter, (void *)phy);464}465EXPORT_SYMBOL_GPL(mt7925_roc_abort_sync);466467void mt7925_roc_work(struct work_struct *work)468{469struct mt792x_phy *phy;470471phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,472roc_work);473474if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))475return;476477mt792x_mutex_acquire(phy->dev);478ieee80211_iterate_active_interfaces(phy->mt76->hw,479IEEE80211_IFACE_ITER_RESUME_ALL,480mt7925_roc_iter, phy);481mt792x_mutex_release(phy->dev);482ieee80211_remain_on_channel_expired(phy->mt76->hw);483}484485static int mt7925_abort_roc(struct mt792x_phy *phy,486struct mt792x_bss_conf *mconf)487{488int err = 0;489490timer_delete_sync(&phy->roc_timer);491cancel_work_sync(&phy->roc_work);492493mt792x_mutex_acquire(phy->dev);494if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))495err = mt7925_mcu_abort_roc(phy, mconf, phy->roc_token_id);496mt792x_mutex_release(phy->dev);497498return err;499}500501static int mt7925_set_roc(struct mt792x_phy *phy,502struct mt792x_bss_conf *mconf,503struct ieee80211_channel *chan,504int duration,505enum mt7925_roc_req type)506{507int err;508509if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state))510return -EBUSY;511512phy->roc_grant = false;513514err = mt7925_mcu_set_roc(phy, mconf, chan, duration, type,515++phy->roc_token_id);516if (err < 0) {517clear_bit(MT76_STATE_ROC, &phy->mt76->state);518goto out;519}520521if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, 4 * HZ)) {522mt7925_mcu_abort_roc(phy, mconf, phy->roc_token_id);523clear_bit(MT76_STATE_ROC, &phy->mt76->state);524err = -ETIMEDOUT;525}526527out:528return err;529}530531static int mt7925_set_mlo_roc(struct mt792x_phy *phy,532struct mt792x_bss_conf *mconf,533u16 sel_links)534{535int err;536537if (WARN_ON_ONCE(test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state)))538return -EBUSY;539540phy->roc_grant = false;541542err = mt7925_mcu_set_mlo_roc(mconf, sel_links, 5, ++phy->roc_token_id);543if (err < 0) {544clear_bit(MT76_STATE_ROC, &phy->mt76->state);545goto out;546}547548if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, 4 * HZ)) {549mt7925_mcu_abort_roc(phy, mconf, phy->roc_token_id);550clear_bit(MT76_STATE_ROC, &phy->mt76->state);551err = -ETIMEDOUT;552}553554out:555return err;556}557558static int mt7925_remain_on_channel(struct ieee80211_hw *hw,559struct ieee80211_vif *vif,560struct ieee80211_channel *chan,561int duration,562enum ieee80211_roc_type type)563{564struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;565struct mt792x_phy *phy = mt792x_hw_phy(hw);566int err;567568mt792x_mutex_acquire(phy->dev);569err = mt7925_set_roc(phy, &mvif->bss_conf,570chan, duration, MT7925_ROC_REQ_ROC);571mt792x_mutex_release(phy->dev);572573return err;574}575576static int mt7925_cancel_remain_on_channel(struct ieee80211_hw *hw,577struct ieee80211_vif *vif)578{579struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;580struct mt792x_phy *phy = mt792x_hw_phy(hw);581582return mt7925_abort_roc(phy, &mvif->bss_conf);583}584585static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,586struct ieee80211_vif *vif, struct ieee80211_sta *sta,587struct ieee80211_key_conf *key, int link_id)588{589struct mt792x_dev *dev = mt792x_hw_dev(hw);590struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;591struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv :592&mvif->sta;593struct ieee80211_bss_conf *link_conf;594struct ieee80211_link_sta *link_sta;595int idx = key->keyidx, err = 0;596struct mt792x_link_sta *mlink;597struct mt792x_bss_conf *mconf;598struct mt76_wcid *wcid;599u8 *wcid_keyidx;600601link_conf = mt792x_vif_to_bss_conf(vif, link_id);602link_sta = sta ? mt792x_sta_to_link_sta(vif, sta, link_id) : NULL;603mconf = mt792x_vif_to_link(mvif, link_id);604mlink = mt792x_sta_to_link(msta, link_id);605wcid = &mlink->wcid;606wcid_keyidx = &wcid->hw_key_idx;607608/* fall back to sw encryption for unsupported ciphers */609switch (key->cipher) {610case WLAN_CIPHER_SUITE_AES_CMAC:611key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;612wcid_keyidx = &wcid->hw_key_idx2;613break;614case WLAN_CIPHER_SUITE_WEP40:615case WLAN_CIPHER_SUITE_WEP104:616if (!mvif->wep_sta)617return -EOPNOTSUPP;618break;619case WLAN_CIPHER_SUITE_TKIP:620case WLAN_CIPHER_SUITE_CCMP:621case WLAN_CIPHER_SUITE_CCMP_256:622case WLAN_CIPHER_SUITE_GCMP:623case WLAN_CIPHER_SUITE_GCMP_256:624case WLAN_CIPHER_SUITE_SMS4:625break;626default:627return -EOPNOTSUPP;628}629630if (cmd == SET_KEY && !mconf->mt76.cipher) {631struct mt792x_phy *phy = mt792x_hw_phy(hw);632633mconf->mt76.cipher = mt7925_mcu_get_cipher(key->cipher);634mt7925_mcu_add_bss_info(phy, mconf->mt76.ctx, link_conf,635link_sta, true);636}637638if (cmd == SET_KEY)639*wcid_keyidx = idx;640else if (idx == *wcid_keyidx)641*wcid_keyidx = -1;642else643goto out;644645mt76_wcid_key_setup(&dev->mt76, wcid,646cmd == SET_KEY ? key : NULL);647648err = mt7925_mcu_add_key(&dev->mt76, vif, &mlink->bip,649key, MCU_UNI_CMD(STA_REC_UPDATE),650&mlink->wcid, cmd, msta);651652if (err)653goto out;654655if (key->cipher == WLAN_CIPHER_SUITE_WEP104 ||656key->cipher == WLAN_CIPHER_SUITE_WEP40)657err = mt7925_mcu_add_key(&dev->mt76, vif, &mvif->wep_sta->deflink.bip,658key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),659&mvif->wep_sta->deflink.wcid, cmd, msta);660out:661return err;662}663664static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,665struct ieee80211_vif *vif, struct ieee80211_sta *sta,666struct ieee80211_key_conf *key)667{668struct mt792x_dev *dev = mt792x_hw_dev(hw);669struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;670struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv :671&mvif->sta;672int err;673674/* The hardware does not support per-STA RX GTK, fallback675* to software mode for these.676*/677if ((vif->type == NL80211_IFTYPE_ADHOC ||678vif->type == NL80211_IFTYPE_MESH_POINT) &&679(key->cipher == WLAN_CIPHER_SUITE_TKIP ||680key->cipher == WLAN_CIPHER_SUITE_CCMP) &&681!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))682return -EOPNOTSUPP;683684mt792x_mutex_acquire(dev);685686if (ieee80211_vif_is_mld(vif)) {687unsigned int link_id;688unsigned long add;689690add = key->link_id != -1 ? BIT(key->link_id) : msta->valid_links;691692for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {693err = mt7925_set_link_key(hw, cmd, vif, sta, key, link_id);694if (err < 0)695break;696}697} else {698err = mt7925_set_link_key(hw, cmd, vif, sta, key, vif->bss_conf.link_id);699}700701mt792x_mutex_release(dev);702703return err;704}705706static void707mt7925_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)708{709struct mt792x_dev *dev = priv;710struct ieee80211_hw *hw = mt76_hw(dev);711bool pm_enable = dev->pm.enable;712int err;713714err = mt7925_mcu_set_beacon_filter(dev, vif, pm_enable);715if (err < 0)716return;717718if (pm_enable) {719vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;720ieee80211_hw_set(hw, CONNECTION_MONITOR);721} else {722vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;723__clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags);724}725}726727static void728mt7925_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)729{730struct mt792x_dev *dev = priv;731struct ieee80211_hw *hw = mt76_hw(dev);732struct mt76_connac_pm *pm = &dev->pm;733bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);734735mt7925_mcu_set_sniffer(dev, vif, monitor);736pm->enable = pm->enable_user && !monitor;737pm->ds_enable = pm->ds_enable_user && !monitor;738739mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);740741if (monitor)742mt7925_mcu_set_beacon_filter(dev, vif, false);743}744745void mt7925_set_runtime_pm(struct mt792x_dev *dev)746{747struct ieee80211_hw *hw = mt76_hw(dev);748struct mt76_connac_pm *pm = &dev->pm;749bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);750751pm->enable = pm->enable_user && !monitor;752ieee80211_iterate_active_interfaces(hw,753IEEE80211_IFACE_ITER_RESUME_ALL,754mt7925_pm_interface_iter, dev);755pm->ds_enable = pm->ds_enable_user && !monitor;756mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);757}758759static int mt7925_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)760{761struct mt792x_dev *dev = mt792x_hw_dev(hw);762int ret = 0;763764mt792x_mutex_acquire(dev);765766if (changed & IEEE80211_CONF_CHANGE_POWER) {767ret = mt7925_set_tx_sar_pwr(hw, NULL);768if (ret)769goto out;770}771772if (changed & IEEE80211_CONF_CHANGE_MONITOR) {773ieee80211_iterate_active_interfaces(hw,774IEEE80211_IFACE_ITER_RESUME_ALL,775mt7925_sniffer_interface_iter, dev);776}777778out:779mt792x_mutex_release(dev);780781return ret;782}783784static void mt7925_configure_filter(struct ieee80211_hw *hw,785unsigned int changed_flags,786unsigned int *total_flags,787u64 multicast)788{789#define MT7925_FILTER_FCSFAIL BIT(2)790#define MT7925_FILTER_CONTROL BIT(5)791#define MT7925_FILTER_OTHER_BSS BIT(6)792#define MT7925_FILTER_ENABLE BIT(31)793struct mt792x_dev *dev = mt792x_hw_dev(hw);794u32 flags = MT7925_FILTER_ENABLE;795796#define MT7925_FILTER(_fif, _type) do { \797if (*total_flags & (_fif)) \798flags |= MT7925_FILTER_##_type; \799} while (0)800801MT7925_FILTER(FIF_FCSFAIL, FCSFAIL);802MT7925_FILTER(FIF_CONTROL, CONTROL);803MT7925_FILTER(FIF_OTHER_BSS, OTHER_BSS);804805mt792x_mutex_acquire(dev);806mt7925_mcu_set_rxfilter(dev, flags, 0, 0);807mt792x_mutex_release(dev);808809*total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL);810}811812static u8813mt7925_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,814bool beacon, bool mcast)815{816struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;817struct mt76_phy *mphy = hw->priv;818u16 rate;819u8 i, idx, ht;820821rate = mt76_connac2_mac_tx_rate_val(mphy, &vif->bss_conf, beacon, mcast);822ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM;823824if (beacon && ht) {825struct mt792x_dev *dev = mt792x_hw_dev(hw);826827/* must odd index */828idx = MT7925_BEACON_RATES_TBL + 2 * (mvif->idx % 20);829mt7925_mac_set_fixed_rate_table(dev, idx, rate);830return idx;831}832833idx = FIELD_GET(MT_TX_RATE_IDX, rate);834for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)835if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)836return MT792x_BASIC_RATES_TBL + i;837838return mvif->basic_rates_idx;839}840841static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,842struct ieee80211_vif *vif,843struct ieee80211_link_sta *link_sta)844{845struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);846struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;847struct ieee80211_bss_conf *link_conf;848struct mt792x_bss_conf *mconf;849u8 link_id = link_sta->link_id;850struct mt792x_link_sta *mlink;851struct mt792x_sta *msta;852struct mt76_wcid *wcid;853int ret, idx;854855msta = (struct mt792x_sta *)link_sta->sta->drv_priv;856mlink = mt792x_sta_to_link(msta, link_id);857858idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);859if (idx < 0)860return -ENOSPC;861862mconf = mt792x_vif_to_link(mvif, link_id);863mt76_wcid_init(&mlink->wcid, 0);864mlink->wcid.sta = 1;865mlink->wcid.idx = idx;866mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET;867mlink->last_txs = jiffies;868mlink->wcid.link_id = link_sta->link_id;869mlink->wcid.link_valid = !!link_sta->sta->valid_links;870mlink->sta = msta;871872wcid = &mlink->wcid;873ewma_signal_init(&wcid->rssi);874rcu_assign_pointer(dev->mt76.wcid[wcid->idx], wcid);875mt76_wcid_init(wcid, 0);876ewma_avg_signal_init(&mlink->avg_ack_signal);877memset(mlink->airtime_ac, 0,878sizeof(msta->deflink.airtime_ac));879880ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm);881if (ret)882return ret;883884mt7925_mac_wtbl_update(dev, idx,885MT_WTBL_UPDATE_ADM_COUNT_CLEAR);886887link_conf = mt792x_vif_to_bss_conf(vif, link_id);888889/* should update bss info before STA add */890if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) {891if (ieee80211_vif_is_mld(vif))892mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,893link_conf, link_sta, link_sta != mlink->pri_link);894else895mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,896link_conf, link_sta, false);897}898899if (ieee80211_vif_is_mld(vif) &&900link_sta == mlink->pri_link) {901ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,902MT76_STA_INFO_STATE_NONE);903if (ret)904return ret;905} else if (ieee80211_vif_is_mld(vif) &&906link_sta != mlink->pri_link) {907ret = mt7925_mcu_sta_update(dev, mlink->pri_link, vif,908true, MT76_STA_INFO_STATE_ASSOC);909if (ret)910return ret;911912ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,913MT76_STA_INFO_STATE_ASSOC);914if (ret)915return ret;916} else {917ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,918MT76_STA_INFO_STATE_NONE);919if (ret)920return ret;921}922923mt76_connac_power_save_sched(&dev->mphy, &dev->pm);924925return 0;926}927928static int929mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,930struct ieee80211_sta *sta, unsigned long new_links)931{932struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;933unsigned int link_id;934int err = 0;935936for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {937struct ieee80211_link_sta *link_sta;938struct mt792x_link_sta *mlink;939940if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {941mlink = &msta->deflink;942msta->deflink_id = link_id;943} else {944mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink), GFP_KERNEL);945if (!mlink) {946err = -ENOMEM;947break;948}949}950951msta->valid_links |= BIT(link_id);952rcu_assign_pointer(msta->link[link_id], mlink);953mlink->sta = msta;954mlink->pri_link = &sta->deflink;955mlink->wcid.def_wcid = &msta->deflink.wcid;956957link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);958mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta);959}960961return err;962}963964int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,965struct ieee80211_sta *sta)966{967struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);968struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;969struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;970int err;971972msta->vif = mvif;973974if (vif->type == NL80211_IFTYPE_STATION)975mvif->wep_sta = msta;976977if (ieee80211_vif_is_mld(vif)) {978msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;979980err = mt7925_mac_sta_add_links(dev, vif, sta, sta->valid_links);981} else {982err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink);983}984985return err;986}987EXPORT_SYMBOL_GPL(mt7925_mac_sta_add);988989static u16990mt7925_mac_select_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)991{992unsigned long usable_links = ieee80211_vif_usable_links(vif);993struct {994u8 link_id;995enum nl80211_band band;996} data[IEEE80211_MLD_MAX_NUM_LINKS];997u8 link_id, i, j, n_data = 0;998u16 sel_links = 0;9991000if (!ieee80211_vif_is_mld(vif))1001return 0;10021003if (vif->active_links == usable_links)1004return vif->active_links;10051006rcu_read_lock();1007for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {1008struct ieee80211_bss_conf *link_conf =1009rcu_dereference(vif->link_conf[link_id]);10101011if (WARN_ON_ONCE(!link_conf))1012continue;10131014data[n_data].link_id = link_id;1015data[n_data].band = link_conf->chanreq.oper.chan->band;1016n_data++;1017}1018rcu_read_unlock();10191020for (i = 0; i < n_data; i++) {1021if (!(BIT(data[i].link_id) & vif->active_links))1022continue;10231024sel_links = BIT(data[i].link_id);10251026for (j = 0; j < n_data; j++) {1027if (data[i].band != data[j].band) {1028sel_links |= BIT(data[j].link_id);1029break;1030}1031}10321033break;1034}10351036return sel_links;1037}10381039static void1040mt7925_mac_set_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)1041{1042struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);1043struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1044struct ieee80211_bss_conf *link_conf =1045mt792x_vif_to_bss_conf(vif, mvif->deflink_id);1046struct cfg80211_chan_def *chandef = &link_conf->chanreq.oper;1047enum nl80211_band band = chandef->chan->band, secondary_band;10481049u16 sel_links = mt7925_mac_select_links(mdev, vif);1050u8 secondary_link_id = __ffs(~BIT(mvif->deflink_id) & sel_links);10511052if (!ieee80211_vif_is_mld(vif) || hweight16(sel_links) < 2)1053return;10541055link_conf = mt792x_vif_to_bss_conf(vif, secondary_link_id);1056secondary_band = link_conf->chanreq.oper.chan->band;10571058if (band == NL80211_BAND_2GHZ ||1059(band == NL80211_BAND_5GHZ && secondary_band == NL80211_BAND_6GHZ)) {1060mt7925_abort_roc(mvif->phy, &mvif->bss_conf);10611062mt792x_mutex_acquire(dev);10631064mt7925_set_mlo_roc(mvif->phy, &mvif->bss_conf, sel_links);10651066mt792x_mutex_release(dev);1067}10681069ieee80211_set_active_links_async(vif, sel_links);1070}10711072static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev,1073struct ieee80211_vif *vif,1074struct ieee80211_link_sta *link_sta)1075{1076struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);1077struct ieee80211_bss_conf *link_conf;1078struct mt792x_link_sta *mlink;1079struct mt792x_sta *msta;10801081msta = (struct mt792x_sta *)link_sta->sta->drv_priv;1082mlink = mt792x_sta_to_link(msta, link_sta->link_id);10831084mt792x_mutex_acquire(dev);10851086if (ieee80211_vif_is_mld(vif)) {1087link_conf = mt792x_vif_to_bss_conf(vif, msta->deflink_id);1088} else {1089link_conf = mt792x_vif_to_bss_conf(vif, vif->bss_conf.link_id);1090}10911092if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) {1093struct mt792x_bss_conf *mconf;10941095mconf = mt792x_link_conf_to_mconf(link_conf);1096mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,1097link_conf, link_sta, true);1098}10991100ewma_avg_signal_init(&mlink->avg_ack_signal);11011102mt7925_mac_wtbl_update(dev, mlink->wcid.idx,1103MT_WTBL_UPDATE_ADM_COUNT_CLEAR);1104memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac));11051106mt7925_mcu_sta_update(dev, link_sta, vif, true, MT76_STA_INFO_STATE_ASSOC);11071108mt792x_mutex_release(dev);1109}11101111int mt7925_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,1112struct ieee80211_sta *sta, enum mt76_sta_event ev)1113{1114struct ieee80211_link_sta *link_sta = &sta->deflink;11151116if (ev != MT76_STA_EVENT_ASSOC)1117return 0;11181119if (ieee80211_vif_is_mld(vif)) {1120struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;11211122link_sta = mt792x_sta_to_link_sta(vif, sta, msta->deflink_id);1123mt7925_mac_set_links(mdev, vif);1124}11251126mt7925_mac_link_sta_assoc(mdev, vif, link_sta);11271128return 0;1129}1130EXPORT_SYMBOL_GPL(mt7925_mac_sta_event);11311132static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,1133struct ieee80211_vif *vif,1134struct ieee80211_link_sta *link_sta)1135{1136struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);1137struct ieee80211_bss_conf *link_conf;1138u8 link_id = link_sta->link_id;1139struct mt792x_link_sta *mlink;1140struct mt792x_sta *msta;11411142msta = (struct mt792x_sta *)link_sta->sta->drv_priv;1143mlink = mt792x_sta_to_link(msta, link_id);11441145mt7925_roc_abort_sync(dev);11461147mt76_connac_free_pending_tx_skbs(&dev->pm, &mlink->wcid);1148mt76_connac_pm_wake(&dev->mphy, &dev->pm);11491150mt7925_mcu_sta_update(dev, link_sta, vif, false,1151MT76_STA_INFO_STATE_NONE);1152mt7925_mac_wtbl_update(dev, mlink->wcid.idx,1153MT_WTBL_UPDATE_ADM_COUNT_CLEAR);11541155link_conf = mt792x_vif_to_bss_conf(vif, link_id);11561157if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) {1158struct mt792x_bss_conf *mconf;11591160mconf = mt792x_link_conf_to_mconf(link_conf);11611162if (ieee80211_vif_is_mld(vif))1163mt792x_mac_link_bss_remove(dev, mconf, mlink);1164else1165mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf,1166link_sta, false);1167}11681169spin_lock_bh(&mdev->sta_poll_lock);1170if (!list_empty(&mlink->wcid.poll_list))1171list_del_init(&mlink->wcid.poll_list);1172spin_unlock_bh(&mdev->sta_poll_lock);11731174mt76_connac_power_save_sched(&dev->mphy, &dev->pm);1175}11761177static int1178mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,1179struct ieee80211_sta *sta, unsigned long old_links)1180{1181struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;1182struct mt76_dev *mdev = &dev->mt76;1183struct mt76_wcid *wcid;1184unsigned int link_id;11851186/* clean up bss before starec */1187for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) {1188struct ieee80211_link_sta *link_sta;1189struct ieee80211_bss_conf *link_conf;1190struct mt792x_bss_conf *mconf;1191struct mt792x_link_sta *mlink;11921193if (vif->type == NL80211_IFTYPE_AP)1194break;11951196link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);1197if (!link_sta)1198continue;11991200mlink = mt792x_sta_to_link(msta, link_id);1201if (!mlink)1202continue;12031204link_conf = mt792x_vif_to_bss_conf(vif, link_id);1205if (!link_conf)1206continue;12071208mconf = mt792x_link_conf_to_mconf(link_conf);12091210mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf,1211link_sta, false);1212}12131214for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) {1215struct ieee80211_link_sta *link_sta;1216struct mt792x_link_sta *mlink;12171218link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);1219if (!link_sta)1220continue;12211222mlink = mt792x_sta_to_link(msta, link_id);1223if (!mlink)1224continue;12251226mt7925_mac_link_sta_remove(&dev->mt76, vif, link_sta);12271228wcid = &mlink->wcid;1229rcu_assign_pointer(msta->link[link_id], NULL);1230msta->valid_links &= ~BIT(link_id);1231mlink->sta = NULL;1232mlink->pri_link = NULL;12331234if (link_sta != mlink->pri_link) {1235mt76_wcid_cleanup(mdev, wcid);1236mt76_wcid_mask_clear(mdev->wcid_mask, wcid->idx);1237}12381239if (msta->deflink_id == link_id)1240msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;1241}12421243return 0;1244}12451246void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,1247struct ieee80211_sta *sta)1248{1249struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);1250struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;1251struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1252unsigned long rem;12531254rem = ieee80211_vif_is_mld(vif) ? msta->valid_links : BIT(0);12551256mt7925_mac_sta_remove_links(dev, vif, sta, rem);12571258if (ieee80211_vif_is_mld(vif))1259mt7925_mcu_del_dev(mdev, vif);12601261if (vif->type == NL80211_IFTYPE_STATION) {1262mvif->wep_sta = NULL;1263ewma_rssi_init(&mvif->bss_conf.rssi);1264}12651266mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC;1267}1268EXPORT_SYMBOL_GPL(mt7925_mac_sta_remove);12691270static int mt7925_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,1271u32 val)1272{1273struct mt792x_dev *dev = mt792x_hw_dev(hw);12741275mt792x_mutex_acquire(dev);1276mt7925_mcu_set_rts_thresh(&dev->phy, val);1277mt792x_mutex_release(dev);12781279return 0;1280}12811282static int1283mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1284struct ieee80211_ampdu_params *params)1285{1286enum ieee80211_ampdu_mlme_action action = params->action;1287struct mt792x_dev *dev = mt792x_hw_dev(hw);1288struct ieee80211_sta *sta = params->sta;1289struct ieee80211_txq *txq = sta->txq[params->tid];1290struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;1291u16 tid = params->tid;1292u16 ssn = params->ssn;1293struct mt76_txq *mtxq;1294int ret = 0;12951296if (!txq)1297return -EINVAL;12981299mtxq = (struct mt76_txq *)txq->drv_priv;13001301mt792x_mutex_acquire(dev);1302switch (action) {1303case IEEE80211_AMPDU_RX_START:1304mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid, ssn,1305params->buf_size);1306mt7925_mcu_uni_rx_ba(dev, params, true);1307break;1308case IEEE80211_AMPDU_RX_STOP:1309mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid);1310mt7925_mcu_uni_rx_ba(dev, params, false);1311break;1312case IEEE80211_AMPDU_TX_OPERATIONAL:1313mtxq->aggr = true;1314mtxq->send_bar = false;1315mt7925_mcu_uni_tx_ba(dev, params, true);1316break;1317case IEEE80211_AMPDU_TX_STOP_FLUSH:1318case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:1319mtxq->aggr = false;1320clear_bit(tid, &msta->deflink.wcid.ampdu_state);1321mt7925_mcu_uni_tx_ba(dev, params, false);1322break;1323case IEEE80211_AMPDU_TX_START:1324set_bit(tid, &msta->deflink.wcid.ampdu_state);1325ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;1326break;1327case IEEE80211_AMPDU_TX_STOP_CONT:1328mtxq->aggr = false;1329clear_bit(tid, &msta->deflink.wcid.ampdu_state);1330mt7925_mcu_uni_tx_ba(dev, params, false);1331ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);1332break;1333}1334mt792x_mutex_release(dev);13351336return ret;1337}13381339static void1340mt7925_mlo_pm_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)1341{1342struct mt792x_dev *dev = priv;1343struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1344unsigned long valid = ieee80211_vif_is_mld(vif) ?1345mvif->valid_links : BIT(0);1346struct ieee80211_bss_conf *bss_conf;1347int i;13481349if (mvif->mlo_pm_state != MT792x_MLO_CHANGED_PS)1350return;13511352mt792x_mutex_acquire(dev);1353for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {1354bss_conf = mt792x_vif_to_bss_conf(vif, i);1355mt7925_mcu_uni_bss_ps(dev, bss_conf);1356}1357mt792x_mutex_release(dev);1358}13591360void mt7925_mlo_pm_work(struct work_struct *work)1361{1362struct mt792x_dev *dev = container_of(work, struct mt792x_dev,1363mlo_pm_work.work);1364struct ieee80211_hw *hw = mt76_hw(dev);13651366ieee80211_iterate_active_interfaces(hw,1367IEEE80211_IFACE_ITER_RESUME_ALL,1368mt7925_mlo_pm_iter, dev);1369}13701371static bool is_valid_alpha2(const char *alpha2)1372{1373if (!alpha2)1374return false;13751376if (alpha2[0] == '0' && alpha2[1] == '0')1377return true;13781379if (isalpha(alpha2[0]) && isalpha(alpha2[1]))1380return true;13811382return false;1383}13841385void mt7925_scan_work(struct work_struct *work)1386{1387struct mt792x_phy *phy;13881389phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy,1390scan_work.work);13911392while (true) {1393struct mt76_dev *mdev = &phy->dev->mt76;1394struct sk_buff *skb;1395struct tlv *tlv;1396int tlv_len;13971398spin_lock_bh(&phy->dev->mt76.lock);1399skb = __skb_dequeue(&phy->scan_event_list);1400spin_unlock_bh(&phy->dev->mt76.lock);14011402if (!skb)1403break;14041405skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4);1406tlv = (struct tlv *)skb->data;1407tlv_len = skb->len;14081409while (tlv_len > 0 && le16_to_cpu(tlv->len) <= tlv_len) {1410struct mt7925_mcu_scan_chinfo_event *evt;14111412switch (le16_to_cpu(tlv->tag)) {1413case UNI_EVENT_SCAN_DONE_BASIC:1414if (test_and_clear_bit(MT76_HW_SCANNING, &phy->mt76->state)) {1415struct cfg80211_scan_info info = {1416.aborted = false,1417};1418ieee80211_scan_completed(phy->mt76->hw, &info);1419}1420break;1421case UNI_EVENT_SCAN_DONE_CHNLINFO:1422evt = (struct mt7925_mcu_scan_chinfo_event *)tlv->data;14231424if (!is_valid_alpha2(evt->alpha2))1425break;14261427mt7925_regd_be_ctrl(phy->dev, evt->alpha2);14281429if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')1430break;14311432mt7925_mcu_set_clc(phy->dev, evt->alpha2, ENVIRON_INDOOR);14331434break;1435case UNI_EVENT_SCAN_DONE_NLO:1436ieee80211_sched_scan_results(phy->mt76->hw);1437break;1438default:1439break;1440}14411442tlv_len -= le16_to_cpu(tlv->len);1443tlv = (struct tlv *)((char *)(tlv) + le16_to_cpu(tlv->len));1444}14451446dev_kfree_skb(skb);1447}1448}14491450static int1451mt7925_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1452struct ieee80211_scan_request *req)1453{1454struct mt792x_dev *dev = mt792x_hw_dev(hw);1455struct mt76_phy *mphy = hw->priv;1456int err;14571458mt792x_mutex_acquire(dev);1459err = mt7925_mcu_hw_scan(mphy, vif, req);1460mt792x_mutex_release(dev);14611462return err;1463}14641465static void1466mt7925_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)1467{1468struct mt792x_dev *dev = mt792x_hw_dev(hw);1469struct mt76_phy *mphy = hw->priv;14701471mt792x_mutex_acquire(dev);1472mt7925_mcu_cancel_hw_scan(mphy, vif);1473mt792x_mutex_release(dev);1474}14751476static int1477mt7925_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1478struct cfg80211_sched_scan_request *req,1479struct ieee80211_scan_ies *ies)1480{1481struct mt792x_dev *dev = mt792x_hw_dev(hw);1482struct mt76_phy *mphy = hw->priv;1483int err;14841485mt792x_mutex_acquire(dev);14861487err = mt7925_mcu_sched_scan_req(mphy, vif, req, ies);1488if (err < 0)1489goto out;14901491err = mt7925_mcu_sched_scan_enable(mphy, vif, true);1492out:1493mt792x_mutex_release(dev);14941495return err;1496}14971498static int1499mt7925_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)1500{1501struct mt792x_dev *dev = mt792x_hw_dev(hw);1502struct mt76_phy *mphy = hw->priv;1503int err;15041505mt792x_mutex_acquire(dev);1506err = mt7925_mcu_sched_scan_enable(mphy, vif, false);1507mt792x_mutex_release(dev);15081509return err;1510}15111512static int1513mt7925_set_antenna(struct ieee80211_hw *hw, int radio_idx,1514u32 tx_ant, u32 rx_ant)1515{1516struct mt792x_dev *dev = mt792x_hw_dev(hw);1517struct mt792x_phy *phy = mt792x_hw_phy(hw);1518int max_nss = hweight8(hw->wiphy->available_antennas_tx);15191520if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss)1521return -EINVAL;15221523if ((BIT(hweight8(tx_ant)) - 1) != tx_ant)1524tx_ant = BIT(ffs(tx_ant) - 1) - 1;15251526mt792x_mutex_acquire(dev);15271528phy->mt76->antenna_mask = tx_ant;1529phy->mt76->chainmask = tx_ant;15301531mt76_set_stream_caps(phy->mt76, true);1532mt7925_set_stream_he_eht_caps(phy);15331534/* TODO: update bmc_wtbl spe_idx when antenna changes */1535mt792x_mutex_release(dev);15361537return 0;1538}15391540#ifdef CONFIG_PM1541static int mt7925_suspend(struct ieee80211_hw *hw,1542struct cfg80211_wowlan *wowlan)1543{1544struct mt792x_dev *dev = mt792x_hw_dev(hw);1545struct mt792x_phy *phy = mt792x_hw_phy(hw);15461547cancel_delayed_work_sync(&phy->scan_work);1548cancel_delayed_work_sync(&phy->mt76->mac_work);15491550cancel_delayed_work_sync(&dev->pm.ps_work);1551mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);15521553mt792x_mutex_acquire(dev);15541555clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);1556ieee80211_iterate_active_interfaces(hw,1557IEEE80211_IFACE_ITER_RESUME_ALL,1558mt7925_mcu_set_suspend_iter,1559&dev->mphy);15601561mt792x_mutex_release(dev);15621563return 0;1564}15651566static int mt7925_resume(struct ieee80211_hw *hw)1567{1568struct mt792x_dev *dev = mt792x_hw_dev(hw);1569struct mt792x_phy *phy = mt792x_hw_phy(hw);15701571mt792x_mutex_acquire(dev);15721573set_bit(MT76_STATE_RUNNING, &phy->mt76->state);1574ieee80211_iterate_active_interfaces(hw,1575IEEE80211_IFACE_ITER_RESUME_ALL,1576mt7925_mcu_set_suspend_iter,1577&dev->mphy);15781579ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,1580MT792x_WATCHDOG_TIME);15811582mt792x_mutex_release(dev);15831584return 0;1585}15861587static void mt7925_set_rekey_data(struct ieee80211_hw *hw,1588struct ieee80211_vif *vif,1589struct cfg80211_gtk_rekey_data *data)1590{1591struct mt792x_dev *dev = mt792x_hw_dev(hw);15921593mt792x_mutex_acquire(dev);1594mt76_connac_mcu_update_gtk_rekey(hw, vif, data);1595mt792x_mutex_release(dev);1596}1597#endif /* CONFIG_PM */15981599static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,1600struct ieee80211_vif *vif,1601struct ieee80211_sta *sta,1602bool enabled)1603{1604struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;1605struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1606struct mt792x_dev *dev = mt792x_hw_dev(hw);1607unsigned long valid = mvif->valid_links;1608u8 i;16091610if (!msta->vif)1611return;16121613mt792x_mutex_acquire(dev);16141615valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0);16161617for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {1618struct mt792x_link_sta *mlink;16191620mlink = mt792x_sta_to_link(msta, i);16211622if (enabled)1623set_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags);1624else1625clear_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags);16261627if (!mlink->wcid.sta)1628continue;16291630mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta, i);1631}16321633mt792x_mutex_release(dev);1634}16351636#if IS_ENABLED(CONFIG_IPV6)1637static void __mt7925_ipv6_addr_change(struct ieee80211_hw *hw,1638struct ieee80211_bss_conf *link_conf,1639struct inet6_dev *idev)1640{1641struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);1642struct mt792x_dev *dev = mt792x_hw_dev(hw);1643struct inet6_ifaddr *ifa;1644struct sk_buff *skb;1645u8 idx = 0;16461647struct {1648struct {1649u8 bss_idx;1650u8 pad[3];1651} __packed hdr;1652struct mt7925_arpns_tlv arpns;1653struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN];1654} req_hdr = {1655.hdr = {1656.bss_idx = mconf->mt76.idx,1657},1658.arpns = {1659.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND),1660.len = cpu_to_le16(sizeof(req_hdr) - 4),1661.enable = true,1662},1663};16641665read_lock_bh(&idev->lock);1666list_for_each_entry(ifa, &idev->addr_list, if_list) {1667if (ifa->flags & IFA_F_TENTATIVE)1668continue;1669req_hdr.ns_addrs[idx] = ifa->addr;1670if (++idx >= IEEE80211_BSS_ARP_ADDR_LIST_LEN)1671break;1672}1673read_unlock_bh(&idev->lock);16741675if (!idx)1676return;16771678req_hdr.arpns.ips_num = idx;16791680skb = __mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr),16810, GFP_ATOMIC);1682if (!skb)1683return;16841685skb_put_data(skb, &req_hdr, sizeof(req_hdr));16861687skb_queue_tail(&dev->ipv6_ns_list, skb);16881689ieee80211_queue_work(dev->mt76.hw, &dev->ipv6_ns_work);1690}16911692static void mt7925_ipv6_addr_change(struct ieee80211_hw *hw,1693struct ieee80211_vif *vif,1694struct inet6_dev *idev)1695{1696struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1697unsigned long valid = ieee80211_vif_is_mld(vif) ?1698mvif->valid_links : BIT(0);1699struct ieee80211_bss_conf *bss_conf;1700int i;17011702for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {1703bss_conf = mt792x_vif_to_bss_conf(vif, i);1704__mt7925_ipv6_addr_change(hw, bss_conf, idev);1705}1706}17071708#endif17091710int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw,1711const struct cfg80211_sar_specs *sar)1712{1713struct mt76_phy *mphy = hw->priv;17141715if (sar) {1716int err = mt76_init_sar_power(hw, sar);17171718if (err)1719return err;1720}1721mt792x_init_acpi_sar_power(mt792x_hw_phy(hw), !sar);17221723return mt7925_mcu_set_rate_txpower(mphy);1724}17251726static int mt7925_set_sar_specs(struct ieee80211_hw *hw,1727const struct cfg80211_sar_specs *sar)1728{1729struct mt792x_dev *dev = mt792x_hw_dev(hw);1730int err;17311732mt792x_mutex_acquire(dev);1733err = mt7925_mcu_set_clc(dev, dev->mt76.alpha2,1734dev->country_ie_env);1735if (err < 0)1736goto out;17371738err = mt7925_set_tx_sar_pwr(hw, sar);1739out:1740mt792x_mutex_release(dev);17411742return err;1743}17441745static void1746mt7925_channel_switch_beacon(struct ieee80211_hw *hw,1747struct ieee80211_vif *vif,1748struct cfg80211_chan_def *chandef)1749{1750struct mt792x_dev *dev = mt792x_hw_dev(hw);17511752mt792x_mutex_acquire(dev);1753mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true);1754mt792x_mutex_release(dev);1755}17561757static int1758mt7925_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1759unsigned int link_id, u16 queue,1760const struct ieee80211_tx_queue_params *params)1761{1762struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1763struct mt792x_bss_conf *mconf = mt792x_vif_to_link(mvif, link_id);1764static const u8 mq_to_aci[] = {1765[IEEE80211_AC_VO] = 3,1766[IEEE80211_AC_VI] = 2,1767[IEEE80211_AC_BE] = 0,1768[IEEE80211_AC_BK] = 1,1769};17701771/* firmware uses access class index */1772mconf->queue_params[mq_to_aci[queue]] = *params;17731774return 0;1775}17761777static int1778mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1779struct ieee80211_bss_conf *link_conf)1780{1781struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1782struct mt792x_dev *dev = mt792x_hw_dev(hw);1783int err;17841785mt792x_mutex_acquire(dev);17861787err = mt7925_mcu_add_bss_info(&dev->phy, mvif->bss_conf.mt76.ctx,1788link_conf, NULL, true);1789if (err)1790goto out;17911792err = mt7925_mcu_set_bss_pm(dev, link_conf, true);1793if (err)1794goto out;17951796err = mt7925_mcu_sta_update(dev, NULL, vif, true,1797MT76_STA_INFO_STATE_NONE);1798out:1799mt792x_mutex_release(dev);18001801return err;1802}18031804static void1805mt7925_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1806struct ieee80211_bss_conf *link_conf)1807{1808struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1809struct mt792x_dev *dev = mt792x_hw_dev(hw);1810int err;18111812mt792x_mutex_acquire(dev);18131814err = mt7925_mcu_set_bss_pm(dev, link_conf, false);1815if (err)1816goto out;18171818mt7925_mcu_add_bss_info(&dev->phy, mvif->bss_conf.mt76.ctx, link_conf,1819NULL, false);18201821out:1822mt792x_mutex_release(dev);1823}18241825static int1826mt7925_add_chanctx(struct ieee80211_hw *hw,1827struct ieee80211_chanctx_conf *ctx)1828{1829return 0;1830}18311832static void1833mt7925_remove_chanctx(struct ieee80211_hw *hw,1834struct ieee80211_chanctx_conf *ctx)1835{1836}18371838static void1839mt7925_change_chanctx(struct ieee80211_hw *hw,1840struct ieee80211_chanctx_conf *ctx,1841u32 changed)1842{1843struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv;1844struct mt792x_phy *phy = mt792x_hw_phy(hw);1845struct mt792x_bss_conf *mconf;1846struct ieee80211_vif *vif;1847struct mt792x_vif *mvif;18481849if (!mctx->bss_conf)1850return;18511852mconf = mctx->bss_conf;1853mvif = mconf->vif;1854vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);18551856mt792x_mutex_acquire(phy->dev);1857if (vif->type == NL80211_IFTYPE_MONITOR) {1858mt7925_mcu_set_sniffer(mvif->phy->dev, vif, true);1859mt7925_mcu_config_sniffer(mvif, ctx);1860} else {1861if (ieee80211_vif_is_mld(vif)) {1862unsigned long valid = mvif->valid_links;1863u8 i;18641865for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {1866mconf = mt792x_vif_to_link(mvif, i);1867if (mconf && mconf->mt76.ctx == ctx)1868break;1869}18701871} else {1872mconf = &mvif->bss_conf;1873}18741875if (mconf) {1876struct ieee80211_bss_conf *link_conf;18771878link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);1879mt7925_mcu_set_chctx(mvif->phy->mt76, &mconf->mt76,1880link_conf, ctx);18811882if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)1883mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76,1884link_conf, ctx);1885}1886}18871888mt792x_mutex_release(phy->dev);1889}18901891static void mt7925_mgd_prepare_tx(struct ieee80211_hw *hw,1892struct ieee80211_vif *vif,1893struct ieee80211_prep_tx_info *info)1894{1895struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1896struct mt792x_dev *dev = mt792x_hw_dev(hw);1897u16 duration = info->duration ? info->duration :1898jiffies_to_msecs(HZ);18991900mt792x_mutex_acquire(dev);1901mt7925_set_roc(mvif->phy, &mvif->bss_conf,1902mvif->bss_conf.mt76.ctx->def.chan, duration,1903MT7925_ROC_REQ_JOIN);1904mt792x_mutex_release(dev);1905}19061907static void mt7925_mgd_complete_tx(struct ieee80211_hw *hw,1908struct ieee80211_vif *vif,1909struct ieee80211_prep_tx_info *info)1910{1911struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;19121913mt7925_abort_roc(mvif->phy, &mvif->bss_conf);1914}19151916static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw,1917struct ieee80211_vif *vif,1918u64 changed)1919{1920struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1921struct mt792x_dev *dev = mt792x_hw_dev(hw);1922unsigned long valid = ieee80211_vif_is_mld(vif) ?1923mvif->valid_links : BIT(0);1924struct ieee80211_bss_conf *bss_conf;1925int i;19261927mt792x_mutex_acquire(dev);19281929if (changed & BSS_CHANGED_ASSOC) {1930mt7925_mcu_sta_update(dev, NULL, vif, true,1931MT76_STA_INFO_STATE_ASSOC);1932mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);19331934if (ieee80211_vif_is_mld(vif))1935mvif->mlo_pm_state = MT792x_MLO_LINK_ASSOC;1936}19371938if (changed & BSS_CHANGED_ARP_FILTER) {1939for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {1940bss_conf = mt792x_vif_to_bss_conf(vif, i);1941mt7925_mcu_update_arp_filter(&dev->mt76, bss_conf);1942}1943}19441945if (changed & BSS_CHANGED_PS) {1946if (hweight16(mvif->valid_links) < 2) {1947/* legacy */1948bss_conf = &vif->bss_conf;1949mt7925_mcu_uni_bss_ps(dev, bss_conf);1950} else {1951if (mvif->mlo_pm_state == MT792x_MLO_LINK_ASSOC) {1952mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS_PENDING;1953} else if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS) {1954for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {1955bss_conf = mt792x_vif_to_bss_conf(vif, i);1956mt7925_mcu_uni_bss_ps(dev, bss_conf);1957}1958}1959}1960}19611962mt792x_mutex_release(dev);1963}19641965static void mt7925_link_info_changed(struct ieee80211_hw *hw,1966struct ieee80211_vif *vif,1967struct ieee80211_bss_conf *info,1968u64 changed)1969{1970struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;1971struct mt792x_phy *phy = mt792x_hw_phy(hw);1972struct mt792x_dev *dev = mt792x_hw_dev(hw);1973struct mt792x_bss_conf *mconf;1974struct ieee80211_bss_conf *link_conf;19751976mconf = mt792x_vif_to_link(mvif, info->link_id);1977link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);19781979mt792x_mutex_acquire(dev);19801981if (changed & BSS_CHANGED_ERP_SLOT) {1982int slottime = info->use_short_slot ? 9 : 20;19831984if (slottime != phy->slottime) {1985phy->slottime = slottime;1986mt7925_mcu_set_timing(phy, info);1987}1988}19891990if (changed & BSS_CHANGED_MCAST_RATE)1991mconf->mt76.mcast_rates_idx =1992mt7925_get_rates_table(hw, vif, false, true);19931994if (changed & BSS_CHANGED_BASIC_RATES)1995mconf->mt76.basic_rates_idx =1996mt7925_get_rates_table(hw, vif, false, false);19971998if (changed & (BSS_CHANGED_BEACON |1999BSS_CHANGED_BEACON_ENABLED)) {2000mconf->mt76.beacon_rates_idx =2001mt7925_get_rates_table(hw, vif, true, false);20022003mt7925_mcu_uni_add_beacon_offload(dev, hw, vif,2004info->enable_beacon);2005}20062007/* ensure that enable txcmd_mode after bss_info */2008if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))2009mt7925_mcu_set_tx(dev, info);20102011if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS_PENDING) {2012/* Indicate the secondary setup done */2013mt7925_mcu_uni_bss_bcnft(dev, info, true);20142015ieee80211_queue_delayed_work(hw, &dev->mlo_pm_work, 5 * HZ);2016mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS;2017}20182019if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)2020mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76,2021link_conf, NULL);20222023mt792x_mutex_release(dev);2024}20252026static int2027mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,2028u16 old_links, u16 new_links,2029struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])2030{2031struct mt792x_bss_conf *mconfs[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *mconf;2032struct mt792x_link_sta *mlinks[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *mlink;2033struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;2034unsigned long add = new_links & ~old_links;2035unsigned long rem = old_links & ~new_links;2036struct mt792x_dev *dev = mt792x_hw_dev(hw);2037struct mt792x_phy *phy = mt792x_hw_phy(hw);2038struct ieee80211_bss_conf *link_conf;2039unsigned int link_id;2040int err;20412042if (old_links == new_links)2043return 0;20442045mt792x_mutex_acquire(dev);20462047for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) {2048mconf = mt792x_vif_to_link(mvif, link_id);2049mlink = mt792x_sta_to_link(&mvif->sta, link_id);20502051if (!mconf || !mlink)2052continue;20532054if (mconf != &mvif->bss_conf) {2055mt792x_mac_link_bss_remove(dev, mconf, mlink);2056devm_kfree(dev->mt76.dev, mconf);2057devm_kfree(dev->mt76.dev, mlink);2058}20592060rcu_assign_pointer(mvif->link_conf[link_id], NULL);2061rcu_assign_pointer(mvif->sta.link[link_id], NULL);2062}20632064for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {2065if (!old_links) {2066mvif->deflink_id = link_id;2067mconf = &mvif->bss_conf;2068mlink = &mvif->sta.deflink;2069} else {2070mconf = devm_kzalloc(dev->mt76.dev, sizeof(*mconf),2071GFP_KERNEL);2072mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink),2073GFP_KERNEL);2074if (!mconf || !mlink) {2075mt792x_mutex_release(dev);2076return -ENOMEM;2077}2078}20792080mconfs[link_id] = mconf;2081mlinks[link_id] = mlink;2082mconf->link_id = link_id;2083mconf->vif = mvif;2084mlink->wcid.link_id = link_id;2085mlink->wcid.link_valid = !!vif->valid_links;2086mlink->wcid.def_wcid = &mvif->sta.deflink.wcid;2087}20882089if (hweight16(mvif->valid_links) == 0)2090mt792x_mac_link_bss_remove(dev, &mvif->bss_conf,2091&mvif->sta.deflink);20922093for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {2094mconf = mconfs[link_id];2095mlink = mlinks[link_id];2096link_conf = mt792x_vif_to_bss_conf(vif, link_id);20972098rcu_assign_pointer(mvif->link_conf[link_id], mconf);2099rcu_assign_pointer(mvif->sta.link[link_id], mlink);21002101err = mt7925_mac_link_bss_add(dev, link_conf, mlink);2102if (err < 0)2103goto free;21042105if (mconf != &mvif->bss_conf) {2106err = mt7925_set_mlo_roc(phy, &mvif->bss_conf,2107vif->active_links);2108if (err < 0)2109goto free;2110}2111}21122113mvif->valid_links = new_links;21142115mt792x_mutex_release(dev);21162117return 0;21182119free:2120for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {2121rcu_assign_pointer(mvif->link_conf[link_id], NULL);2122rcu_assign_pointer(mvif->sta.link[link_id], NULL);21232124if (mconf != &mvif->bss_conf)2125devm_kfree(dev->mt76.dev, mconfs[link_id]);2126if (mlink != &mvif->sta.deflink)2127devm_kfree(dev->mt76.dev, mlinks[link_id]);2128}21292130mt792x_mutex_release(dev);21312132return err;2133}21342135static int2136mt7925_change_sta_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,2137struct ieee80211_sta *sta, u16 old_links, u16 new_links)2138{2139unsigned long add = new_links & ~old_links;2140unsigned long rem = old_links & ~new_links;2141struct mt792x_dev *dev = mt792x_hw_dev(hw);2142int err = 0;21432144if (old_links == new_links)2145return 0;21462147mt792x_mutex_acquire(dev);21482149err = mt7925_mac_sta_remove_links(dev, vif, sta, rem);2150if (err < 0)2151goto out;21522153err = mt7925_mac_sta_add_links(dev, vif, sta, add);2154if (err < 0)2155goto out;21562157out:2158mt792x_mutex_release(dev);21592160return err;2161}21622163static int mt7925_assign_vif_chanctx(struct ieee80211_hw *hw,2164struct ieee80211_vif *vif,2165struct ieee80211_bss_conf *link_conf,2166struct ieee80211_chanctx_conf *ctx)2167{2168struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv;2169struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;2170struct mt792x_dev *dev = mt792x_hw_dev(hw);2171struct ieee80211_bss_conf *pri_link_conf;2172struct mt792x_bss_conf *mconf;21732174mutex_lock(&dev->mt76.mutex);21752176if (ieee80211_vif_is_mld(vif)) {2177mconf = mt792x_vif_to_link(mvif, link_conf->link_id);2178pri_link_conf = mt792x_vif_to_bss_conf(vif, mvif->deflink_id);21792180if (vif->type == NL80211_IFTYPE_STATION &&2181mconf == &mvif->bss_conf)2182mt7925_mcu_add_bss_info(&dev->phy, NULL, pri_link_conf,2183NULL, true);2184} else {2185mconf = &mvif->bss_conf;2186}21872188mconf->mt76.ctx = ctx;2189mctx->bss_conf = mconf;2190mutex_unlock(&dev->mt76.mutex);21912192return 0;2193}21942195static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw,2196struct ieee80211_vif *vif,2197struct ieee80211_bss_conf *link_conf,2198struct ieee80211_chanctx_conf *ctx)2199{2200struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv;2201struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;2202struct mt792x_dev *dev = mt792x_hw_dev(hw);2203struct mt792x_bss_conf *mconf;22042205mutex_lock(&dev->mt76.mutex);22062207if (ieee80211_vif_is_mld(vif)) {2208mconf = mt792x_vif_to_link(mvif, link_conf->link_id);22092210if (vif->type == NL80211_IFTYPE_STATION &&2211mconf == &mvif->bss_conf)2212mt7925_mcu_add_bss_info(&dev->phy, NULL, link_conf,2213NULL, false);2214} else {2215mconf = &mvif->bss_conf;2216}22172218mctx->bss_conf = NULL;2219mconf->mt76.ctx = NULL;2220mutex_unlock(&dev->mt76.mutex);2221}22222223static void mt7925_rfkill_poll(struct ieee80211_hw *hw)2224{2225struct mt792x_phy *phy = mt792x_hw_phy(hw);2226int ret;22272228mt792x_mutex_acquire(phy->dev);2229ret = mt7925_mcu_wf_rf_pin_ctrl(phy);2230mt792x_mutex_release(phy->dev);22312232wiphy_rfkill_set_hw_state(hw->wiphy, ret == 0);2233}22342235const struct ieee80211_ops mt7925_ops = {2236.tx = mt792x_tx,2237.start = mt7925_start,2238.stop = mt792x_stop,2239.add_interface = mt7925_add_interface,2240.remove_interface = mt792x_remove_interface,2241.config = mt7925_config,2242.conf_tx = mt7925_conf_tx,2243.configure_filter = mt7925_configure_filter,2244.start_ap = mt7925_start_ap,2245.stop_ap = mt7925_stop_ap,2246.sta_state = mt76_sta_state,2247.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,2248.set_key = mt7925_set_key,2249.sta_set_decap_offload = mt7925_sta_set_decap_offload,2250#if IS_ENABLED(CONFIG_IPV6)2251.ipv6_addr_change = mt7925_ipv6_addr_change,2252#endif /* CONFIG_IPV6 */2253.ampdu_action = mt7925_ampdu_action,2254.set_rts_threshold = mt7925_set_rts_threshold,2255.wake_tx_queue = mt76_wake_tx_queue,2256.release_buffered_frames = mt76_release_buffered_frames,2257.channel_switch_beacon = mt7925_channel_switch_beacon,2258.get_txpower = mt76_get_txpower,2259.get_stats = mt792x_get_stats,2260.get_et_sset_count = mt792x_get_et_sset_count,2261.get_et_strings = mt792x_get_et_strings,2262.get_et_stats = mt792x_get_et_stats,2263.get_tsf = mt792x_get_tsf,2264.set_tsf = mt792x_set_tsf,2265.get_survey = mt76_get_survey,2266.get_antenna = mt76_get_antenna,2267.set_antenna = mt7925_set_antenna,2268.set_coverage_class = mt792x_set_coverage_class,2269.hw_scan = mt7925_hw_scan,2270.cancel_hw_scan = mt7925_cancel_hw_scan,2271.sta_statistics = mt792x_sta_statistics,2272.sched_scan_start = mt7925_start_sched_scan,2273.sched_scan_stop = mt7925_stop_sched_scan,2274CFG80211_TESTMODE_CMD(mt7925_testmode_cmd)2275CFG80211_TESTMODE_DUMP(mt7925_testmode_dump)2276#ifdef CONFIG_PM2277.suspend = mt7925_suspend,2278.resume = mt7925_resume,2279.set_wakeup = mt792x_set_wakeup,2280.set_rekey_data = mt7925_set_rekey_data,2281#endif /* CONFIG_PM */2282.flush = mt792x_flush,2283.set_sar_specs = mt7925_set_sar_specs,2284.remain_on_channel = mt7925_remain_on_channel,2285.cancel_remain_on_channel = mt7925_cancel_remain_on_channel,2286.add_chanctx = mt7925_add_chanctx,2287.remove_chanctx = mt7925_remove_chanctx,2288.change_chanctx = mt7925_change_chanctx,2289.assign_vif_chanctx = mt7925_assign_vif_chanctx,2290.unassign_vif_chanctx = mt7925_unassign_vif_chanctx,2291.mgd_prepare_tx = mt7925_mgd_prepare_tx,2292.mgd_complete_tx = mt7925_mgd_complete_tx,2293.vif_cfg_changed = mt7925_vif_cfg_changed,2294.link_info_changed = mt7925_link_info_changed,2295.change_vif_links = mt7925_change_vif_links,2296.change_sta_links = mt7925_change_sta_links,2297.rfkill_poll = mt7925_rfkill_poll,2298};2299EXPORT_SYMBOL_GPL(mt7925_ops);23002301MODULE_AUTHOR("Deren Wu <[email protected]>");2302MODULE_DESCRIPTION("MediaTek MT7925 core driver");2303MODULE_LICENSE("Dual BSD/GPL");230423052306