Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7915/main.c
48526 views
// SPDX-License-Identifier: ISC1/* Copyright (C) 2020 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 "mt7915.h"8#include "mcu.h"910static bool mt7915_dev_running(struct mt7915_dev *dev)11{12struct mt7915_phy *phy;1314if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))15return true;1617phy = mt7915_ext_phy(dev);1819return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);20}2122int mt7915_run(struct ieee80211_hw *hw)23{24struct mt7915_dev *dev = mt7915_hw_dev(hw);25struct mt7915_phy *phy = mt7915_hw_phy(hw);26bool running;27int ret;2829running = mt7915_dev_running(dev);3031if (!running) {32ret = mt76_connac_mcu_set_pm(&dev->mt76,33dev->phy.mt76->band_idx, 0);34if (ret)35goto out;3637ret = mt7915_mcu_set_mac(dev, dev->phy.mt76->band_idx,38true, true);39if (ret)40goto out;4142mt7915_mac_enable_nf(dev, dev->phy.mt76->band_idx);43}4445if (phy != &dev->phy) {46ret = mt76_connac_mcu_set_pm(&dev->mt76,47phy->mt76->band_idx, 0);48if (ret)49goto out;5051ret = mt7915_mcu_set_mac(dev, phy->mt76->band_idx,52true, true);53if (ret)54goto out;5556mt7915_mac_enable_nf(dev, phy->mt76->band_idx);57}5859ret = mt7915_mcu_set_thermal_throttling(phy,60MT7915_THERMAL_THROTTLE_MAX);6162if (ret)63goto out;6465ret = mt7915_mcu_set_thermal_protect(phy);6667if (ret)68goto out;6970ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b,71phy->mt76->band_idx);72if (ret)73goto out;7475ret = mt7915_mcu_set_sku_en(phy, true);76if (ret)77goto out;7879ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));80if (ret)81goto out;8283set_bit(MT76_STATE_RUNNING, &phy->mt76->state);8485if (!mt76_testmode_enabled(phy->mt76))86ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,87MT7915_WATCHDOG_TIME);8889if (!running)90mt7915_mac_reset_counters(phy);9192out:93return ret;94}9596static int mt7915_start(struct ieee80211_hw *hw)97{98struct mt7915_dev *dev = mt7915_hw_dev(hw);99int ret;100101flush_work(&dev->init_work);102103mutex_lock(&dev->mt76.mutex);104ret = mt7915_run(hw);105mutex_unlock(&dev->mt76.mutex);106107return ret;108}109110static void mt7915_stop(struct ieee80211_hw *hw, bool suspend)111{112struct mt7915_dev *dev = mt7915_hw_dev(hw);113struct mt7915_phy *phy = mt7915_hw_phy(hw);114115cancel_delayed_work_sync(&phy->mt76->mac_work);116117mutex_lock(&dev->mt76.mutex);118119mt76_testmode_reset(phy->mt76, true);120121clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);122123if (phy != &dev->phy) {124mt76_connac_mcu_set_pm(&dev->mt76, phy->mt76->band_idx, 1);125mt7915_mcu_set_mac(dev, phy->mt76->band_idx, false, false);126}127128if (!mt7915_dev_running(dev)) {129mt76_connac_mcu_set_pm(&dev->mt76, dev->phy.mt76->band_idx, 1);130mt7915_mcu_set_mac(dev, dev->phy.mt76->band_idx, false, false);131}132133mutex_unlock(&dev->mt76.mutex);134}135136static inline int get_free_idx(u32 mask, u8 start, u8 end)137{138return ffs(~mask & GENMASK(end, start));139}140141static int get_omac_idx(enum nl80211_iftype type, u64 mask)142{143int i;144145switch (type) {146case NL80211_IFTYPE_MESH_POINT:147case NL80211_IFTYPE_ADHOC:148case NL80211_IFTYPE_STATION:149/* prefer hw bssid slot 1-3 */150i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3);151if (i)152return i - 1;153154if (type != NL80211_IFTYPE_STATION)155break;156157i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);158if (i)159return i - 1;160161if (~mask & BIT(HW_BSSID_0))162return HW_BSSID_0;163164break;165case NL80211_IFTYPE_MONITOR:166case NL80211_IFTYPE_AP:167/* ap uses hw bssid 0 and ext bssid */168if (~mask & BIT(HW_BSSID_0))169return HW_BSSID_0;170171i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);172if (i)173return i - 1;174175break;176default:177WARN_ON(1);178break;179}180181return -1;182}183184static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)185{186struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;187int i;188189for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) {190mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;191mvif->bitrate_mask.control[i].he_gi = 0xff;192mvif->bitrate_mask.control[i].he_ltf = 0xff;193mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0);194memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff,195sizeof(mvif->bitrate_mask.control[i].ht_mcs));196memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff,197sizeof(mvif->bitrate_mask.control[i].vht_mcs));198memset(mvif->bitrate_mask.control[i].he_mcs, 0xff,199sizeof(mvif->bitrate_mask.control[i].he_mcs));200}201}202203static int mt7915_add_interface(struct ieee80211_hw *hw,204struct ieee80211_vif *vif)205{206struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;207struct mt7915_dev *dev = mt7915_hw_dev(hw);208struct mt7915_phy *phy = mt7915_hw_phy(hw);209struct mt76_txq *mtxq;210bool ext_phy = phy != &dev->phy;211int idx, ret = 0;212213mutex_lock(&dev->mt76.mutex);214215mt76_testmode_reset(phy->mt76, true);216217if (vif->type == NL80211_IFTYPE_MONITOR &&218is_zero_ether_addr(vif->addr))219phy->monitor_vif = vif;220221mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);222if (mvif->mt76.idx >= (MT7915_MAX_INTERFACES << dev->dbdc_support)) {223ret = -ENOSPC;224goto out;225}226227idx = get_omac_idx(vif->type, phy->omac_mask);228if (idx < 0) {229ret = -ENOSPC;230goto out;231}232mvif->mt76.omac_idx = idx;233mvif->phy = phy;234mvif->mt76.band_idx = phy->mt76->band_idx;235mvif->mt76.wcid = &mvif->sta.wcid;236237mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP;238if (ext_phy)239mvif->mt76.wmm_idx += 2;240241ret = mt7915_mcu_add_dev_info(phy, vif, true);242if (ret)243goto out;244245dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);246phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);247248idx = mt76_wcid_alloc(dev->mt76.wcid_mask, mt7915_wtbl_size(dev));249if (idx < 0) {250ret = -ENOSPC;251goto out;252}253254INIT_LIST_HEAD(&mvif->sta.rc_list);255mvif->sta.wcid.idx = idx;256mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;257mt76_wcid_init(&mvif->sta.wcid, phy->mt76->band_idx);258259mt7915_mac_wtbl_update(dev, idx,260MT_WTBL_UPDATE_ADM_COUNT_CLEAR);261262if (vif->txq) {263mtxq = (struct mt76_txq *)vif->txq->drv_priv;264mtxq->wcid = idx;265}266267if (vif->type != NL80211_IFTYPE_AP &&268(!mvif->mt76.omac_idx || mvif->mt76.omac_idx > 3))269vif->offload_flags = 0;270vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;271272mt7915_init_bitrate_mask(vif);273memset(&mvif->cap, -1, sizeof(mvif->cap));274275mt7915_mcu_add_bss_info(phy, vif, true);276mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, true);277rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);278279out:280mutex_unlock(&dev->mt76.mutex);281282return ret;283}284285static void mt7915_remove_interface(struct ieee80211_hw *hw,286struct ieee80211_vif *vif)287{288struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;289struct mt7915_sta *msta = &mvif->sta;290struct mt7915_dev *dev = mt7915_hw_dev(hw);291struct mt7915_phy *phy = mt7915_hw_phy(hw);292int idx = msta->wcid.idx;293294mt7915_mcu_add_bss_info(phy, vif, false);295mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false);296mt76_wcid_mask_clear(dev->mt76.wcid_mask, mvif->sta.wcid.idx);297298mutex_lock(&dev->mt76.mutex);299mt76_testmode_reset(phy->mt76, true);300mutex_unlock(&dev->mt76.mutex);301302if (vif == phy->monitor_vif)303phy->monitor_vif = NULL;304305mt7915_mcu_add_dev_info(phy, vif, false);306307rcu_assign_pointer(dev->mt76.wcid[idx], NULL);308309mutex_lock(&dev->mt76.mutex);310dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);311phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);312mutex_unlock(&dev->mt76.mutex);313314spin_lock_bh(&dev->mt76.sta_poll_lock);315if (!list_empty(&msta->wcid.poll_list))316list_del_init(&msta->wcid.poll_list);317spin_unlock_bh(&dev->mt76.sta_poll_lock);318319mt76_wcid_cleanup(&dev->mt76, &msta->wcid);320}321322int mt7915_set_channel(struct mt76_phy *mphy)323{324struct mt7915_phy *phy = mphy->priv;325struct mt7915_dev *dev = phy->dev;326int ret;327328if (dev->cal) {329ret = mt7915_mcu_apply_tx_dpd(phy);330if (ret)331goto out;332}333334ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));335if (ret)336goto out;337338mt7915_mac_set_timing(phy);339ret = mt7915_dfs_init_radar_detector(phy);340mt7915_mac_cca_stats_reset(phy);341342mt7915_mac_reset_counters(phy);343phy->noise = 0;344345out:346if (!mt76_testmode_enabled(phy->mt76))347ieee80211_queue_delayed_work(phy->mt76->hw,348&phy->mt76->mac_work,349MT7915_WATCHDOG_TIME);350351return ret;352}353354static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,355struct ieee80211_vif *vif, struct ieee80211_sta *sta,356struct ieee80211_key_conf *key)357{358struct mt7915_dev *dev = mt7915_hw_dev(hw);359struct mt7915_phy *phy = mt7915_hw_phy(hw);360struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;361struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv :362&mvif->sta;363struct mt76_wcid *wcid = &msta->wcid;364u8 *wcid_keyidx = &wcid->hw_key_idx;365int idx = key->keyidx;366int err = 0;367368if (sta && !wcid->sta) {369if (cmd != SET_KEY)370return 0;371372return -EOPNOTSUPP;373}374375/* The hardware does not support per-STA RX GTK, fallback376* to software mode for these.377*/378if ((vif->type == NL80211_IFTYPE_ADHOC ||379vif->type == NL80211_IFTYPE_MESH_POINT) &&380(key->cipher == WLAN_CIPHER_SUITE_TKIP ||381key->cipher == WLAN_CIPHER_SUITE_CCMP) &&382!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))383return -EOPNOTSUPP;384385/* fall back to sw encryption for unsupported ciphers */386switch (key->cipher) {387case WLAN_CIPHER_SUITE_AES_CMAC:388wcid_keyidx = &wcid->hw_key_idx2;389key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;390break;391case WLAN_CIPHER_SUITE_TKIP:392case WLAN_CIPHER_SUITE_CCMP:393case WLAN_CIPHER_SUITE_CCMP_256:394case WLAN_CIPHER_SUITE_GCMP:395case WLAN_CIPHER_SUITE_GCMP_256:396case WLAN_CIPHER_SUITE_SMS4:397break;398case WLAN_CIPHER_SUITE_WEP40:399case WLAN_CIPHER_SUITE_WEP104:400default:401return -EOPNOTSUPP;402}403404mutex_lock(&dev->mt76.mutex);405406if (cmd == SET_KEY && !sta && !mvif->mt76.cipher) {407mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher);408mt7915_mcu_add_bss_info(phy, vif, true);409}410411if (cmd == SET_KEY) {412*wcid_keyidx = idx;413} else {414if (idx == *wcid_keyidx)415*wcid_keyidx = -1;416goto out;417}418419mt76_wcid_key_setup(&dev->mt76, wcid, key);420err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,421key, MCU_EXT_CMD(STA_REC_UPDATE),422&msta->wcid, cmd);423out:424mutex_unlock(&dev->mt76.mutex);425426return err;427}428429static int mt7915_set_sar_specs(struct ieee80211_hw *hw,430const struct cfg80211_sar_specs *sar)431{432struct mt7915_phy *phy = mt7915_hw_phy(hw);433struct mt7915_dev *dev = mt7915_hw_dev(hw);434int err = -EINVAL;435436mutex_lock(&dev->mt76.mutex);437if (!cfg80211_chandef_valid(&phy->mt76->chandef))438goto out;439440err = mt76_init_sar_power(hw, sar);441if (err)442goto out;443444err = mt7915_mcu_set_txpower_sku(phy);445out:446mutex_unlock(&dev->mt76.mutex);447448return err;449}450451static int mt7915_config(struct ieee80211_hw *hw, int radio_idx,452u32 changed)453{454struct mt7915_dev *dev = mt7915_hw_dev(hw);455struct mt7915_phy *phy = mt7915_hw_phy(hw);456int ret;457458if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {459#ifdef CONFIG_NL80211_TESTMODE460if (phy->mt76->test.state != MT76_TM_STATE_OFF) {461mutex_lock(&dev->mt76.mutex);462mt76_testmode_reset(phy->mt76, false);463mutex_unlock(&dev->mt76.mutex);464}465#endif466ret = mt76_update_channel(phy->mt76);467if (ret)468return ret;469}470471if (changed & (IEEE80211_CONF_CHANGE_POWER |472IEEE80211_CONF_CHANGE_CHANNEL)) {473ret = mt7915_mcu_set_txpower_sku(phy);474if (ret)475return ret;476}477478mutex_lock(&dev->mt76.mutex);479480if (changed & IEEE80211_CONF_CHANGE_MONITOR) {481bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);482bool band = phy->mt76->band_idx;483u32 rxfilter = phy->rxfilter;484485if (!enabled) {486rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;487dev->monitor_mask &= ~BIT(band);488} else {489rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;490dev->monitor_mask |= BIT(band);491}492493mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN,494enabled);495mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_MDP_DCR0_RX_HDR_TRANS_EN,496!dev->monitor_mask);497mt76_testmode_reset(phy->mt76, true);498mt76_wr(dev, MT_WF_RFCR(band), rxfilter);499}500501mutex_unlock(&dev->mt76.mutex);502503return 0;504}505506static int507mt7915_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,508unsigned int link_id, u16 queue,509const struct ieee80211_tx_queue_params *params)510{511struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;512513/* no need to update right away, we'll get BSS_CHANGED_QOS */514queue = mt76_connac_lmac_mapping(queue);515mvif->queue_params[queue] = *params;516517return 0;518}519520static void mt7915_configure_filter(struct ieee80211_hw *hw,521unsigned int changed_flags,522unsigned int *total_flags,523u64 multicast)524{525struct mt7915_dev *dev = mt7915_hw_dev(hw);526struct mt7915_phy *phy = mt7915_hw_phy(hw);527bool band = phy->mt76->band_idx;528u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |529MT_WF_RFCR1_DROP_BF_POLL |530MT_WF_RFCR1_DROP_BA |531MT_WF_RFCR1_DROP_CFEND |532MT_WF_RFCR1_DROP_CFACK;533u32 rxfilter;534u32 flags = 0;535536#define MT76_FILTER(_flag, _hw) do { \537flags |= *total_flags & FIF_##_flag; \538phy->rxfilter &= ~(_hw); \539phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \540} while (0)541542mutex_lock(&dev->mt76.mutex);543544phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |545MT_WF_RFCR_DROP_OTHER_BEACON |546MT_WF_RFCR_DROP_FRAME_REPORT |547MT_WF_RFCR_DROP_PROBEREQ |548MT_WF_RFCR_DROP_MCAST_FILTERED |549MT_WF_RFCR_DROP_MCAST |550MT_WF_RFCR_DROP_BCAST |551MT_WF_RFCR_DROP_DUPLICATE |552MT_WF_RFCR_DROP_A2_BSSID |553MT_WF_RFCR_DROP_UNWANTED_CTL |554MT_WF_RFCR_DROP_STBC_MULTI);555556MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |557MT_WF_RFCR_DROP_A3_MAC |558MT_WF_RFCR_DROP_A3_BSSID);559560MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL);561562MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |563MT_WF_RFCR_DROP_RTS |564MT_WF_RFCR_DROP_CTL_RSV);565566*total_flags = flags;567rxfilter = phy->rxfilter;568if (hw->conf.flags & IEEE80211_CONF_MONITOR)569rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;570else571rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;572mt76_wr(dev, MT_WF_RFCR(band), rxfilter);573574if (*total_flags & FIF_CONTROL)575mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags);576else577mt76_set(dev, MT_WF_RFCR1(band), ctl_flags);578579mutex_unlock(&dev->mt76.mutex);580}581582static void583mt7915_update_bss_color(struct ieee80211_hw *hw,584struct ieee80211_vif *vif,585struct cfg80211_he_bss_color *bss_color)586{587struct mt7915_dev *dev = mt7915_hw_dev(hw);588589switch (vif->type) {590case NL80211_IFTYPE_AP: {591struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;592593if (mvif->mt76.omac_idx > HW_BSSID_MAX)594return;595fallthrough;596}597case NL80211_IFTYPE_STATION:598mt7915_mcu_update_bss_color(dev, vif, bss_color);599break;600default:601break;602}603}604605static void mt7915_bss_info_changed(struct ieee80211_hw *hw,606struct ieee80211_vif *vif,607struct ieee80211_bss_conf *info,608u64 changed)609{610struct mt7915_phy *phy = mt7915_hw_phy(hw);611struct mt7915_dev *dev = mt7915_hw_dev(hw);612int set_bss_info = -1, set_sta = -1;613614mutex_lock(&dev->mt76.mutex);615616/*617* station mode uses BSSID to map the wlan entry to a peer,618* and then peer references bss_info_rfch to set bandwidth cap.619*/620if (changed & BSS_CHANGED_BSSID &&621vif->type == NL80211_IFTYPE_STATION)622set_bss_info = set_sta = !is_zero_ether_addr(info->bssid);623if (changed & BSS_CHANGED_ASSOC)624set_bss_info = vif->cfg.assoc;625if (changed & BSS_CHANGED_BEACON_ENABLED &&626info->enable_beacon &&627vif->type != NL80211_IFTYPE_AP)628set_bss_info = set_sta = 1;629630if (set_bss_info == 1)631mt7915_mcu_add_bss_info(phy, vif, true);632if (set_sta == 1)633mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);634635if (changed & BSS_CHANGED_ERP_CTS_PROT)636mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);637638if (changed & BSS_CHANGED_ERP_SLOT) {639int slottime = 9;640641if (phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ &&642!info->use_short_slot)643slottime = 20;644645if (slottime != phy->slottime) {646phy->slottime = slottime;647mt7915_mac_set_timing(phy);648}649}650651/* ensure that enable txcmd_mode after bss_info */652if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))653mt7915_mcu_set_tx(dev, vif);654655if (changed & BSS_CHANGED_HE_OBSS_PD)656mt7915_mcu_add_obss_spr(phy, vif, &info->he_obss_pd);657658if (changed & BSS_CHANGED_HE_BSS_COLOR)659mt7915_update_bss_color(hw, vif, &info->he_bss_color);660661if (changed & (BSS_CHANGED_BEACON |662BSS_CHANGED_BEACON_ENABLED))663mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);664665if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |666BSS_CHANGED_FILS_DISCOVERY))667mt7915_mcu_add_inband_discov(dev, vif, changed);668669if (set_bss_info == 0)670mt7915_mcu_add_bss_info(phy, vif, false);671if (set_sta == 0)672mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false);673674mutex_unlock(&dev->mt76.mutex);675}676677static void678mt7915_vif_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif)679{680struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;681struct mt7915_vif_cap *vc = &mvif->cap;682683vc->ht_ldpc = vif->bss_conf.ht_ldpc;684vc->vht_ldpc = vif->bss_conf.vht_ldpc;685vc->vht_su_ebfer = vif->bss_conf.vht_su_beamformer;686vc->vht_su_ebfee = vif->bss_conf.vht_su_beamformee;687vc->vht_mu_ebfer = vif->bss_conf.vht_mu_beamformer;688vc->vht_mu_ebfee = vif->bss_conf.vht_mu_beamformee;689vc->he_ldpc = vif->bss_conf.he_ldpc;690vc->he_su_ebfer = vif->bss_conf.he_su_beamformer;691vc->he_su_ebfee = vif->bss_conf.he_su_beamformee;692vc->he_mu_ebfer = vif->bss_conf.he_mu_beamformer;693}694695static int696mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,697struct ieee80211_bss_conf *link_conf)698{699struct mt7915_phy *phy = mt7915_hw_phy(hw);700struct mt7915_dev *dev = mt7915_hw_dev(hw);701int err;702703mutex_lock(&dev->mt76.mutex);704705mt7915_vif_check_caps(phy, vif);706707err = mt7915_mcu_add_bss_info(phy, vif, true);708if (err)709goto out;710err = mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);711out:712mutex_unlock(&dev->mt76.mutex);713714return err;715}716717static void718mt7915_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,719struct ieee80211_bss_conf *link_conf)720{721struct mt7915_dev *dev = mt7915_hw_dev(hw);722723mutex_lock(&dev->mt76.mutex);724mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false);725mutex_unlock(&dev->mt76.mutex);726}727728static void729mt7915_channel_switch_beacon(struct ieee80211_hw *hw,730struct ieee80211_vif *vif,731struct cfg80211_chan_def *chandef)732{733struct mt7915_dev *dev = mt7915_hw_dev(hw);734735mutex_lock(&dev->mt76.mutex);736mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON);737mutex_unlock(&dev->mt76.mutex);738}739740int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,741struct ieee80211_sta *sta)742{743struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);744struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;745struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;746bool ext_phy = mvif->phy != &dev->phy;747int idx;748749idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);750if (idx < 0)751return -ENOSPC;752753INIT_LIST_HEAD(&msta->rc_list);754INIT_LIST_HEAD(&msta->wcid.poll_list);755msta->vif = mvif;756msta->wcid.sta_disabled = 1;757msta->wcid.idx = idx;758msta->wcid.phy_idx = ext_phy;759msta->jiffies = jiffies;760761ewma_avg_signal_init(&msta->avg_ack_signal);762763mt7915_mac_wtbl_update(dev, idx,764MT_WTBL_UPDATE_ADM_COUNT_CLEAR);765mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, true);766767return 0;768}769770struct drop_sta_iter {771struct mt7915_dev *dev;772struct ieee80211_hw *hw;773struct ieee80211_vif *vif;774u8 sta_addr[ETH_ALEN];775};776777static void778__mt7915_drop_sta(void *ptr, u8 *mac, struct ieee80211_vif *vif)779{780struct drop_sta_iter *data = ptr;781struct ieee80211_sta *sta;782struct mt7915_sta *msta;783784if (vif == data->vif || vif->type != NL80211_IFTYPE_AP)785return;786787sta = ieee80211_find_sta_by_ifaddr(data->hw, data->sta_addr, mac);788if (!sta)789return;790791msta = (struct mt7915_sta *)sta->drv_priv;792mt7915_mcu_add_sta(data->dev, vif, sta, CONN_STATE_DISCONNECT, false);793msta->wcid.sta_disabled = 1;794msta->wcid.sta = 0;795}796797static void798mt7915_drop_other_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,799struct ieee80211_sta *sta)800{801struct mt76_phy *ext_phy = dev->mt76.phys[MT_BAND1];802struct drop_sta_iter data = {803.dev = dev,804.hw = dev->mphy.hw,805.vif = vif,806};807808if (vif->type != NL80211_IFTYPE_AP)809return;810811memcpy(data.sta_addr, sta->addr, ETH_ALEN);812ieee80211_iterate_active_interfaces(data.hw, 0, __mt7915_drop_sta, &data);813814if (!ext_phy)815return;816817data.hw = ext_phy->hw;818ieee80211_iterate_active_interfaces(data.hw, 0, __mt7915_drop_sta, &data);819}820821int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,822struct ieee80211_sta *sta, enum mt76_sta_event ev)823{824struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);825struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;826int i, ret;827u32 addr;828829switch (ev) {830case MT76_STA_EVENT_ASSOC:831ret = mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_CONNECT, true);832if (ret)833return ret;834835addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 30);836mt76_rmw_field(dev, addr, GENMASK(7, 0), 0xa0);837838ret = mt7915_mcu_add_rate_ctrl(dev, vif, sta, false);839if (ret)840return ret;841842msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;843msta->wcid.sta = 1;844msta->wcid.sta_disabled = 0;845846return 0;847848case MT76_STA_EVENT_AUTHORIZE:849mt7915_drop_other_sta(dev, vif, sta);850return mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_PORT_SECURE, false);851852case MT76_STA_EVENT_DISASSOC:853for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)854mt7915_mac_twt_teardown_flow(dev, msta, i);855856mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, false);857msta->wcid.sta_disabled = 1;858msta->wcid.sta = 0;859return 0;860}861862return 0;863}864865void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,866struct ieee80211_sta *sta)867{868struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);869struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;870871mt7915_mac_wtbl_update(dev, msta->wcid.idx,872MT_WTBL_UPDATE_ADM_COUNT_CLEAR);873874spin_lock_bh(&mdev->sta_poll_lock);875if (!list_empty(&msta->wcid.poll_list))876list_del_init(&msta->wcid.poll_list);877if (!list_empty(&msta->rc_list))878list_del_init(&msta->rc_list);879spin_unlock_bh(&mdev->sta_poll_lock);880}881882static void mt7915_tx(struct ieee80211_hw *hw,883struct ieee80211_tx_control *control,884struct sk_buff *skb)885{886struct mt7915_dev *dev = mt7915_hw_dev(hw);887struct mt76_phy *mphy = hw->priv;888struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);889struct ieee80211_vif *vif = info->control.vif;890struct mt76_wcid *wcid = &dev->mt76.global_wcid;891892if (control->sta) {893struct mt7915_sta *sta;894895sta = (struct mt7915_sta *)control->sta->drv_priv;896wcid = &sta->wcid;897}898899if (vif && !control->sta) {900struct mt7915_vif *mvif;901902mvif = (struct mt7915_vif *)vif->drv_priv;903wcid = &mvif->sta.wcid;904}905906mt76_tx(mphy, control->sta, wcid, skb);907}908909static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,910u32 val)911{912struct mt7915_dev *dev = mt7915_hw_dev(hw);913struct mt7915_phy *phy = mt7915_hw_phy(hw);914int ret;915916mutex_lock(&dev->mt76.mutex);917ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, val,918phy->mt76->band_idx);919mutex_unlock(&dev->mt76.mutex);920921return ret;922}923924static int925mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,926struct ieee80211_ampdu_params *params)927{928enum ieee80211_ampdu_mlme_action action = params->action;929struct mt7915_dev *dev = mt7915_hw_dev(hw);930struct ieee80211_sta *sta = params->sta;931struct ieee80211_txq *txq = sta->txq[params->tid];932struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;933u16 tid = params->tid;934u16 ssn = params->ssn;935struct mt76_txq *mtxq;936int ret = 0;937938if (!txq)939return -EINVAL;940941mtxq = (struct mt76_txq *)txq->drv_priv;942943mutex_lock(&dev->mt76.mutex);944switch (action) {945case IEEE80211_AMPDU_RX_START:946mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,947params->buf_size);948ret = mt7915_mcu_add_rx_ba(dev, params, true);949break;950case IEEE80211_AMPDU_RX_STOP:951mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);952ret = mt7915_mcu_add_rx_ba(dev, params, false);953break;954case IEEE80211_AMPDU_TX_OPERATIONAL:955mtxq->aggr = true;956mtxq->send_bar = false;957ret = mt7915_mcu_add_tx_ba(dev, params, true);958break;959case IEEE80211_AMPDU_TX_STOP_FLUSH:960case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:961mtxq->aggr = false;962clear_bit(tid, &msta->wcid.ampdu_state);963ret = mt7915_mcu_add_tx_ba(dev, params, false);964break;965case IEEE80211_AMPDU_TX_START:966set_bit(tid, &msta->wcid.ampdu_state);967ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;968break;969case IEEE80211_AMPDU_TX_STOP_CONT:970mtxq->aggr = false;971clear_bit(tid, &msta->wcid.ampdu_state);972ret = mt7915_mcu_add_tx_ba(dev, params, false);973ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);974break;975}976mutex_unlock(&dev->mt76.mutex);977978return ret;979}980981static int982mt7915_get_stats(struct ieee80211_hw *hw,983struct ieee80211_low_level_stats *stats)984{985struct mt7915_phy *phy = mt7915_hw_phy(hw);986struct mt7915_dev *dev = mt7915_hw_dev(hw);987struct mt76_mib_stats *mib = &phy->mib;988989mutex_lock(&dev->mt76.mutex);990991stats->dot11RTSSuccessCount = mib->rts_cnt;992stats->dot11RTSFailureCount = mib->rts_retries_cnt;993stats->dot11FCSErrorCount = mib->fcs_err_cnt;994stats->dot11ACKFailureCount = mib->ack_fail_cnt;995996mutex_unlock(&dev->mt76.mutex);997998return 0;999}10001001u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif)1002{1003struct mt7915_dev *dev = mt7915_hw_dev(hw);1004struct mt7915_phy *phy = mt7915_hw_phy(hw);1005bool band = phy->mt76->band_idx;1006union {1007u64 t64;1008u32 t32[2];1009} tsf;1010u16 n;10111012lockdep_assert_held(&dev->mt76.mutex);10131014n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_01015: mvif->mt76.omac_idx;1016/* TSF software read */1017if (is_mt7915(&dev->mt76))1018mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,1019MT_LPON_TCR_SW_READ);1020else1021mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE,1022MT_LPON_TCR_SW_READ);1023tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band));1024tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band));10251026return tsf.t64;1027}10281029static u641030mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)1031{1032struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1033struct mt7915_dev *dev = mt7915_hw_dev(hw);1034u64 ret;10351036mutex_lock(&dev->mt76.mutex);1037ret = __mt7915_get_tsf(hw, mvif);1038mutex_unlock(&dev->mt76.mutex);10391040return ret;1041}10421043static void1044mt7915_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1045u64 timestamp)1046{1047struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1048struct mt7915_dev *dev = mt7915_hw_dev(hw);1049struct mt7915_phy *phy = mt7915_hw_phy(hw);1050bool band = phy->mt76->band_idx;1051union {1052u64 t64;1053u32 t32[2];1054} tsf = { .t64 = timestamp, };1055u16 n;10561057mutex_lock(&dev->mt76.mutex);10581059n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_01060: mvif->mt76.omac_idx;1061mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);1062mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);1063/* TSF software overwrite */1064if (is_mt7915(&dev->mt76))1065mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,1066MT_LPON_TCR_SW_WRITE);1067else1068mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE,1069MT_LPON_TCR_SW_WRITE);10701071mutex_unlock(&dev->mt76.mutex);1072}10731074static void1075mt7915_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1076s64 timestamp)1077{1078struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1079struct mt7915_dev *dev = mt7915_hw_dev(hw);1080struct mt7915_phy *phy = mt7915_hw_phy(hw);1081bool band = phy->mt76->band_idx;1082union {1083u64 t64;1084u32 t32[2];1085} tsf = { .t64 = timestamp, };1086u16 n;10871088mutex_lock(&dev->mt76.mutex);10891090n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_01091: mvif->mt76.omac_idx;1092mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);1093mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);1094/* TSF software adjust*/1095if (is_mt7915(&dev->mt76))1096mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,1097MT_LPON_TCR_SW_ADJUST);1098else1099mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE,1100MT_LPON_TCR_SW_ADJUST);11011102mutex_unlock(&dev->mt76.mutex);1103}11041105static void1106mt7915_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,1107s16 coverage_class)1108{1109struct mt7915_phy *phy = mt7915_hw_phy(hw);1110struct mt7915_dev *dev = phy->dev;11111112mutex_lock(&dev->mt76.mutex);1113phy->coverage_class = max_t(s16, coverage_class, 0);1114mt7915_mac_set_timing(phy);1115mutex_unlock(&dev->mt76.mutex);1116}11171118static int1119mt7915_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant, u32 rx_ant)1120{1121struct mt7915_dev *dev = mt7915_hw_dev(hw);1122struct mt7915_phy *phy = mt7915_hw_phy(hw);1123int max_nss = hweight8(hw->wiphy->available_antennas_tx);1124u8 chainshift = dev->chainshift;1125u8 band = phy->mt76->band_idx;11261127if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss)1128return -EINVAL;11291130mutex_lock(&dev->mt76.mutex);11311132phy->mt76->antenna_mask = tx_ant;11331134/* handle a variant of mt7916/mt7981 which has 3T3R but nss2 on 5 GHz band */1135if ((is_mt7916(&dev->mt76) || is_mt7981(&dev->mt76)) &&1136band && hweight8(tx_ant) == max_nss)1137phy->mt76->chainmask = (dev->chainmask >> chainshift) << chainshift;1138else1139phy->mt76->chainmask = tx_ant << (chainshift * band);11401141mt76_set_stream_caps(phy->mt76, true);1142mt7915_set_stream_vht_txbf_caps(phy);1143mt7915_set_stream_he_caps(phy);11441145mutex_unlock(&dev->mt76.mutex);11461147return 0;1148}11491150static void mt7915_sta_statistics(struct ieee80211_hw *hw,1151struct ieee80211_vif *vif,1152struct ieee80211_sta *sta,1153struct station_info *sinfo)1154{1155struct mt7915_phy *phy = mt7915_hw_phy(hw);1156struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;1157struct rate_info *txrate = &msta->wcid.rate;1158struct rate_info rxrate = {};11591160if (!mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) {1161sinfo->rxrate = rxrate;1162sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);1163}11641165if (txrate->legacy || txrate->flags) {1166if (txrate->legacy) {1167sinfo->txrate.legacy = txrate->legacy;1168} else {1169sinfo->txrate.mcs = txrate->mcs;1170sinfo->txrate.nss = txrate->nss;1171sinfo->txrate.bw = txrate->bw;1172sinfo->txrate.he_gi = txrate->he_gi;1173sinfo->txrate.he_dcm = txrate->he_dcm;1174sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;1175}1176sinfo->txrate.flags = txrate->flags;1177sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);1178}11791180/* offloading flows bypass networking stack, so driver counts and1181* reports sta statistics via NL80211_STA_INFO when WED is active.1182*/1183if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {1184sinfo->tx_bytes = msta->wcid.stats.tx_bytes;1185sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);11861187if (!mt7915_mcu_wed_wa_tx_stats(phy->dev, msta->wcid.idx)) {1188sinfo->tx_packets = msta->wcid.stats.tx_packets;1189sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);1190}11911192if (mtk_wed_get_rx_capa(&phy->dev->mt76.mmio.wed)) {1193sinfo->rx_bytes = msta->wcid.stats.rx_bytes;1194sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);11951196sinfo->rx_packets = msta->wcid.stats.rx_packets;1197sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);1198}1199}12001201sinfo->tx_failed = msta->wcid.stats.tx_failed;1202sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);12031204sinfo->tx_retries = msta->wcid.stats.tx_retries;1205sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);12061207sinfo->ack_signal = (s8)msta->ack_signal;1208sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);12091210sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);1211sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);1212}12131214static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)1215{1216struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;1217struct mt7915_dev *dev = msta->vif->phy->dev;1218u32 *changed = data;12191220spin_lock_bh(&dev->mt76.sta_poll_lock);1221msta->changed |= *changed;1222if (list_empty(&msta->rc_list))1223list_add_tail(&msta->rc_list, &dev->sta_rc_list);1224spin_unlock_bh(&dev->mt76.sta_poll_lock);1225}12261227static void mt7915_sta_rc_update(struct ieee80211_hw *hw,1228struct ieee80211_vif *vif,1229struct ieee80211_link_sta *link_sta,1230u32 changed)1231{1232struct ieee80211_sta *sta = link_sta->sta;1233struct mt7915_phy *phy = mt7915_hw_phy(hw);1234struct mt7915_dev *dev = phy->dev;1235struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;12361237if (!msta->wcid.sta)1238return;12391240mt7915_sta_rc_work(&changed, sta);1241ieee80211_queue_work(hw, &dev->rc_work);1242}12431244static int1245mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1246const struct cfg80211_bitrate_mask *mask)1247{1248struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1249struct mt7915_phy *phy = mt7915_hw_phy(hw);1250struct mt7915_dev *dev = phy->dev;1251u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;12521253mvif->bitrate_mask = *mask;12541255/* if multiple rates across different preambles are given we can1256* reconfigure this info with all peers using sta_rec command with1257* the below exception cases.1258* - single rate : if a rate is passed along with different preambles,1259* we select the highest one as fixed rate. i.e VHT MCS for VHT peers.1260* - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT1261* then multiple MCS setting (MCS 4,5,6) is not supported.1262*/1263ieee80211_iterate_stations_atomic(hw, mt7915_sta_rc_work, &changed);1264ieee80211_queue_work(hw, &dev->rc_work);12651266return 0;1267}12681269static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,1270struct ieee80211_vif *vif,1271struct ieee80211_sta *sta,1272bool enabled)1273{1274struct mt7915_dev *dev = mt7915_hw_dev(hw);1275struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;12761277if (enabled)1278set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);1279else1280clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);12811282if (!msta->wcid.sta)1283return;12841285mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);1286}12871288static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,1289struct ieee80211_vif *vif,1290struct ieee80211_sta *sta,1291bool enabled)1292{1293struct mt7915_dev *dev = mt7915_hw_dev(hw);1294struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;12951296if (enabled)1297set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);1298else1299clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);13001301if (!msta->wcid.sta)1302return;13031304mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);1305}13061307static int mt7915_sta_set_txpwr(struct ieee80211_hw *hw,1308struct ieee80211_vif *vif,1309struct ieee80211_sta *sta)1310{1311struct mt7915_phy *phy = mt7915_hw_phy(hw);1312struct mt7915_dev *dev = mt7915_hw_dev(hw);1313s16 txpower = sta->deflink.txpwr.power;1314int ret;13151316if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC)1317txpower = 0;13181319mutex_lock(&dev->mt76.mutex);13201321/* NOTE: temporarily use 0 as minimum limit, which is a1322* global setting and will be applied to all stations.1323*/1324ret = mt7915_mcu_set_txpower_frame_min(phy, 0);1325if (ret)1326goto out;13271328/* This only applies to data frames while pushing traffic,1329* whereas the management frames or other packets that are1330* using fixed rate can be configured via TxD.1331*/1332ret = mt7915_mcu_set_txpower_frame(phy, vif, sta, txpower);13331334out:1335mutex_unlock(&dev->mt76.mutex);13361337return ret;1338}13391340static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {1341"tx_ampdu_cnt",1342"tx_stop_q_empty_cnt",1343"tx_mpdu_attempts",1344"tx_mpdu_success",1345"tx_rwp_fail_cnt",1346"tx_rwp_need_cnt",1347"tx_pkt_ebf_cnt",1348"tx_pkt_ibf_cnt",1349"tx_ampdu_len:0-1",1350"tx_ampdu_len:2-10",1351"tx_ampdu_len:11-19",1352"tx_ampdu_len:20-28",1353"tx_ampdu_len:29-37",1354"tx_ampdu_len:38-46",1355"tx_ampdu_len:47-55",1356"tx_ampdu_len:56-79",1357"tx_ampdu_len:80-103",1358"tx_ampdu_len:104-127",1359"tx_ampdu_len:128-151",1360"tx_ampdu_len:152-175",1361"tx_ampdu_len:176-199",1362"tx_ampdu_len:200-223",1363"tx_ampdu_len:224-247",1364"ba_miss_count",1365"tx_beamformer_ppdu_iBF",1366"tx_beamformer_ppdu_eBF",1367"tx_beamformer_rx_feedback_all",1368"tx_beamformer_rx_feedback_he",1369"tx_beamformer_rx_feedback_vht",1370"tx_beamformer_rx_feedback_ht",1371"tx_beamformer_rx_feedback_bw", /* zero based idx: 20, 40, 80, 160 */1372"tx_beamformer_rx_feedback_nc",1373"tx_beamformer_rx_feedback_nr",1374"tx_beamformee_ok_feedback_pkts",1375"tx_beamformee_feedback_trig",1376"tx_mu_beamforming",1377"tx_mu_mpdu",1378"tx_mu_successful_mpdu",1379"tx_su_successful_mpdu",1380"tx_msdu_pack_1",1381"tx_msdu_pack_2",1382"tx_msdu_pack_3",1383"tx_msdu_pack_4",1384"tx_msdu_pack_5",1385"tx_msdu_pack_6",1386"tx_msdu_pack_7",1387"tx_msdu_pack_8",13881389/* rx counters */1390"rx_fifo_full_cnt",1391"rx_mpdu_cnt",1392"channel_idle_cnt",1393"primary_cca_busy_time",1394"secondary_cca_busy_time",1395"primary_energy_detect_time",1396"cck_mdrdy_time",1397"ofdm_mdrdy_time",1398"green_mdrdy_time",1399"rx_vector_mismatch_cnt",1400"rx_delimiter_fail_cnt",1401"rx_mrdy_cnt",1402"rx_len_mismatch_cnt",1403"rx_ampdu_cnt",1404"rx_ampdu_bytes_cnt",1405"rx_ampdu_valid_subframe_cnt",1406"rx_ampdu_valid_subframe_b_cnt",1407"rx_pfdrop_cnt",1408"rx_vec_queue_overflow_drop_cnt",1409"rx_ba_cnt",14101411/* muru mu-mimo and ofdma related stats */1412"dl_cck_cnt",1413"dl_ofdm_cnt",1414"dl_htmix_cnt",1415"dl_htgf_cnt",1416"dl_vht_su_cnt",1417"dl_vht_2mu_cnt",1418"dl_vht_3mu_cnt",1419"dl_vht_4mu_cnt",1420"dl_he_su_cnt",1421"dl_he_ext_su_cnt",1422"dl_he_2ru_cnt",1423"dl_he_2mu_cnt",1424"dl_he_3ru_cnt",1425"dl_he_3mu_cnt",1426"dl_he_4ru_cnt",1427"dl_he_4mu_cnt",1428"dl_he_5to8ru_cnt",1429"dl_he_9to16ru_cnt",1430"dl_he_gtr16ru_cnt",14311432"ul_hetrig_su_cnt",1433"ul_hetrig_2ru_cnt",1434"ul_hetrig_3ru_cnt",1435"ul_hetrig_4ru_cnt",1436"ul_hetrig_5to8ru_cnt",1437"ul_hetrig_9to16ru_cnt",1438"ul_hetrig_gtr16ru_cnt",1439"ul_hetrig_2mu_cnt",1440"ul_hetrig_3mu_cnt",1441"ul_hetrig_4mu_cnt",14421443/* per vif counters */1444"v_tx_mode_cck",1445"v_tx_mode_ofdm",1446"v_tx_mode_ht",1447"v_tx_mode_ht_gf",1448"v_tx_mode_vht",1449"v_tx_mode_he_su",1450"v_tx_mode_he_ext_su",1451"v_tx_mode_he_tb",1452"v_tx_mode_he_mu",1453"v_tx_bw_20",1454"v_tx_bw_40",1455"v_tx_bw_80",1456"v_tx_bw_160",1457"v_tx_mcs_0",1458"v_tx_mcs_1",1459"v_tx_mcs_2",1460"v_tx_mcs_3",1461"v_tx_mcs_4",1462"v_tx_mcs_5",1463"v_tx_mcs_6",1464"v_tx_mcs_7",1465"v_tx_mcs_8",1466"v_tx_mcs_9",1467"v_tx_mcs_10",1468"v_tx_mcs_11",1469"v_tx_nss_1",1470"v_tx_nss_2",1471"v_tx_nss_3",1472"v_tx_nss_4",1473};14741475#define MT7915_SSTATS_LEN ARRAY_SIZE(mt7915_gstrings_stats)14761477/* Ethtool related API */1478static1479void mt7915_get_et_strings(struct ieee80211_hw *hw,1480struct ieee80211_vif *vif,1481u32 sset, u8 *data)1482{1483if (sset != ETH_SS_STATS)1484return;14851486memcpy(data, mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats));1487data += sizeof(mt7915_gstrings_stats);1488page_pool_ethtool_stats_get_strings(data);1489}14901491static1492int mt7915_get_et_sset_count(struct ieee80211_hw *hw,1493struct ieee80211_vif *vif, int sset)1494{1495if (sset != ETH_SS_STATS)1496return 0;14971498return MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count();1499}15001501static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)1502{1503struct mt76_ethtool_worker_info *wi = wi_data;1504struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;15051506if (msta->vif->mt76.idx != wi->idx)1507return;15081509mt76_ethtool_worker(wi, &msta->wcid.stats, false);1510}15111512static1513void mt7915_get_et_stats(struct ieee80211_hw *hw,1514struct ieee80211_vif *vif,1515struct ethtool_stats *stats, u64 *data)1516{1517struct mt7915_dev *dev = mt7915_hw_dev(hw);1518struct mt7915_phy *phy = mt7915_hw_phy(hw);1519struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1520struct mt76_mib_stats *mib = &phy->mib;1521struct mt76_ethtool_worker_info wi = {1522.data = data,1523.idx = mvif->mt76.idx,1524};1525/* See mt7915_ampdu_stat_read_phy, etc */1526int i, ei = 0, stats_size;15271528mutex_lock(&dev->mt76.mutex);15291530mt7915_mac_update_stats(phy);15311532data[ei++] = mib->tx_ampdu_cnt;1533data[ei++] = mib->tx_stop_q_empty_cnt;1534data[ei++] = mib->tx_mpdu_attempts_cnt;1535data[ei++] = mib->tx_mpdu_success_cnt;1536data[ei++] = mib->tx_rwp_fail_cnt;1537data[ei++] = mib->tx_rwp_need_cnt;1538data[ei++] = mib->tx_pkt_ebf_cnt;1539data[ei++] = mib->tx_pkt_ibf_cnt;15401541/* Tx ampdu stat */1542for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++)1543data[ei++] = phy->mt76->aggr_stats[i];15441545data[ei++] = phy->mib.ba_miss_cnt;15461547/* Tx Beamformer monitor */1548data[ei++] = mib->tx_bf_ibf_ppdu_cnt;1549data[ei++] = mib->tx_bf_ebf_ppdu_cnt;15501551/* Tx Beamformer Rx feedback monitor */1552data[ei++] = mib->tx_bf_rx_fb_all_cnt;1553data[ei++] = mib->tx_bf_rx_fb_he_cnt;1554data[ei++] = mib->tx_bf_rx_fb_vht_cnt;1555data[ei++] = mib->tx_bf_rx_fb_ht_cnt;15561557data[ei++] = mib->tx_bf_rx_fb_bw;1558data[ei++] = mib->tx_bf_rx_fb_nc_cnt;1559data[ei++] = mib->tx_bf_rx_fb_nr_cnt;15601561/* Tx Beamformee Rx NDPA & Tx feedback report */1562data[ei++] = mib->tx_bf_fb_cpl_cnt;1563data[ei++] = mib->tx_bf_fb_trig_cnt;15641565/* Tx SU & MU counters */1566data[ei++] = mib->tx_bf_cnt;1567data[ei++] = mib->tx_mu_mpdu_cnt;1568data[ei++] = mib->tx_mu_acked_mpdu_cnt;1569data[ei++] = mib->tx_su_acked_mpdu_cnt;15701571/* Tx amsdu info (pack-count histogram) */1572for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++)1573data[ei++] = mib->tx_amsdu[i];15741575/* rx counters */1576data[ei++] = mib->rx_fifo_full_cnt;1577data[ei++] = mib->rx_mpdu_cnt;1578data[ei++] = mib->channel_idle_cnt;1579data[ei++] = mib->primary_cca_busy_time;1580data[ei++] = mib->secondary_cca_busy_time;1581data[ei++] = mib->primary_energy_detect_time;1582data[ei++] = mib->cck_mdrdy_time;1583data[ei++] = mib->ofdm_mdrdy_time;1584data[ei++] = mib->green_mdrdy_time;1585data[ei++] = mib->rx_vector_mismatch_cnt;1586data[ei++] = mib->rx_delimiter_fail_cnt;1587data[ei++] = mib->rx_mrdy_cnt;1588data[ei++] = mib->rx_len_mismatch_cnt;1589data[ei++] = mib->rx_ampdu_cnt;1590data[ei++] = mib->rx_ampdu_bytes_cnt;1591data[ei++] = mib->rx_ampdu_valid_subframe_cnt;1592data[ei++] = mib->rx_ampdu_valid_subframe_bytes_cnt;1593data[ei++] = mib->rx_pfdrop_cnt;1594data[ei++] = mib->rx_vec_queue_overflow_drop_cnt;1595data[ei++] = mib->rx_ba_cnt;15961597data[ei++] = mib->dl_cck_cnt;1598data[ei++] = mib->dl_ofdm_cnt;1599data[ei++] = mib->dl_htmix_cnt;1600data[ei++] = mib->dl_htgf_cnt;1601data[ei++] = mib->dl_vht_su_cnt;1602data[ei++] = mib->dl_vht_2mu_cnt;1603data[ei++] = mib->dl_vht_3mu_cnt;1604data[ei++] = mib->dl_vht_4mu_cnt;1605data[ei++] = mib->dl_he_su_cnt;1606data[ei++] = mib->dl_he_ext_su_cnt;1607data[ei++] = mib->dl_he_2ru_cnt;1608data[ei++] = mib->dl_he_2mu_cnt;1609data[ei++] = mib->dl_he_3ru_cnt;1610data[ei++] = mib->dl_he_3mu_cnt;1611data[ei++] = mib->dl_he_4ru_cnt;1612data[ei++] = mib->dl_he_4mu_cnt;1613data[ei++] = mib->dl_he_5to8ru_cnt;1614data[ei++] = mib->dl_he_9to16ru_cnt;1615data[ei++] = mib->dl_he_gtr16ru_cnt;16161617data[ei++] = mib->ul_hetrig_su_cnt;1618data[ei++] = mib->ul_hetrig_2ru_cnt;1619data[ei++] = mib->ul_hetrig_3ru_cnt;1620data[ei++] = mib->ul_hetrig_4ru_cnt;1621data[ei++] = mib->ul_hetrig_5to8ru_cnt;1622data[ei++] = mib->ul_hetrig_9to16ru_cnt;1623data[ei++] = mib->ul_hetrig_gtr16ru_cnt;1624data[ei++] = mib->ul_hetrig_2mu_cnt;1625data[ei++] = mib->ul_hetrig_3mu_cnt;1626data[ei++] = mib->ul_hetrig_4mu_cnt;16271628/* Add values for all stations owned by this vif */1629wi.initial_stat_idx = ei;1630ieee80211_iterate_stations_atomic(hw, mt7915_ethtool_worker, &wi);16311632mutex_unlock(&dev->mt76.mutex);16331634if (wi.sta_count == 0)1635return;16361637ei += wi.worker_stat_count;16381639mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei);16401641stats_size = MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count();1642if (ei != stats_size)1643dev_err(dev->mt76.dev, "ei: %d size: %d", ei, stats_size);1644}16451646static void1647mt7915_twt_teardown_request(struct ieee80211_hw *hw,1648struct ieee80211_sta *sta,1649u8 flowid)1650{1651struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;1652struct mt7915_dev *dev = mt7915_hw_dev(hw);16531654mutex_lock(&dev->mt76.mutex);1655mt7915_mac_twt_teardown_flow(dev, msta, flowid);1656mutex_unlock(&dev->mt76.mutex);1657}16581659static int1660mt7915_set_frag_threshold(struct ieee80211_hw *hw, int radio_idx, u32 val)1661{1662return 0;1663}16641665static int1666mt7915_set_radar_background(struct ieee80211_hw *hw,1667struct cfg80211_chan_def *chandef)1668{1669struct mt7915_phy *phy = mt7915_hw_phy(hw);1670struct mt7915_dev *dev = phy->dev;1671int ret = -EINVAL;1672bool running;16731674mutex_lock(&dev->mt76.mutex);16751676if (dev->mt76.region == NL80211_DFS_UNSET)1677goto out;16781679if (dev->rdd2_phy && dev->rdd2_phy != phy) {1680/* rdd2 is already locked */1681ret = -EBUSY;1682goto out;1683}16841685/* rdd2 already configured on a radar channel */1686running = dev->rdd2_phy &&1687cfg80211_chandef_valid(&dev->rdd2_chandef) &&1688!!(dev->rdd2_chandef.chan->flags & IEEE80211_CHAN_RADAR);16891690if (!chandef || running ||1691!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) {1692ret = mt7915_mcu_rdd_background_enable(phy, NULL);1693if (ret)1694goto out;16951696if (!running)1697goto update_phy;1698}16991700ret = mt7915_mcu_rdd_background_enable(phy, chandef);1701if (ret)1702goto out;17031704update_phy:1705dev->rdd2_phy = chandef ? phy : NULL;1706if (chandef)1707dev->rdd2_chandef = *chandef;1708out:1709mutex_unlock(&dev->mt76.mutex);17101711return ret;1712}17131714#ifdef CONFIG_NET_MEDIATEK_SOC_WED1715static int1716mt7915_net_fill_forward_path(struct ieee80211_hw *hw,1717struct ieee80211_vif *vif,1718struct ieee80211_sta *sta,1719struct net_device_path_ctx *ctx,1720struct net_device_path *path)1721{1722struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;1723struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;1724struct mt7915_dev *dev = mt7915_hw_dev(hw);1725struct mt7915_phy *phy = mt7915_hw_phy(hw);1726struct mtk_wed_device *wed = &dev->mt76.mmio.wed;17271728if (!mtk_wed_device_active(wed))1729return -ENODEV;17301731if (msta->wcid.idx > 0xff)1732return -EIO;17331734path->type = DEV_PATH_MTK_WDMA;1735path->dev = ctx->dev;1736path->mtk_wdma.wdma_idx = wed->wdma_idx;1737path->mtk_wdma.bss = mvif->mt76.idx;1738path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff;1739path->mtk_wdma.queue = phy != &dev->phy;17401741ctx->dev = NULL;17421743return 0;1744}1745#endif17461747static void1748mt7915_reconfig_complete(struct ieee80211_hw *hw,1749enum ieee80211_reconfig_type reconfig_type)1750{1751struct mt7915_phy *phy = mt7915_hw_phy(hw);17521753ieee80211_wake_queues(hw);1754ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,1755MT7915_WATCHDOG_TIME);1756}17571758const struct ieee80211_ops mt7915_ops = {1759.add_chanctx = ieee80211_emulate_add_chanctx,1760.remove_chanctx = ieee80211_emulate_remove_chanctx,1761.change_chanctx = ieee80211_emulate_change_chanctx,1762.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,1763.tx = mt7915_tx,1764.start = mt7915_start,1765.stop = mt7915_stop,1766.add_interface = mt7915_add_interface,1767.remove_interface = mt7915_remove_interface,1768.config = mt7915_config,1769.conf_tx = mt7915_conf_tx,1770.configure_filter = mt7915_configure_filter,1771.bss_info_changed = mt7915_bss_info_changed,1772.start_ap = mt7915_start_ap,1773.stop_ap = mt7915_stop_ap,1774.sta_state = mt76_sta_state,1775.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,1776.link_sta_rc_update = mt7915_sta_rc_update,1777.set_key = mt7915_set_key,1778.ampdu_action = mt7915_ampdu_action,1779.set_rts_threshold = mt7915_set_rts_threshold,1780.wake_tx_queue = mt76_wake_tx_queue,1781.sw_scan_start = mt76_sw_scan,1782.sw_scan_complete = mt76_sw_scan_complete,1783.release_buffered_frames = mt76_release_buffered_frames,1784.get_txpower = mt76_get_txpower,1785.set_sar_specs = mt7915_set_sar_specs,1786.channel_switch_beacon = mt7915_channel_switch_beacon,1787.get_stats = mt7915_get_stats,1788.get_et_sset_count = mt7915_get_et_sset_count,1789.get_et_stats = mt7915_get_et_stats,1790.get_et_strings = mt7915_get_et_strings,1791.get_tsf = mt7915_get_tsf,1792.set_tsf = mt7915_set_tsf,1793.offset_tsf = mt7915_offset_tsf,1794.get_survey = mt76_get_survey,1795.get_antenna = mt76_get_antenna,1796.set_antenna = mt7915_set_antenna,1797.set_bitrate_mask = mt7915_set_bitrate_mask,1798.set_coverage_class = mt7915_set_coverage_class,1799.sta_statistics = mt7915_sta_statistics,1800.sta_set_txpwr = mt7915_sta_set_txpwr,1801.sta_set_4addr = mt7915_sta_set_4addr,1802.sta_set_decap_offload = mt7915_sta_set_decap_offload,1803.add_twt_setup = mt7915_mac_add_twt_setup,1804.twt_teardown_request = mt7915_twt_teardown_request,1805.set_frag_threshold = mt7915_set_frag_threshold,1806CFG80211_TESTMODE_CMD(mt76_testmode_cmd)1807CFG80211_TESTMODE_DUMP(mt76_testmode_dump)1808#ifdef CONFIG_MAC80211_DEBUGFS1809.sta_add_debugfs = mt7915_sta_add_debugfs,1810#endif1811.set_radar_background = mt7915_set_radar_background,1812#ifdef CONFIG_NET_MEDIATEK_SOC_WED1813.net_fill_forward_path = mt7915_net_fill_forward_path,1814.net_setup_tc = mt76_wed_net_setup_tc,1815#endif1816.reconfig_complete = mt7915_reconfig_complete,1817};181818191820