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