brintos

brintos / linux-shallow public Read only

0
0
Text · 39.9 KiB · 39f071e Raw
1511 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (C) 2022 MediaTek Inc.4 */5 6#include "mt7996.h"7#include "mcu.h"8#include "mac.h"9 10static bool mt7996_dev_running(struct mt7996_dev *dev)11{12	struct mt7996_phy *phy;13 14	if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))15		return true;16 17	phy = mt7996_phy2(dev);18	if (phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state))19		return true;20 21	phy = mt7996_phy3(dev);22 23	return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);24}25 26int mt7996_run(struct ieee80211_hw *hw)27{28	struct mt7996_dev *dev = mt7996_hw_dev(hw);29	struct mt7996_phy *phy = mt7996_hw_phy(hw);30	bool running;31	int ret;32 33	running = mt7996_dev_running(dev);34	if (!running) {35		ret = mt7996_mcu_set_hdr_trans(dev, true);36		if (ret)37			goto out;38 39		if (is_mt7992(&dev->mt76)) {40			u8 queue = mt76_connac_lmac_mapping(IEEE80211_AC_VI);41 42			ret = mt7996_mcu_cp_support(dev, queue);43			if (ret)44				goto out;45		}46	}47 48	mt7996_mac_enable_nf(dev, phy->mt76->band_idx);49 50	ret = mt7996_mcu_set_rts_thresh(phy, 0x92b);51	if (ret)52		goto out;53 54	ret = mt7996_mcu_set_radio_en(phy, true);55	if (ret)56		goto out;57 58	ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH);59	if (ret)60		goto out;61 62	ret = mt7996_mcu_set_thermal_throttling(phy, MT7996_THERMAL_THROTTLE_MAX);63	if (ret)64		goto out;65 66	ret = mt7996_mcu_set_thermal_protect(phy, true);67	if (ret)68		goto out;69 70	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);71 72	ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,73				     MT7996_WATCHDOG_TIME);74 75	if (!running)76		mt7996_mac_reset_counters(phy);77 78out:79	return ret;80}81 82static int mt7996_start(struct ieee80211_hw *hw)83{84	struct mt7996_dev *dev = mt7996_hw_dev(hw);85	int ret;86 87	flush_work(&dev->init_work);88 89	mutex_lock(&dev->mt76.mutex);90	ret = mt7996_run(hw);91	mutex_unlock(&dev->mt76.mutex);92 93	return ret;94}95 96static void mt7996_stop(struct ieee80211_hw *hw, bool suspend)97{98	struct mt7996_dev *dev = mt7996_hw_dev(hw);99	struct mt7996_phy *phy = mt7996_hw_phy(hw);100 101	cancel_delayed_work_sync(&phy->mt76->mac_work);102 103	mutex_lock(&dev->mt76.mutex);104 105	mt7996_mcu_set_radio_en(phy, false);106 107	clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);108 109	mutex_unlock(&dev->mt76.mutex);110}111 112static inline int get_free_idx(u32 mask, u8 start, u8 end)113{114	return ffs(~mask & GENMASK(end, start));115}116 117static int get_omac_idx(enum nl80211_iftype type, u64 mask)118{119	int i;120 121	switch (type) {122	case NL80211_IFTYPE_MESH_POINT:123	case NL80211_IFTYPE_ADHOC:124	case NL80211_IFTYPE_STATION:125		/* prefer hw bssid slot 1-3 */126		i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3);127		if (i)128			return i - 1;129 130		if (type != NL80211_IFTYPE_STATION)131			break;132 133		i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);134		if (i)135			return i - 1;136 137		if (~mask & BIT(HW_BSSID_0))138			return HW_BSSID_0;139 140		break;141	case NL80211_IFTYPE_MONITOR:142	case NL80211_IFTYPE_AP:143		/* ap uses hw bssid 0 and ext bssid */144		if (~mask & BIT(HW_BSSID_0))145			return HW_BSSID_0;146 147		i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);148		if (i)149			return i - 1;150 151		break;152	default:153		WARN_ON(1);154		break;155	}156 157	return -1;158}159 160static void mt7996_init_bitrate_mask(struct ieee80211_vif *vif)161{162	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;163	int i;164 165	for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) {166		mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;167		mvif->bitrate_mask.control[i].he_gi = 0xff;168		mvif->bitrate_mask.control[i].he_ltf = 0xff;169		mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0);170		memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff,171		       sizeof(mvif->bitrate_mask.control[i].ht_mcs));172		memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff,173		       sizeof(mvif->bitrate_mask.control[i].vht_mcs));174		memset(mvif->bitrate_mask.control[i].he_mcs, 0xff,175		       sizeof(mvif->bitrate_mask.control[i].he_mcs));176	}177}178 179static int mt7996_add_interface(struct ieee80211_hw *hw,180				struct ieee80211_vif *vif)181{182	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;183	struct mt7996_dev *dev = mt7996_hw_dev(hw);184	struct mt7996_phy *phy = mt7996_hw_phy(hw);185	struct mt76_txq *mtxq;186	u8 band_idx = phy->mt76->band_idx;187	int idx, ret = 0;188 189	mutex_lock(&dev->mt76.mutex);190 191	if (vif->type == NL80211_IFTYPE_MONITOR &&192	    is_zero_ether_addr(vif->addr))193		phy->monitor_vif = vif;194 195	mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);196	if (mvif->mt76.idx >= mt7996_max_interface_num(dev)) {197		ret = -ENOSPC;198		goto out;199	}200 201	idx = get_omac_idx(vif->type, phy->omac_mask);202	if (idx < 0) {203		ret = -ENOSPC;204		goto out;205	}206	mvif->mt76.omac_idx = idx;207	mvif->phy = phy;208	mvif->mt76.band_idx = band_idx;209	mvif->mt76.wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3;210 211	ret = mt7996_mcu_add_dev_info(phy, vif, true);212	if (ret)213		goto out;214 215	dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);216	phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);217 218	idx = MT7996_WTBL_RESERVED - mvif->mt76.idx;219 220	INIT_LIST_HEAD(&mvif->sta.rc_list);221	INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);222	mvif->sta.wcid.idx = idx;223	mvif->sta.wcid.phy_idx = band_idx;224	mvif->sta.wcid.hw_key_idx = -1;225	mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;226	mt76_wcid_init(&mvif->sta.wcid);227 228	mt7996_mac_wtbl_update(dev, idx,229			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);230 231	if (vif->txq) {232		mtxq = (struct mt76_txq *)vif->txq->drv_priv;233		mtxq->wcid = idx;234	}235 236	if (vif->type != NL80211_IFTYPE_AP &&237	    (!mvif->mt76.omac_idx || mvif->mt76.omac_idx > 3))238		vif->offload_flags = 0;239	vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;240 241	if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)242		mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;243	else244		mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL;245 246	mt7996_init_bitrate_mask(vif);247 248	mt7996_mcu_add_bss_info(phy, vif, true);249	/* defer the first STA_REC of BMC entry to BSS_CHANGED_BSSID for STA250	 * interface, since firmware only records BSSID when the entry is new251	 */252	if (vif->type != NL80211_IFTYPE_STATION)253		mt7996_mcu_add_sta(dev, vif, NULL, true, true);254	rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);255 256out:257	mutex_unlock(&dev->mt76.mutex);258 259	return ret;260}261 262static void mt7996_remove_interface(struct ieee80211_hw *hw,263				    struct ieee80211_vif *vif)264{265	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;266	struct mt7996_sta *msta = &mvif->sta;267	struct mt7996_dev *dev = mt7996_hw_dev(hw);268	struct mt7996_phy *phy = mt7996_hw_phy(hw);269	int idx = msta->wcid.idx;270 271	mt7996_mcu_add_sta(dev, vif, NULL, false, false);272	mt7996_mcu_add_bss_info(phy, vif, false);273 274	if (vif == phy->monitor_vif)275		phy->monitor_vif = NULL;276 277	mt7996_mcu_add_dev_info(phy, vif, false);278 279	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);280 281	mutex_lock(&dev->mt76.mutex);282	dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);283	phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);284	mutex_unlock(&dev->mt76.mutex);285 286	spin_lock_bh(&dev->mt76.sta_poll_lock);287	if (!list_empty(&msta->wcid.poll_list))288		list_del_init(&msta->wcid.poll_list);289	spin_unlock_bh(&dev->mt76.sta_poll_lock);290 291	mt76_wcid_cleanup(&dev->mt76, &msta->wcid);292}293 294int mt7996_set_channel(struct mt76_phy *mphy)295{296	struct mt7996_phy *phy = mphy->priv;297	int ret;298 299	ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);300	if (ret)301		goto out;302 303	ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH);304	if (ret)305		goto out;306 307	ret = mt7996_dfs_init_radar_detector(phy);308	mt7996_mac_cca_stats_reset(phy);309 310	mt7996_mac_reset_counters(phy);311	phy->noise = 0;312 313out:314	ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,315				     MT7996_WATCHDOG_TIME);316 317	return ret;318}319 320static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,321			  struct ieee80211_vif *vif, struct ieee80211_sta *sta,322			  struct ieee80211_key_conf *key)323{324	struct mt7996_dev *dev = mt7996_hw_dev(hw);325	struct mt7996_phy *phy = mt7996_hw_phy(hw);326	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;327	struct mt7996_sta *msta = sta ? (struct mt7996_sta *)sta->drv_priv :328				  &mvif->sta;329	struct mt76_wcid *wcid = &msta->wcid;330	u8 *wcid_keyidx = &wcid->hw_key_idx;331	int idx = key->keyidx;332	int err = 0;333 334	/* The hardware does not support per-STA RX GTK, fallback335	 * to software mode for these.336	 */337	if ((vif->type == NL80211_IFTYPE_ADHOC ||338	     vif->type == NL80211_IFTYPE_MESH_POINT) &&339	    (key->cipher == WLAN_CIPHER_SUITE_TKIP ||340	     key->cipher == WLAN_CIPHER_SUITE_CCMP) &&341	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))342		return -EOPNOTSUPP;343 344	/* fall back to sw encryption for unsupported ciphers */345	switch (key->cipher) {346	case WLAN_CIPHER_SUITE_TKIP:347	case WLAN_CIPHER_SUITE_CCMP:348	case WLAN_CIPHER_SUITE_CCMP_256:349	case WLAN_CIPHER_SUITE_GCMP:350	case WLAN_CIPHER_SUITE_GCMP_256:351	case WLAN_CIPHER_SUITE_SMS4:352		break;353	case WLAN_CIPHER_SUITE_AES_CMAC:354	case WLAN_CIPHER_SUITE_BIP_CMAC_256:355	case WLAN_CIPHER_SUITE_BIP_GMAC_128:356	case WLAN_CIPHER_SUITE_BIP_GMAC_256:357		if (key->keyidx == 6 || key->keyidx == 7) {358			wcid_keyidx = &wcid->hw_key_idx2;359			key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;360			break;361		}362		fallthrough;363	case WLAN_CIPHER_SUITE_WEP40:364	case WLAN_CIPHER_SUITE_WEP104:365	default:366		return -EOPNOTSUPP;367	}368 369	mutex_lock(&dev->mt76.mutex);370 371	if (cmd == SET_KEY && !sta && !mvif->mt76.cipher) {372		mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher);373		mt7996_mcu_add_bss_info(phy, vif, true);374	}375 376	if (cmd == SET_KEY) {377		*wcid_keyidx = idx;378	} else {379		if (idx == *wcid_keyidx)380			*wcid_keyidx = -1;381		goto out;382	}383 384	mt76_wcid_key_setup(&dev->mt76, wcid, key);385 386	if (key->keyidx == 6 || key->keyidx == 7)387		err = mt7996_mcu_bcn_prot_enable(dev, vif, key);388	else389		err = mt7996_mcu_add_key(&dev->mt76, vif, key,390					 MCU_WMWA_UNI_CMD(STA_REC_UPDATE),391					 &msta->wcid, cmd);392out:393	mutex_unlock(&dev->mt76.mutex);394 395	return err;396}397 398static int mt7996_config(struct ieee80211_hw *hw, u32 changed)399{400	struct mt7996_dev *dev = mt7996_hw_dev(hw);401	struct mt7996_phy *phy = mt7996_hw_phy(hw);402	int ret;403 404	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {405		ret = mt76_update_channel(phy->mt76);406		if (ret)407			return ret;408	}409 410	if (changed & (IEEE80211_CONF_CHANGE_POWER |411		       IEEE80211_CONF_CHANGE_CHANNEL)) {412		ret = mt7996_mcu_set_txpower_sku(phy);413		if (ret)414			return ret;415	}416 417	mutex_lock(&dev->mt76.mutex);418 419	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {420		bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);421 422		if (!enabled)423			phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;424		else425			phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;426 427		mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx),428			       MT_DMA_DCR0_RXD_G5_EN, enabled);429		mt76_wr(dev, MT_WF_RFCR(phy->mt76->band_idx), phy->rxfilter);430	}431 432	mutex_unlock(&dev->mt76.mutex);433 434	return 0;435}436 437static int438mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,439	       unsigned int link_id, u16 queue,440	       const struct ieee80211_tx_queue_params *params)441{442	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;443	static const u8 mq_to_aci[] = {444		[IEEE80211_AC_VO] = 3,445		[IEEE80211_AC_VI] = 2,446		[IEEE80211_AC_BE] = 0,447		[IEEE80211_AC_BK] = 1,448	};449 450	/* firmware uses access class index */451	mvif->queue_params[mq_to_aci[queue]] = *params;452	/* no need to update right away, we'll get BSS_CHANGED_QOS */453 454	return 0;455}456 457static void mt7996_configure_filter(struct ieee80211_hw *hw,458				    unsigned int changed_flags,459				    unsigned int *total_flags,460				    u64 multicast)461{462	struct mt7996_dev *dev = mt7996_hw_dev(hw);463	struct mt7996_phy *phy = mt7996_hw_phy(hw);464	u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |465			MT_WF_RFCR1_DROP_BF_POLL |466			MT_WF_RFCR1_DROP_BA |467			MT_WF_RFCR1_DROP_CFEND |468			MT_WF_RFCR1_DROP_CFACK;469	u32 flags = 0;470 471#define MT76_FILTER(_flag, _hw) do {					\472		flags |= *total_flags & FIF_##_flag;			\473		phy->rxfilter &= ~(_hw);				\474		phy->rxfilter |= !(flags & FIF_##_flag) * (_hw);	\475	} while (0)476 477	mutex_lock(&dev->mt76.mutex);478 479	phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |480			   MT_WF_RFCR_DROP_OTHER_BEACON |481			   MT_WF_RFCR_DROP_FRAME_REPORT |482			   MT_WF_RFCR_DROP_PROBEREQ |483			   MT_WF_RFCR_DROP_MCAST_FILTERED |484			   MT_WF_RFCR_DROP_MCAST |485			   MT_WF_RFCR_DROP_BCAST |486			   MT_WF_RFCR_DROP_DUPLICATE |487			   MT_WF_RFCR_DROP_A2_BSSID |488			   MT_WF_RFCR_DROP_UNWANTED_CTL |489			   MT_WF_RFCR_DROP_STBC_MULTI);490 491	MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |492			       MT_WF_RFCR_DROP_A3_MAC |493			       MT_WF_RFCR_DROP_A3_BSSID);494 495	MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL);496 497	MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |498			     MT_WF_RFCR_DROP_RTS |499			     MT_WF_RFCR_DROP_CTL_RSV |500			     MT_WF_RFCR_DROP_NDPA);501 502	*total_flags = flags;503	mt76_wr(dev, MT_WF_RFCR(phy->mt76->band_idx), phy->rxfilter);504 505	if (*total_flags & FIF_CONTROL)506		mt76_clear(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags);507	else508		mt76_set(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags);509 510	mutex_unlock(&dev->mt76.mutex);511}512 513static void514mt7996_update_bss_color(struct ieee80211_hw *hw,515			struct ieee80211_vif *vif,516			struct cfg80211_he_bss_color *bss_color)517{518	struct mt7996_dev *dev = mt7996_hw_dev(hw);519 520	switch (vif->type) {521	case NL80211_IFTYPE_AP: {522		struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;523 524		if (mvif->mt76.omac_idx > HW_BSSID_MAX)525			return;526		fallthrough;527	}528	case NL80211_IFTYPE_STATION:529		mt7996_mcu_update_bss_color(dev, vif, bss_color);530		break;531	default:532		break;533	}534}535 536static u8537mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,538		       bool beacon, bool mcast)539{540	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;541	struct mt76_phy *mphy = hw->priv;542	u16 rate;543	u8 i, idx;544 545	rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast);546 547	if (beacon) {548		struct mt7996_phy *phy = mphy->priv;549 550		/* odd index for driver, even index for firmware */551		idx = MT7996_BEACON_RATES_TBL + 2 * phy->mt76->band_idx;552		if (phy->beacon_rate != rate)553			mt7996_mcu_set_fixed_rate_table(phy, idx, rate, beacon);554 555		return idx;556	}557 558	idx = FIELD_GET(MT_TX_RATE_IDX, rate);559	for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)560		if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)561			return MT7996_BASIC_RATES_TBL + 2 * i;562 563	return mvif->basic_rates_idx;564}565 566static void567mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif,568		       struct ieee80211_bss_conf *info)569{570	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;571	struct mt7996_dev *dev = mt7996_hw_dev(hw);572	u8 band = mvif->mt76.band_idx;573	u32 *mu;574 575	mu = (u32 *)info->mu_group.membership;576	mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD0(band), mu[0]);577	mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD1(band), mu[1]);578 579	mu = (u32 *)info->mu_group.position;580	mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS0(band), mu[0]);581	mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS1(band), mu[1]);582	mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS2(band), mu[2]);583	mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS3(band), mu[3]);584}585 586static void mt7996_bss_info_changed(struct ieee80211_hw *hw,587				    struct ieee80211_vif *vif,588				    struct ieee80211_bss_conf *info,589				    u64 changed)590{591	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;592	struct mt7996_phy *phy = mt7996_hw_phy(hw);593	struct mt7996_dev *dev = mt7996_hw_dev(hw);594 595	mutex_lock(&dev->mt76.mutex);596 597	/* station mode uses BSSID to map the wlan entry to a peer,598	 * and then peer references bss_info_rfch to set bandwidth cap.599	 */600	if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||601	    (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) ||602	    (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {603		mt7996_mcu_add_bss_info(phy, vif, true);604		mt7996_mcu_add_sta(dev, vif, NULL, true,605				   !!(changed & BSS_CHANGED_BSSID));606	}607 608	if (changed & BSS_CHANGED_ERP_CTS_PROT)609		mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot);610 611	if (changed & BSS_CHANGED_ERP_SLOT) {612		int slottime = info->use_short_slot ? 9 : 20;613 614		if (slottime != phy->slottime) {615			phy->slottime = slottime;616			mt7996_mcu_set_timing(phy, vif);617		}618	}619 620	if (changed & BSS_CHANGED_MCAST_RATE)621		mvif->mcast_rates_idx =622			mt7996_get_rates_table(hw, vif, false, true);623 624	if (changed & BSS_CHANGED_BASIC_RATES)625		mvif->basic_rates_idx =626			mt7996_get_rates_table(hw, vif, false, false);627 628	/* ensure that enable txcmd_mode after bss_info */629	if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))630		mt7996_mcu_set_tx(dev, vif);631 632	if (changed & BSS_CHANGED_HE_OBSS_PD)633		mt7996_mcu_add_obss_spr(phy, vif, &info->he_obss_pd);634 635	if (changed & BSS_CHANGED_HE_BSS_COLOR)636		mt7996_update_bss_color(hw, vif, &info->he_bss_color);637 638	if (changed & (BSS_CHANGED_BEACON |639		       BSS_CHANGED_BEACON_ENABLED)) {640		mvif->beacon_rates_idx =641			mt7996_get_rates_table(hw, vif, true, false);642 643		mt7996_mcu_add_beacon(hw, vif, info->enable_beacon);644	}645 646	if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |647		       BSS_CHANGED_FILS_DISCOVERY))648		mt7996_mcu_beacon_inband_discov(dev, vif, changed);649 650	if (changed & BSS_CHANGED_MU_GROUPS)651		mt7996_update_mu_group(hw, vif, info);652 653	mutex_unlock(&dev->mt76.mutex);654}655 656static void657mt7996_channel_switch_beacon(struct ieee80211_hw *hw,658			     struct ieee80211_vif *vif,659			     struct cfg80211_chan_def *chandef)660{661	struct mt7996_dev *dev = mt7996_hw_dev(hw);662 663	mutex_lock(&dev->mt76.mutex);664	mt7996_mcu_add_beacon(hw, vif, true);665	mutex_unlock(&dev->mt76.mutex);666}667 668int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,669		       struct ieee80211_sta *sta)670{671	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);672	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;673	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;674	u8 band_idx = mvif->phy->mt76->band_idx;675	int ret, idx;676 677	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);678	if (idx < 0)679		return -ENOSPC;680 681	INIT_LIST_HEAD(&msta->rc_list);682	INIT_LIST_HEAD(&msta->wcid.poll_list);683	msta->vif = mvif;684	msta->wcid.sta = 1;685	msta->wcid.idx = idx;686	msta->wcid.phy_idx = band_idx;687	msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;688 689	ewma_avg_signal_init(&msta->avg_ack_signal);690 691	mt7996_mac_wtbl_update(dev, idx,692			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);693 694	ret = mt7996_mcu_add_sta(dev, vif, sta, true, true);695	if (ret)696		return ret;697 698	return mt7996_mcu_add_rate_ctrl(dev, vif, sta, false);699}700 701void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,702			   struct ieee80211_sta *sta)703{704	struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);705	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;706	int i;707 708	mt7996_mcu_add_sta(dev, vif, sta, false, false);709 710	mt7996_mac_wtbl_update(dev, msta->wcid.idx,711			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);712 713	for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)714		mt7996_mac_twt_teardown_flow(dev, msta, i);715 716	spin_lock_bh(&mdev->sta_poll_lock);717	if (!list_empty(&msta->wcid.poll_list))718		list_del_init(&msta->wcid.poll_list);719	if (!list_empty(&msta->rc_list))720		list_del_init(&msta->rc_list);721	spin_unlock_bh(&mdev->sta_poll_lock);722}723 724static void mt7996_tx(struct ieee80211_hw *hw,725		      struct ieee80211_tx_control *control,726		      struct sk_buff *skb)727{728	struct mt7996_dev *dev = mt7996_hw_dev(hw);729	struct mt76_phy *mphy = hw->priv;730	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);731	struct ieee80211_vif *vif = info->control.vif;732	struct mt76_wcid *wcid = &dev->mt76.global_wcid;733 734	if (control->sta) {735		struct mt7996_sta *sta;736 737		sta = (struct mt7996_sta *)control->sta->drv_priv;738		wcid = &sta->wcid;739	}740 741	if (vif && !control->sta) {742		struct mt7996_vif *mvif;743 744		mvif = (struct mt7996_vif *)vif->drv_priv;745		wcid = &mvif->sta.wcid;746	}747 748	mt76_tx(mphy, control->sta, wcid, skb);749}750 751static int mt7996_set_rts_threshold(struct ieee80211_hw *hw, u32 val)752{753	struct mt7996_phy *phy = mt7996_hw_phy(hw);754	int ret;755 756	mutex_lock(&phy->dev->mt76.mutex);757	ret = mt7996_mcu_set_rts_thresh(phy, val);758	mutex_unlock(&phy->dev->mt76.mutex);759 760	return ret;761}762 763static int764mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,765		    struct ieee80211_ampdu_params *params)766{767	enum ieee80211_ampdu_mlme_action action = params->action;768	struct mt7996_dev *dev = mt7996_hw_dev(hw);769	struct ieee80211_sta *sta = params->sta;770	struct ieee80211_txq *txq = sta->txq[params->tid];771	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;772	u16 tid = params->tid;773	u16 ssn = params->ssn;774	struct mt76_txq *mtxq;775	int ret = 0;776 777	if (!txq)778		return -EINVAL;779 780	mtxq = (struct mt76_txq *)txq->drv_priv;781 782	mutex_lock(&dev->mt76.mutex);783	switch (action) {784	case IEEE80211_AMPDU_RX_START:785		mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,786				   params->buf_size);787		ret = mt7996_mcu_add_rx_ba(dev, params, true);788		break;789	case IEEE80211_AMPDU_RX_STOP:790		mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);791		ret = mt7996_mcu_add_rx_ba(dev, params, false);792		break;793	case IEEE80211_AMPDU_TX_OPERATIONAL:794		mtxq->aggr = true;795		mtxq->send_bar = false;796		ret = mt7996_mcu_add_tx_ba(dev, params, true);797		break;798	case IEEE80211_AMPDU_TX_STOP_FLUSH:799	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:800		mtxq->aggr = false;801		clear_bit(tid, &msta->wcid.ampdu_state);802		ret = mt7996_mcu_add_tx_ba(dev, params, false);803		break;804	case IEEE80211_AMPDU_TX_START:805		set_bit(tid, &msta->wcid.ampdu_state);806		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;807		break;808	case IEEE80211_AMPDU_TX_STOP_CONT:809		mtxq->aggr = false;810		clear_bit(tid, &msta->wcid.ampdu_state);811		ret = mt7996_mcu_add_tx_ba(dev, params, false);812		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);813		break;814	}815	mutex_unlock(&dev->mt76.mutex);816 817	return ret;818}819 820static int821mt7996_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,822	       struct ieee80211_sta *sta)823{824	return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST,825			      IEEE80211_STA_NONE);826}827 828static int829mt7996_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,830		  struct ieee80211_sta *sta)831{832	return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE,833			      IEEE80211_STA_NOTEXIST);834}835 836static int837mt7996_get_stats(struct ieee80211_hw *hw,838		 struct ieee80211_low_level_stats *stats)839{840	struct mt7996_phy *phy = mt7996_hw_phy(hw);841	struct mt7996_dev *dev = mt7996_hw_dev(hw);842	struct mt76_mib_stats *mib = &phy->mib;843 844	mutex_lock(&dev->mt76.mutex);845 846	stats->dot11RTSSuccessCount = mib->rts_cnt;847	stats->dot11RTSFailureCount = mib->rts_retries_cnt;848	stats->dot11FCSErrorCount = mib->fcs_err_cnt;849	stats->dot11ACKFailureCount = mib->ack_fail_cnt;850 851	mutex_unlock(&dev->mt76.mutex);852 853	return 0;854}855 856u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif)857{858	struct mt7996_dev *dev = mt7996_hw_dev(hw);859	struct mt7996_phy *phy = mt7996_hw_phy(hw);860	union {861		u64 t64;862		u32 t32[2];863	} tsf;864	u16 n;865 866	lockdep_assert_held(&dev->mt76.mutex);867 868	n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0869					       : mvif->mt76.omac_idx;870	/* TSF software read */871	mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE,872		 MT_LPON_TCR_SW_READ);873	tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(phy->mt76->band_idx));874	tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(phy->mt76->band_idx));875 876	return tsf.t64;877}878 879static u64880mt7996_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)881{882	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;883	struct mt7996_dev *dev = mt7996_hw_dev(hw);884	u64 ret;885 886	mutex_lock(&dev->mt76.mutex);887	ret = __mt7996_get_tsf(hw, mvif);888	mutex_unlock(&dev->mt76.mutex);889 890	return ret;891}892 893static void894mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,895	       u64 timestamp)896{897	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;898	struct mt7996_dev *dev = mt7996_hw_dev(hw);899	struct mt7996_phy *phy = mt7996_hw_phy(hw);900	union {901		u64 t64;902		u32 t32[2];903	} tsf = { .t64 = timestamp, };904	u16 n;905 906	mutex_lock(&dev->mt76.mutex);907 908	n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0909					       : mvif->mt76.omac_idx;910	mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]);911	mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]);912	/* TSF software overwrite */913	mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE,914		 MT_LPON_TCR_SW_WRITE);915 916	mutex_unlock(&dev->mt76.mutex);917}918 919static void920mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,921		  s64 timestamp)922{923	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;924	struct mt7996_dev *dev = mt7996_hw_dev(hw);925	struct mt7996_phy *phy = mt7996_hw_phy(hw);926	union {927		u64 t64;928		u32 t32[2];929	} tsf = { .t64 = timestamp, };930	u16 n;931 932	mutex_lock(&dev->mt76.mutex);933 934	n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0935					       : mvif->mt76.omac_idx;936	mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]);937	mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]);938	/* TSF software adjust*/939	mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE,940		 MT_LPON_TCR_SW_ADJUST);941 942	mutex_unlock(&dev->mt76.mutex);943}944 945static void946mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)947{948	struct mt7996_phy *phy = mt7996_hw_phy(hw);949	struct mt7996_dev *dev = phy->dev;950 951	mutex_lock(&dev->mt76.mutex);952	phy->coverage_class = max_t(s16, coverage_class, 0);953	mt7996_mac_set_coverage_class(phy);954	mutex_unlock(&dev->mt76.mutex);955}956 957static int958mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)959{960	struct mt7996_dev *dev = mt7996_hw_dev(hw);961	struct mt7996_phy *phy = mt7996_hw_phy(hw);962	int max_nss = hweight8(hw->wiphy->available_antennas_tx);963	u8 band_idx = phy->mt76->band_idx, shift = dev->chainshift[band_idx];964 965	if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss)966		return -EINVAL;967 968	if ((BIT(hweight8(tx_ant)) - 1) != tx_ant)969		tx_ant = BIT(ffs(tx_ant) - 1) - 1;970 971	mutex_lock(&dev->mt76.mutex);972 973	phy->mt76->antenna_mask = tx_ant;974 975	/* restore to the origin chainmask which might have auxiliary path */976	if (hweight8(tx_ant) == max_nss && band_idx < MT_BAND2)977		phy->mt76->chainmask = ((dev->chainmask >> shift) &978					(BIT(dev->chainshift[band_idx + 1] - shift) - 1)) << shift;979	else if (hweight8(tx_ant) == max_nss)980		phy->mt76->chainmask = (dev->chainmask >> shift) << shift;981	else982		phy->mt76->chainmask = tx_ant << shift;983 984	mt76_set_stream_caps(phy->mt76, true);985	mt7996_set_stream_vht_txbf_caps(phy);986	mt7996_set_stream_he_eht_caps(phy);987	mt7996_mcu_set_txpower_sku(phy);988 989	mutex_unlock(&dev->mt76.mutex);990 991	return 0;992}993 994static void mt7996_sta_statistics(struct ieee80211_hw *hw,995				  struct ieee80211_vif *vif,996				  struct ieee80211_sta *sta,997				  struct station_info *sinfo)998{999	struct mt7996_phy *phy = mt7996_hw_phy(hw);1000	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;1001	struct rate_info *txrate = &msta->wcid.rate;1002 1003	if (txrate->legacy || txrate->flags) {1004		if (txrate->legacy) {1005			sinfo->txrate.legacy = txrate->legacy;1006		} else {1007			sinfo->txrate.mcs = txrate->mcs;1008			sinfo->txrate.nss = txrate->nss;1009			sinfo->txrate.bw = txrate->bw;1010			sinfo->txrate.he_gi = txrate->he_gi;1011			sinfo->txrate.he_dcm = txrate->he_dcm;1012			sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;1013			sinfo->txrate.eht_gi = txrate->eht_gi;1014		}1015		sinfo->txrate.flags = txrate->flags;1016		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);1017	}1018	sinfo->txrate.flags = txrate->flags;1019	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);1020 1021	sinfo->tx_failed = msta->wcid.stats.tx_failed;1022	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);1023 1024	sinfo->tx_retries = msta->wcid.stats.tx_retries;1025	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);1026 1027	sinfo->ack_signal = (s8)msta->ack_signal;1028	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);1029 1030	sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);1031	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);1032 1033	if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {1034		sinfo->tx_bytes = msta->wcid.stats.tx_bytes;1035		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);1036 1037		sinfo->rx_bytes = msta->wcid.stats.rx_bytes;1038		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);1039 1040		sinfo->tx_packets = msta->wcid.stats.tx_packets;1041		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);1042 1043		sinfo->rx_packets = msta->wcid.stats.rx_packets;1044		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);1045	}1046}1047 1048static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)1049{1050	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;1051	struct mt7996_dev *dev = msta->vif->phy->dev;1052	u32 *changed = data;1053 1054	spin_lock_bh(&dev->mt76.sta_poll_lock);1055	msta->changed |= *changed;1056	if (list_empty(&msta->rc_list))1057		list_add_tail(&msta->rc_list, &dev->sta_rc_list);1058	spin_unlock_bh(&dev->mt76.sta_poll_lock);1059}1060 1061static void mt7996_sta_rc_update(struct ieee80211_hw *hw,1062				 struct ieee80211_vif *vif,1063				 struct ieee80211_sta *sta,1064				 u32 changed)1065{1066	struct mt7996_phy *phy = mt7996_hw_phy(hw);1067	struct mt7996_dev *dev = phy->dev;1068 1069	mt7996_sta_rc_work(&changed, sta);1070	ieee80211_queue_work(hw, &dev->rc_work);1071}1072 1073static int1074mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,1075			const struct cfg80211_bitrate_mask *mask)1076{1077	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;1078	struct mt7996_phy *phy = mt7996_hw_phy(hw);1079	struct mt7996_dev *dev = phy->dev;1080	u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;1081 1082	mvif->bitrate_mask = *mask;1083 1084	/* if multiple rates across different preambles are given we can1085	 * reconfigure this info with all peers using sta_rec command with1086	 * the below exception cases.1087	 * - single rate : if a rate is passed along with different preambles,1088	 * we select the highest one as fixed rate. i.e VHT MCS for VHT peers.1089	 * - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT1090	 * then multiple MCS setting (MCS 4,5,6) is not supported.1091	 */1092	ieee80211_iterate_stations_atomic(hw, mt7996_sta_rc_work, &changed);1093	ieee80211_queue_work(hw, &dev->rc_work);1094 1095	return 0;1096}1097 1098static void mt7996_sta_set_4addr(struct ieee80211_hw *hw,1099				 struct ieee80211_vif *vif,1100				 struct ieee80211_sta *sta,1101				 bool enabled)1102{1103	struct mt7996_dev *dev = mt7996_hw_dev(hw);1104	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;1105 1106	if (enabled)1107		set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);1108	else1109		clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);1110 1111	mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta);1112}1113 1114static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,1115					 struct ieee80211_vif *vif,1116					 struct ieee80211_sta *sta,1117					 bool enabled)1118{1119	struct mt7996_dev *dev = mt7996_hw_dev(hw);1120	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;1121 1122	if (enabled)1123		set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);1124	else1125		clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);1126 1127	mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta);1128}1129 1130static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = {1131	"tx_ampdu_cnt",1132	"tx_stop_q_empty_cnt",1133	"tx_mpdu_attempts",1134	"tx_mpdu_success",1135	"tx_rwp_fail_cnt",1136	"tx_rwp_need_cnt",1137	"tx_pkt_ebf_cnt",1138	"tx_pkt_ibf_cnt",1139	"tx_ampdu_len:0-1",1140	"tx_ampdu_len:2-10",1141	"tx_ampdu_len:11-19",1142	"tx_ampdu_len:20-28",1143	"tx_ampdu_len:29-37",1144	"tx_ampdu_len:38-46",1145	"tx_ampdu_len:47-55",1146	"tx_ampdu_len:56-79",1147	"tx_ampdu_len:80-103",1148	"tx_ampdu_len:104-127",1149	"tx_ampdu_len:128-151",1150	"tx_ampdu_len:152-175",1151	"tx_ampdu_len:176-199",1152	"tx_ampdu_len:200-223",1153	"tx_ampdu_len:224-247",1154	"ba_miss_count",1155	"tx_beamformer_ppdu_iBF",1156	"tx_beamformer_ppdu_eBF",1157	"tx_beamformer_rx_feedback_all",1158	"tx_beamformer_rx_feedback_he",1159	"tx_beamformer_rx_feedback_vht",1160	"tx_beamformer_rx_feedback_ht",1161	"tx_beamformer_rx_feedback_bw", /* zero based idx: 20, 40, 80, 160 */1162	"tx_beamformer_rx_feedback_nc",1163	"tx_beamformer_rx_feedback_nr",1164	"tx_beamformee_ok_feedback_pkts",1165	"tx_beamformee_feedback_trig",1166	"tx_mu_beamforming",1167	"tx_mu_mpdu",1168	"tx_mu_successful_mpdu",1169	"tx_su_successful_mpdu",1170	"tx_msdu_pack_1",1171	"tx_msdu_pack_2",1172	"tx_msdu_pack_3",1173	"tx_msdu_pack_4",1174	"tx_msdu_pack_5",1175	"tx_msdu_pack_6",1176	"tx_msdu_pack_7",1177	"tx_msdu_pack_8",1178 1179	/* rx counters */1180	"rx_fifo_full_cnt",1181	"rx_mpdu_cnt",1182	"channel_idle_cnt",1183	"rx_vector_mismatch_cnt",1184	"rx_delimiter_fail_cnt",1185	"rx_len_mismatch_cnt",1186	"rx_ampdu_cnt",1187	"rx_ampdu_bytes_cnt",1188	"rx_ampdu_valid_subframe_cnt",1189	"rx_ampdu_valid_subframe_b_cnt",1190	"rx_pfdrop_cnt",1191	"rx_vec_queue_overflow_drop_cnt",1192	"rx_ba_cnt",1193 1194	/* per vif counters */1195	"v_tx_mode_cck",1196	"v_tx_mode_ofdm",1197	"v_tx_mode_ht",1198	"v_tx_mode_ht_gf",1199	"v_tx_mode_vht",1200	"v_tx_mode_he_su",1201	"v_tx_mode_he_ext_su",1202	"v_tx_mode_he_tb",1203	"v_tx_mode_he_mu",1204	"v_tx_mode_eht_su",1205	"v_tx_mode_eht_trig",1206	"v_tx_mode_eht_mu",1207	"v_tx_bw_20",1208	"v_tx_bw_40",1209	"v_tx_bw_80",1210	"v_tx_bw_160",1211	"v_tx_bw_320",1212	"v_tx_mcs_0",1213	"v_tx_mcs_1",1214	"v_tx_mcs_2",1215	"v_tx_mcs_3",1216	"v_tx_mcs_4",1217	"v_tx_mcs_5",1218	"v_tx_mcs_6",1219	"v_tx_mcs_7",1220	"v_tx_mcs_8",1221	"v_tx_mcs_9",1222	"v_tx_mcs_10",1223	"v_tx_mcs_11",1224	"v_tx_mcs_12",1225	"v_tx_mcs_13",1226	"v_tx_nss_1",1227	"v_tx_nss_2",1228	"v_tx_nss_3",1229	"v_tx_nss_4",1230};1231 1232#define MT7996_SSTATS_LEN ARRAY_SIZE(mt7996_gstrings_stats)1233 1234/* Ethtool related API */1235static1236void mt7996_get_et_strings(struct ieee80211_hw *hw,1237			   struct ieee80211_vif *vif,1238			   u32 sset, u8 *data)1239{1240	if (sset == ETH_SS_STATS)1241		memcpy(data, mt7996_gstrings_stats,1242		       sizeof(mt7996_gstrings_stats));1243}1244 1245static1246int mt7996_get_et_sset_count(struct ieee80211_hw *hw,1247			     struct ieee80211_vif *vif, int sset)1248{1249	if (sset == ETH_SS_STATS)1250		return MT7996_SSTATS_LEN;1251 1252	return 0;1253}1254 1255static void mt7996_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)1256{1257	struct mt76_ethtool_worker_info *wi = wi_data;1258	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;1259 1260	if (msta->vif->mt76.idx != wi->idx)1261		return;1262 1263	mt76_ethtool_worker(wi, &msta->wcid.stats, true);1264}1265 1266static1267void mt7996_get_et_stats(struct ieee80211_hw *hw,1268			 struct ieee80211_vif *vif,1269			 struct ethtool_stats *stats, u64 *data)1270{1271	struct mt7996_dev *dev = mt7996_hw_dev(hw);1272	struct mt7996_phy *phy = mt7996_hw_phy(hw);1273	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;1274	struct mt76_mib_stats *mib = &phy->mib;1275	struct mt76_ethtool_worker_info wi = {1276		.data = data,1277		.idx = mvif->mt76.idx,1278	};1279	/* See mt7996_ampdu_stat_read_phy, etc */1280	int i, ei = 0;1281 1282	mutex_lock(&dev->mt76.mutex);1283 1284	mt7996_mac_update_stats(phy);1285 1286	data[ei++] = mib->tx_ampdu_cnt;1287	data[ei++] = mib->tx_stop_q_empty_cnt;1288	data[ei++] = mib->tx_mpdu_attempts_cnt;1289	data[ei++] = mib->tx_mpdu_success_cnt;1290	data[ei++] = mib->tx_rwp_fail_cnt;1291	data[ei++] = mib->tx_rwp_need_cnt;1292	data[ei++] = mib->tx_bf_ebf_ppdu_cnt;1293	data[ei++] = mib->tx_bf_ibf_ppdu_cnt;1294 1295	/* Tx ampdu stat */1296	for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++)1297		data[ei++] = phy->mt76->aggr_stats[i];1298	data[ei++] = phy->mib.ba_miss_cnt;1299 1300	/* Tx Beamformer monitor */1301	data[ei++] = mib->tx_bf_ibf_ppdu_cnt;1302	data[ei++] = mib->tx_bf_ebf_ppdu_cnt;1303 1304	/* Tx Beamformer Rx feedback monitor */1305	data[ei++] = mib->tx_bf_rx_fb_all_cnt;1306	data[ei++] = mib->tx_bf_rx_fb_he_cnt;1307	data[ei++] = mib->tx_bf_rx_fb_vht_cnt;1308	data[ei++] = mib->tx_bf_rx_fb_ht_cnt;1309 1310	data[ei++] = mib->tx_bf_rx_fb_bw;1311	data[ei++] = mib->tx_bf_rx_fb_nc_cnt;1312	data[ei++] = mib->tx_bf_rx_fb_nr_cnt;1313 1314	/* Tx Beamformee Rx NDPA & Tx feedback report */1315	data[ei++] = mib->tx_bf_fb_cpl_cnt;1316	data[ei++] = mib->tx_bf_fb_trig_cnt;1317 1318	/* Tx SU & MU counters */1319	data[ei++] = mib->tx_mu_bf_cnt;1320	data[ei++] = mib->tx_mu_mpdu_cnt;1321	data[ei++] = mib->tx_mu_acked_mpdu_cnt;1322	data[ei++] = mib->tx_su_acked_mpdu_cnt;1323 1324	/* Tx amsdu info (pack-count histogram) */1325	for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++)1326		data[ei++] = mib->tx_amsdu[i];1327 1328	/* rx counters */1329	data[ei++] = mib->rx_fifo_full_cnt;1330	data[ei++] = mib->rx_mpdu_cnt;1331	data[ei++] = mib->channel_idle_cnt;1332	data[ei++] = mib->rx_vector_mismatch_cnt;1333	data[ei++] = mib->rx_delimiter_fail_cnt;1334	data[ei++] = mib->rx_len_mismatch_cnt;1335	data[ei++] = mib->rx_ampdu_cnt;1336	data[ei++] = mib->rx_ampdu_bytes_cnt;1337	data[ei++] = mib->rx_ampdu_valid_subframe_cnt;1338	data[ei++] = mib->rx_ampdu_valid_subframe_bytes_cnt;1339	data[ei++] = mib->rx_pfdrop_cnt;1340	data[ei++] = mib->rx_vec_queue_overflow_drop_cnt;1341	data[ei++] = mib->rx_ba_cnt;1342 1343	/* Add values for all stations owned by this vif */1344	wi.initial_stat_idx = ei;1345	ieee80211_iterate_stations_atomic(hw, mt7996_ethtool_worker, &wi);1346 1347	mutex_unlock(&dev->mt76.mutex);1348 1349	if (wi.sta_count == 0)1350		return;1351 1352	ei += wi.worker_stat_count;1353	if (ei != MT7996_SSTATS_LEN)1354		dev_err(dev->mt76.dev, "ei: %d  MT7996_SSTATS_LEN: %d",1355			ei, (int)MT7996_SSTATS_LEN);1356}1357 1358static void1359mt7996_twt_teardown_request(struct ieee80211_hw *hw,1360			    struct ieee80211_sta *sta,1361			    u8 flowid)1362{1363	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;1364	struct mt7996_dev *dev = mt7996_hw_dev(hw);1365 1366	mutex_lock(&dev->mt76.mutex);1367	mt7996_mac_twt_teardown_flow(dev, msta, flowid);1368	mutex_unlock(&dev->mt76.mutex);1369}1370 1371static int1372mt7996_set_radar_background(struct ieee80211_hw *hw,1373			    struct cfg80211_chan_def *chandef)1374{1375	struct mt7996_phy *phy = mt7996_hw_phy(hw);1376	struct mt7996_dev *dev = phy->dev;1377	int ret = -EINVAL;1378	bool running;1379 1380	mutex_lock(&dev->mt76.mutex);1381 1382	if (dev->mt76.region == NL80211_DFS_UNSET)1383		goto out;1384 1385	if (dev->rdd2_phy && dev->rdd2_phy != phy) {1386		/* rdd2 is already locked */1387		ret = -EBUSY;1388		goto out;1389	}1390 1391	/* rdd2 already configured on a radar channel */1392	running = dev->rdd2_phy &&1393		  cfg80211_chandef_valid(&dev->rdd2_chandef) &&1394		  !!(dev->rdd2_chandef.chan->flags & IEEE80211_CHAN_RADAR);1395 1396	if (!chandef || running ||1397	    !(chandef->chan->flags & IEEE80211_CHAN_RADAR)) {1398		ret = mt7996_mcu_rdd_background_enable(phy, NULL);1399		if (ret)1400			goto out;1401 1402		if (!running)1403			goto update_phy;1404	}1405 1406	ret = mt7996_mcu_rdd_background_enable(phy, chandef);1407	if (ret)1408		goto out;1409 1410update_phy:1411	dev->rdd2_phy = chandef ? phy : NULL;1412	if (chandef)1413		dev->rdd2_chandef = *chandef;1414out:1415	mutex_unlock(&dev->mt76.mutex);1416 1417	return ret;1418}1419 1420#ifdef CONFIG_NET_MEDIATEK_SOC_WED1421static int1422mt7996_net_fill_forward_path(struct ieee80211_hw *hw,1423			     struct ieee80211_vif *vif,1424			     struct ieee80211_sta *sta,1425			     struct net_device_path_ctx *ctx,1426			     struct net_device_path *path)1427{1428	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;1429	struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;1430	struct mt7996_dev *dev = mt7996_hw_dev(hw);1431	struct mt7996_phy *phy = mt7996_hw_phy(hw);1432	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;1433 1434	if (phy != &dev->phy && phy->mt76->band_idx == MT_BAND2)1435		wed = &dev->mt76.mmio.wed_hif2;1436 1437	if (!mtk_wed_device_active(wed))1438		return -ENODEV;1439 1440	if (msta->wcid.idx > MT7996_WTBL_STA)1441		return -EIO;1442 1443	path->type = DEV_PATH_MTK_WDMA;1444	path->dev = ctx->dev;1445	path->mtk_wdma.wdma_idx = wed->wdma_idx;1446	path->mtk_wdma.bss = mvif->mt76.idx;1447	path->mtk_wdma.queue = 0;1448	path->mtk_wdma.wcid = msta->wcid.idx;1449 1450	path->mtk_wdma.amsdu = mtk_wed_is_amsdu_supported(wed);1451	ctx->dev = NULL;1452 1453	return 0;1454}1455 1456#endif1457 1458const struct ieee80211_ops mt7996_ops = {1459	.add_chanctx = ieee80211_emulate_add_chanctx,1460	.remove_chanctx = ieee80211_emulate_remove_chanctx,1461	.change_chanctx = ieee80211_emulate_change_chanctx,1462	.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,1463	.tx = mt7996_tx,1464	.start = mt7996_start,1465	.stop = mt7996_stop,1466	.add_interface = mt7996_add_interface,1467	.remove_interface = mt7996_remove_interface,1468	.config = mt7996_config,1469	.conf_tx = mt7996_conf_tx,1470	.configure_filter = mt7996_configure_filter,1471	.bss_info_changed = mt7996_bss_info_changed,1472	.sta_add = mt7996_sta_add,1473	.sta_remove = mt7996_sta_remove,1474	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,1475	.sta_rc_update = mt7996_sta_rc_update,1476	.set_key = mt7996_set_key,1477	.ampdu_action = mt7996_ampdu_action,1478	.set_rts_threshold = mt7996_set_rts_threshold,1479	.wake_tx_queue = mt76_wake_tx_queue,1480	.sw_scan_start = mt76_sw_scan,1481	.sw_scan_complete = mt76_sw_scan_complete,1482	.release_buffered_frames = mt76_release_buffered_frames,1483	.get_txpower = mt76_get_txpower,1484	.channel_switch_beacon = mt7996_channel_switch_beacon,1485	.get_stats = mt7996_get_stats,1486	.get_et_sset_count = mt7996_get_et_sset_count,1487	.get_et_stats = mt7996_get_et_stats,1488	.get_et_strings = mt7996_get_et_strings,1489	.get_tsf = mt7996_get_tsf,1490	.set_tsf = mt7996_set_tsf,1491	.offset_tsf = mt7996_offset_tsf,1492	.get_survey = mt76_get_survey,1493	.get_antenna = mt76_get_antenna,1494	.set_antenna = mt7996_set_antenna,1495	.set_bitrate_mask = mt7996_set_bitrate_mask,1496	.set_coverage_class = mt7996_set_coverage_class,1497	.sta_statistics = mt7996_sta_statistics,1498	.sta_set_4addr = mt7996_sta_set_4addr,1499	.sta_set_decap_offload = mt7996_sta_set_decap_offload,1500	.add_twt_setup = mt7996_mac_add_twt_setup,1501	.twt_teardown_request = mt7996_twt_teardown_request,1502#ifdef CONFIG_MAC80211_DEBUGFS1503	.sta_add_debugfs = mt7996_sta_add_debugfs,1504#endif1505	.set_radar_background = mt7996_set_radar_background,1506#ifdef CONFIG_NET_MEDIATEK_SOC_WED1507	.net_fill_forward_path = mt7996_net_fill_forward_path,1508	.net_setup_tc = mt76_wed_net_setup_tc,1509#endif1510};1511