Commit | Line | Data |
---|---|---|
c948b5da DW |
1 | // SPDX-License-Identifier: ISC |
2 | /* Copyright (C) 2023 MediaTek Inc. */ | |
3 | ||
4 | #include <linux/etherdevice.h> | |
5 | #include <linux/platform_device.h> | |
6 | #include <linux/pci.h> | |
7 | #include <linux/module.h> | |
8 | #include <linux/ctype.h> | |
9 | #include <net/ipv6.h> | |
10 | #include "mt7925.h" | |
11 | #include "mcu.h" | |
12 | #include "mac.h" | |
13 | ||
14 | static void | |
15 | mt7925_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, | |
16 | struct ieee80211_sband_iftype_data *data, | |
695bfba7 | 17 | enum nl80211_iftype iftype) |
c948b5da DW |
18 | { |
19 | struct ieee80211_sta_he_cap *he_cap = &data->he_cap; | |
20 | struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem; | |
21 | struct ieee80211_he_mcs_nss_supp *he_mcs = &he_cap->he_mcs_nss_supp; | |
22 | int i, nss = hweight8(phy->mt76->antenna_mask); | |
23 | u16 mcs_map = 0; | |
24 | ||
25 | for (i = 0; i < 8; i++) { | |
26 | if (i < nss) | |
27 | mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2)); | |
28 | else | |
29 | mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2)); | |
30 | } | |
31 | ||
32 | he_cap->has_he = true; | |
33 | ||
34 | he_cap_elem->mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE; | |
35 | he_cap_elem->mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_OMI_CONTROL | | |
36 | IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3; | |
37 | he_cap_elem->mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU; | |
38 | ||
39 | if (band == NL80211_BAND_2GHZ) | |
40 | he_cap_elem->phy_cap_info[0] = | |
41 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; | |
42 | else | |
43 | he_cap_elem->phy_cap_info[0] = | |
44 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | | |
45 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; | |
46 | ||
47 | he_cap_elem->phy_cap_info[1] = | |
48 | IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; | |
49 | he_cap_elem->phy_cap_info[2] = | |
50 | IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | | |
51 | IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | | |
52 | IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | | |
53 | IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | | |
54 | IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO; | |
55 | ||
695bfba7 | 56 | switch (iftype) { |
c948b5da DW |
57 | case NL80211_IFTYPE_AP: |
58 | he_cap_elem->mac_cap_info[2] |= | |
59 | IEEE80211_HE_MAC_CAP2_BSR; | |
60 | he_cap_elem->mac_cap_info[4] |= | |
61 | IEEE80211_HE_MAC_CAP4_BQR; | |
62 | he_cap_elem->mac_cap_info[5] |= | |
63 | IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX; | |
64 | he_cap_elem->phy_cap_info[3] |= | |
65 | IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | | |
66 | IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK; | |
67 | he_cap_elem->phy_cap_info[6] |= | |
68 | IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | | |
69 | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; | |
70 | he_cap_elem->phy_cap_info[9] |= | |
71 | IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | | |
72 | IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; | |
73 | break; | |
74 | case NL80211_IFTYPE_STATION: | |
75 | he_cap_elem->mac_cap_info[1] |= | |
76 | IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US; | |
77 | ||
78 | if (band == NL80211_BAND_2GHZ) | |
79 | he_cap_elem->phy_cap_info[0] |= | |
80 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G; | |
81 | else | |
82 | he_cap_elem->phy_cap_info[0] |= | |
83 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G; | |
84 | ||
85 | he_cap_elem->phy_cap_info[1] |= | |
86 | IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | | |
87 | IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; | |
88 | he_cap_elem->phy_cap_info[3] |= | |
89 | IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | | |
90 | IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK; | |
91 | he_cap_elem->phy_cap_info[4] |= | |
92 | IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE | | |
93 | IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 | | |
94 | IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4; | |
95 | he_cap_elem->phy_cap_info[5] |= | |
96 | IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | | |
97 | IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; | |
98 | he_cap_elem->phy_cap_info[6] |= | |
99 | IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | | |
100 | IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | | |
101 | IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB | | |
102 | IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | | |
103 | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; | |
104 | he_cap_elem->phy_cap_info[7] |= | |
105 | IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP | | |
106 | IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; | |
107 | he_cap_elem->phy_cap_info[8] |= | |
108 | IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | | |
109 | IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | | |
110 | IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU | | |
111 | IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484; | |
112 | he_cap_elem->phy_cap_info[9] |= | |
113 | IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM | | |
114 | IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK | | |
115 | IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | | |
116 | IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU | | |
117 | IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | | |
118 | IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; | |
119 | break; | |
120 | default: | |
121 | break; | |
122 | } | |
123 | ||
124 | he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map); | |
125 | he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map); | |
126 | he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map); | |
127 | he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map); | |
128 | ||
129 | memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); | |
130 | ||
131 | if (he_cap_elem->phy_cap_info[6] & | |
132 | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { | |
133 | mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss); | |
134 | } else { | |
135 | he_cap_elem->phy_cap_info[9] |= | |
136 | u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, | |
137 | IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK); | |
138 | } | |
139 | ||
140 | if (band == NL80211_BAND_6GHZ) { | |
141 | u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | | |
142 | IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS; | |
143 | ||
144 | cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_0_5, | |
145 | IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | | |
146 | u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, | |
147 | IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | | |
148 | u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, | |
149 | IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN); | |
150 | ||
151 | data->he_6ghz_capa.capa = cpu_to_le16(cap); | |
152 | } | |
153 | } | |
154 | ||
155 | static void | |
156 | mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band, | |
170a8969 | 157 | struct ieee80211_sband_iftype_data *data) |
c948b5da DW |
158 | { |
159 | struct ieee80211_sta_eht_cap *eht_cap = &data->eht_cap; | |
160 | struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem; | |
161 | struct ieee80211_eht_mcs_nss_supp *eht_nss = &eht_cap->eht_mcs_nss_supp; | |
162 | enum nl80211_chan_width width = phy->mt76->chandef.width; | |
163 | int nss = hweight8(phy->mt76->antenna_mask); | |
164 | int sts = hweight16(phy->mt76->chainmask); | |
165 | u8 val; | |
166 | ||
167 | if (!phy->dev->has_eht) | |
168 | return; | |
169 | ||
170 | eht_cap->has_eht = true; | |
171 | ||
172 | eht_cap_elem->mac_cap_info[0] = | |
173 | IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | | |
174 | IEEE80211_EHT_MAC_CAP0_OM_CONTROL; | |
175 | ||
176 | eht_cap_elem->phy_cap_info[0] = | |
177 | IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | | |
178 | IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | | |
179 | IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE; | |
180 | ||
181 | eht_cap_elem->phy_cap_info[0] |= | |
182 | u8_encode_bits(u8_get_bits(sts - 1, BIT(0)), | |
183 | IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK); | |
184 | ||
185 | eht_cap_elem->phy_cap_info[1] = | |
186 | u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)), | |
187 | IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) | | |
188 | u8_encode_bits(sts - 1, | |
189 | IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK); | |
190 | ||
191 | eht_cap_elem->phy_cap_info[2] = | |
192 | u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK) | | |
193 | u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK); | |
194 | ||
195 | eht_cap_elem->phy_cap_info[3] = | |
196 | IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | | |
197 | IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | | |
198 | IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | | |
199 | IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | | |
200 | IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | | |
201 | IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | | |
202 | IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK; | |
203 | ||
204 | eht_cap_elem->phy_cap_info[4] = | |
205 | u8_encode_bits(min_t(int, sts - 1, 2), | |
206 | IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK); | |
207 | ||
208 | eht_cap_elem->phy_cap_info[5] = | |
209 | IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | | |
210 | u8_encode_bits(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US, | |
211 | IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK) | | |
212 | u8_encode_bits(u8_get_bits(0x11, GENMASK(1, 0)), | |
213 | IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK); | |
214 | ||
215 | val = width == NL80211_CHAN_WIDTH_160 ? 0x7 : | |
216 | width == NL80211_CHAN_WIDTH_80 ? 0x3 : 0x1; | |
217 | eht_cap_elem->phy_cap_info[6] = | |
218 | u8_encode_bits(u8_get_bits(0x11, GENMASK(4, 2)), | |
219 | IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK) | | |
220 | u8_encode_bits(val, IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK); | |
221 | ||
222 | eht_cap_elem->phy_cap_info[7] = | |
223 | IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | | |
224 | IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | | |
225 | IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | | |
226 | IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ; | |
227 | ||
228 | val = u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_RX) | | |
229 | u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_TX); | |
230 | ||
231 | eht_nss->bw._80.rx_tx_mcs9_max_nss = val; | |
232 | eht_nss->bw._80.rx_tx_mcs11_max_nss = val; | |
233 | eht_nss->bw._80.rx_tx_mcs13_max_nss = val; | |
234 | eht_nss->bw._160.rx_tx_mcs9_max_nss = val; | |
235 | eht_nss->bw._160.rx_tx_mcs11_max_nss = val; | |
236 | eht_nss->bw._160.rx_tx_mcs13_max_nss = val; | |
237 | } | |
238 | ||
239 | static void | |
240 | __mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy, | |
241 | struct ieee80211_supported_band *sband, | |
242 | enum nl80211_band band) | |
243 | { | |
244 | struct ieee80211_sband_iftype_data *data = phy->iftype[band]; | |
245 | int i, n = 0; | |
246 | ||
247 | for (i = 0; i < NUM_NL80211_IFTYPES; i++) { | |
248 | switch (i) { | |
249 | case NL80211_IFTYPE_STATION: | |
250 | case NL80211_IFTYPE_AP: | |
251 | break; | |
252 | default: | |
253 | continue; | |
254 | } | |
255 | ||
256 | data[n].types_mask = BIT(i); | |
257 | mt7925_init_he_caps(phy, band, &data[n], i); | |
170a8969 | 258 | mt7925_init_eht_caps(phy, band, &data[n]); |
c948b5da DW |
259 | |
260 | n++; | |
261 | } | |
262 | ||
263 | _ieee80211_set_sband_iftype_data(sband, data, n); | |
264 | } | |
265 | ||
266 | void mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy) | |
267 | { | |
268 | if (phy->mt76->cap.has_2ghz) | |
269 | __mt7925_set_stream_he_eht_caps(phy, &phy->mt76->sband_2g.sband, | |
270 | NL80211_BAND_2GHZ); | |
271 | ||
272 | if (phy->mt76->cap.has_5ghz) | |
273 | __mt7925_set_stream_he_eht_caps(phy, &phy->mt76->sband_5g.sband, | |
274 | NL80211_BAND_5GHZ); | |
275 | ||
276 | if (phy->mt76->cap.has_6ghz) | |
277 | __mt7925_set_stream_he_eht_caps(phy, &phy->mt76->sband_6g.sband, | |
278 | NL80211_BAND_6GHZ); | |
279 | } | |
280 | ||
281 | int __mt7925_start(struct mt792x_phy *phy) | |
282 | { | |
283 | struct mt76_phy *mphy = phy->mt76; | |
284 | int err; | |
285 | ||
286 | err = mt7925_mcu_set_channel_domain(mphy); | |
287 | if (err) | |
288 | return err; | |
289 | ||
290 | err = mt7925_mcu_set_rts_thresh(phy, 0x92b); | |
291 | if (err) | |
292 | return err; | |
293 | ||
294 | err = mt7925_set_tx_sar_pwr(mphy->hw, NULL); | |
295 | if (err) | |
296 | return err; | |
297 | ||
298 | mt792x_mac_reset_counters(phy); | |
299 | set_bit(MT76_STATE_RUNNING, &mphy->state); | |
300 | ||
301 | ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, | |
302 | MT792x_WATCHDOG_TIME); | |
303 | ||
304 | return 0; | |
305 | } | |
306 | EXPORT_SYMBOL_GPL(__mt7925_start); | |
307 | ||
308 | static int mt7925_start(struct ieee80211_hw *hw) | |
309 | { | |
310 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
311 | int err; | |
312 | ||
313 | mt792x_mutex_acquire(phy->dev); | |
314 | err = __mt7925_start(phy); | |
315 | mt792x_mutex_release(phy->dev); | |
316 | ||
317 | return err; | |
318 | } | |
319 | ||
c948b5da DW |
320 | static int |
321 | mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |
322 | { | |
323 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
324 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
325 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
326 | struct mt76_txq *mtxq; | |
327 | int idx, ret = 0; | |
328 | ||
329 | mt792x_mutex_acquire(dev); | |
330 | ||
331 | mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); | |
332 | if (mvif->mt76.idx >= MT792x_MAX_INTERFACES) { | |
333 | ret = -ENOSPC; | |
334 | goto out; | |
335 | } | |
336 | ||
337 | mvif->mt76.omac_idx = mvif->mt76.idx; | |
338 | mvif->phy = phy; | |
339 | mvif->mt76.band_idx = 0; | |
340 | mvif->mt76.wmm_idx = mvif->mt76.idx % MT76_CONNAC_MAX_WMM_SETS; | |
341 | ||
342 | if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) | |
343 | mvif->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4; | |
344 | else | |
345 | mvif->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL; | |
346 | ||
347 | ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, | |
348 | true); | |
349 | if (ret) | |
350 | goto out; | |
351 | ||
352 | dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); | |
353 | phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); | |
354 | ||
355 | idx = MT792x_WTBL_RESERVED - mvif->mt76.idx; | |
356 | ||
357 | INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); | |
358 | mvif->sta.wcid.idx = idx; | |
359 | mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; | |
360 | mvif->sta.wcid.hw_key_idx = -1; | |
361 | mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; | |
362 | mt76_wcid_init(&mvif->sta.wcid); | |
363 | ||
364 | mt7925_mac_wtbl_update(dev, idx, | |
365 | MT_WTBL_UPDATE_ADM_COUNT_CLEAR); | |
366 | ||
367 | ewma_rssi_init(&mvif->rssi); | |
368 | ||
369 | rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); | |
370 | if (vif->txq) { | |
371 | mtxq = (struct mt76_txq *)vif->txq->drv_priv; | |
372 | mtxq->wcid = idx; | |
373 | } | |
374 | ||
375 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; | |
376 | out: | |
377 | mt792x_mutex_release(dev); | |
378 | ||
379 | return ret; | |
380 | } | |
381 | ||
382 | static void mt7925_roc_iter(void *priv, u8 *mac, | |
383 | struct ieee80211_vif *vif) | |
384 | { | |
385 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
386 | struct mt792x_phy *phy = priv; | |
387 | ||
388 | mt7925_mcu_abort_roc(phy, mvif, phy->roc_token_id); | |
389 | } | |
390 | ||
391 | void mt7925_roc_work(struct work_struct *work) | |
392 | { | |
393 | struct mt792x_phy *phy; | |
394 | ||
395 | phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy, | |
396 | roc_work); | |
397 | ||
398 | if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) | |
399 | return; | |
400 | ||
401 | mt792x_mutex_acquire(phy->dev); | |
402 | ieee80211_iterate_active_interfaces(phy->mt76->hw, | |
403 | IEEE80211_IFACE_ITER_RESUME_ALL, | |
404 | mt7925_roc_iter, phy); | |
405 | mt792x_mutex_release(phy->dev); | |
406 | ieee80211_remain_on_channel_expired(phy->mt76->hw); | |
407 | } | |
408 | ||
409 | static int mt7925_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif) | |
410 | { | |
411 | int err = 0; | |
412 | ||
413 | del_timer_sync(&phy->roc_timer); | |
414 | cancel_work_sync(&phy->roc_work); | |
415 | ||
416 | mt792x_mutex_acquire(phy->dev); | |
417 | if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) | |
418 | err = mt7925_mcu_abort_roc(phy, vif, phy->roc_token_id); | |
419 | mt792x_mutex_release(phy->dev); | |
420 | ||
421 | return err; | |
422 | } | |
423 | ||
424 | static int mt7925_set_roc(struct mt792x_phy *phy, | |
425 | struct mt792x_vif *vif, | |
426 | struct ieee80211_channel *chan, | |
427 | int duration, | |
428 | enum mt7925_roc_req type) | |
429 | { | |
430 | int err; | |
431 | ||
432 | if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state)) | |
433 | return -EBUSY; | |
434 | ||
435 | phy->roc_grant = false; | |
436 | ||
437 | err = mt7925_mcu_set_roc(phy, vif, chan, duration, type, | |
438 | ++phy->roc_token_id); | |
439 | if (err < 0) { | |
440 | clear_bit(MT76_STATE_ROC, &phy->mt76->state); | |
441 | goto out; | |
442 | } | |
443 | ||
444 | if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, 4 * HZ)) { | |
445 | mt7925_mcu_abort_roc(phy, vif, phy->roc_token_id); | |
446 | clear_bit(MT76_STATE_ROC, &phy->mt76->state); | |
447 | err = -ETIMEDOUT; | |
448 | } | |
449 | ||
450 | out: | |
451 | return err; | |
452 | } | |
453 | ||
454 | static int mt7925_remain_on_channel(struct ieee80211_hw *hw, | |
455 | struct ieee80211_vif *vif, | |
456 | struct ieee80211_channel *chan, | |
457 | int duration, | |
458 | enum ieee80211_roc_type type) | |
459 | { | |
460 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
461 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
462 | int err; | |
463 | ||
464 | mt792x_mutex_acquire(phy->dev); | |
465 | err = mt7925_set_roc(phy, mvif, chan, duration, MT7925_ROC_REQ_ROC); | |
466 | mt792x_mutex_release(phy->dev); | |
467 | ||
468 | return err; | |
469 | } | |
470 | ||
471 | static int mt7925_cancel_remain_on_channel(struct ieee80211_hw *hw, | |
472 | struct ieee80211_vif *vif) | |
473 | { | |
474 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
475 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
476 | ||
477 | return mt7925_abort_roc(phy, mvif); | |
478 | } | |
479 | ||
480 | static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |
481 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | |
482 | struct ieee80211_key_conf *key) | |
483 | { | |
484 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
485 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
486 | struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : | |
487 | &mvif->sta; | |
488 | struct mt76_wcid *wcid = &msta->wcid; | |
489 | u8 *wcid_keyidx = &wcid->hw_key_idx; | |
490 | int idx = key->keyidx, err = 0; | |
491 | ||
492 | /* The hardware does not support per-STA RX GTK, fallback | |
493 | * to software mode for these. | |
494 | */ | |
495 | if ((vif->type == NL80211_IFTYPE_ADHOC || | |
496 | vif->type == NL80211_IFTYPE_MESH_POINT) && | |
497 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || | |
498 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && | |
499 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | |
500 | return -EOPNOTSUPP; | |
501 | ||
502 | /* fall back to sw encryption for unsupported ciphers */ | |
503 | switch (key->cipher) { | |
504 | case WLAN_CIPHER_SUITE_AES_CMAC: | |
505 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; | |
506 | wcid_keyidx = &wcid->hw_key_idx2; | |
507 | break; | |
508 | case WLAN_CIPHER_SUITE_WEP40: | |
509 | case WLAN_CIPHER_SUITE_WEP104: | |
510 | if (!mvif->wep_sta) | |
511 | return -EOPNOTSUPP; | |
512 | break; | |
513 | case WLAN_CIPHER_SUITE_TKIP: | |
514 | case WLAN_CIPHER_SUITE_CCMP: | |
515 | case WLAN_CIPHER_SUITE_CCMP_256: | |
516 | case WLAN_CIPHER_SUITE_GCMP: | |
517 | case WLAN_CIPHER_SUITE_GCMP_256: | |
518 | case WLAN_CIPHER_SUITE_SMS4: | |
519 | break; | |
520 | default: | |
521 | return -EOPNOTSUPP; | |
522 | } | |
523 | ||
524 | mt792x_mutex_acquire(dev); | |
525 | ||
526 | if (cmd == SET_KEY && !mvif->mt76.cipher) { | |
527 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
528 | ||
529 | mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher); | |
530 | mt7925_mcu_add_bss_info(phy, mvif->mt76.ctx, vif, sta, true); | |
531 | } | |
532 | ||
533 | if (cmd == SET_KEY) | |
534 | *wcid_keyidx = idx; | |
535 | else if (idx == *wcid_keyidx) | |
536 | *wcid_keyidx = -1; | |
537 | else | |
538 | goto out; | |
539 | ||
540 | mt76_wcid_key_setup(&dev->mt76, wcid, | |
541 | cmd == SET_KEY ? key : NULL); | |
542 | ||
543 | err = mt7925_mcu_add_key(&dev->mt76, vif, &msta->bip, | |
544 | key, MCU_UNI_CMD(STA_REC_UPDATE), | |
545 | &msta->wcid, cmd); | |
546 | ||
547 | if (err) | |
548 | goto out; | |
549 | ||
550 | if (key->cipher == WLAN_CIPHER_SUITE_WEP104 || | |
551 | key->cipher == WLAN_CIPHER_SUITE_WEP40) | |
552 | err = mt7925_mcu_add_key(&dev->mt76, vif, &mvif->wep_sta->bip, | |
553 | key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), | |
554 | &mvif->wep_sta->wcid, cmd); | |
555 | ||
556 | out: | |
557 | mt792x_mutex_release(dev); | |
558 | ||
559 | return err; | |
560 | } | |
561 | ||
562 | static void | |
563 | mt7925_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) | |
564 | { | |
565 | struct mt792x_dev *dev = priv; | |
566 | struct ieee80211_hw *hw = mt76_hw(dev); | |
567 | bool pm_enable = dev->pm.enable; | |
568 | int err; | |
569 | ||
570 | err = mt7925_mcu_set_beacon_filter(dev, vif, pm_enable); | |
571 | if (err < 0) | |
572 | return; | |
573 | ||
574 | if (pm_enable) { | |
575 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; | |
576 | ieee80211_hw_set(hw, CONNECTION_MONITOR); | |
577 | } else { | |
578 | vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; | |
579 | __clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags); | |
580 | } | |
581 | } | |
582 | ||
583 | static void | |
584 | mt7925_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) | |
585 | { | |
586 | struct mt792x_dev *dev = priv; | |
587 | struct ieee80211_hw *hw = mt76_hw(dev); | |
588 | struct mt76_connac_pm *pm = &dev->pm; | |
589 | bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); | |
590 | ||
591 | mt7925_mcu_set_sniffer(dev, vif, monitor); | |
592 | pm->enable = pm->enable_user && !monitor; | |
593 | pm->ds_enable = pm->ds_enable_user && !monitor; | |
594 | ||
595 | mt7925_mcu_set_deep_sleep(dev, pm->ds_enable); | |
596 | ||
597 | if (monitor) | |
598 | mt7925_mcu_set_beacon_filter(dev, vif, false); | |
599 | } | |
600 | ||
601 | void mt7925_set_runtime_pm(struct mt792x_dev *dev) | |
602 | { | |
603 | struct ieee80211_hw *hw = mt76_hw(dev); | |
604 | struct mt76_connac_pm *pm = &dev->pm; | |
605 | bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); | |
606 | ||
607 | pm->enable = pm->enable_user && !monitor; | |
608 | ieee80211_iterate_active_interfaces(hw, | |
609 | IEEE80211_IFACE_ITER_RESUME_ALL, | |
610 | mt7925_pm_interface_iter, dev); | |
611 | pm->ds_enable = pm->ds_enable_user && !monitor; | |
612 | mt7925_mcu_set_deep_sleep(dev, pm->ds_enable); | |
613 | } | |
614 | ||
615 | static int mt7925_config(struct ieee80211_hw *hw, u32 changed) | |
616 | { | |
617 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
618 | int ret = 0; | |
619 | ||
620 | mt792x_mutex_acquire(dev); | |
621 | ||
622 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | |
623 | ret = mt7925_set_tx_sar_pwr(hw, NULL); | |
624 | if (ret) | |
625 | goto out; | |
626 | } | |
627 | ||
628 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | |
629 | ieee80211_iterate_active_interfaces(hw, | |
630 | IEEE80211_IFACE_ITER_RESUME_ALL, | |
631 | mt7925_sniffer_interface_iter, dev); | |
632 | } | |
633 | ||
634 | out: | |
635 | mt792x_mutex_release(dev); | |
636 | ||
637 | return ret; | |
638 | } | |
639 | ||
640 | static void mt7925_configure_filter(struct ieee80211_hw *hw, | |
641 | unsigned int changed_flags, | |
642 | unsigned int *total_flags, | |
643 | u64 multicast) | |
644 | { | |
645 | #define MT7925_FILTER_FCSFAIL BIT(2) | |
646 | #define MT7925_FILTER_CONTROL BIT(5) | |
647 | #define MT7925_FILTER_OTHER_BSS BIT(6) | |
648 | #define MT7925_FILTER_ENABLE BIT(31) | |
649 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
650 | u32 flags = MT7925_FILTER_ENABLE; | |
651 | ||
652 | #define MT7925_FILTER(_fif, _type) do { \ | |
653 | if (*total_flags & (_fif)) \ | |
654 | flags |= MT7925_FILTER_##_type; \ | |
655 | } while (0) | |
656 | ||
657 | MT7925_FILTER(FIF_FCSFAIL, FCSFAIL); | |
658 | MT7925_FILTER(FIF_CONTROL, CONTROL); | |
659 | MT7925_FILTER(FIF_OTHER_BSS, OTHER_BSS); | |
660 | ||
661 | mt792x_mutex_acquire(dev); | |
662 | mt7925_mcu_set_rxfilter(dev, flags, 0, 0); | |
663 | mt792x_mutex_release(dev); | |
664 | ||
665 | *total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL); | |
666 | } | |
667 | ||
668 | static u8 | |
669 | mt7925_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |
670 | bool beacon, bool mcast) | |
671 | { | |
672 | struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; | |
673 | struct mt76_phy *mphy = hw->priv; | |
674 | u16 rate; | |
675 | u8 i, idx, ht; | |
676 | ||
677 | rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast); | |
678 | ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM; | |
679 | ||
680 | if (beacon && ht) { | |
681 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
682 | ||
683 | /* must odd index */ | |
684 | idx = MT7925_BEACON_RATES_TBL + 2 * (mvif->idx % 20); | |
685 | mt7925_mac_set_fixed_rate_table(dev, idx, rate); | |
686 | return idx; | |
687 | } | |
688 | ||
689 | idx = FIELD_GET(MT_TX_RATE_IDX, rate); | |
690 | for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) | |
691 | if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx) | |
692 | return MT792x_BASIC_RATES_TBL + i; | |
693 | ||
694 | return mvif->basic_rates_idx; | |
695 | } | |
696 | ||
697 | static void mt7925_bss_info_changed(struct ieee80211_hw *hw, | |
698 | struct ieee80211_vif *vif, | |
699 | struct ieee80211_bss_conf *info, | |
700 | u64 changed) | |
701 | { | |
702 | struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; | |
703 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
704 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
705 | ||
706 | mt792x_mutex_acquire(dev); | |
707 | ||
708 | if (changed & BSS_CHANGED_ERP_SLOT) { | |
709 | int slottime = info->use_short_slot ? 9 : 20; | |
710 | ||
711 | if (slottime != phy->slottime) { | |
712 | phy->slottime = slottime; | |
713 | mt792x_mac_set_timeing(phy); | |
714 | } | |
715 | } | |
716 | ||
717 | if (changed & BSS_CHANGED_MCAST_RATE) | |
718 | mvif->mcast_rates_idx = | |
719 | mt7925_get_rates_table(hw, vif, false, true); | |
720 | ||
721 | if (changed & BSS_CHANGED_BASIC_RATES) | |
722 | mvif->basic_rates_idx = | |
723 | mt7925_get_rates_table(hw, vif, false, false); | |
724 | ||
725 | if (changed & (BSS_CHANGED_BEACON | | |
726 | BSS_CHANGED_BEACON_ENABLED)) { | |
727 | mvif->beacon_rates_idx = | |
728 | mt7925_get_rates_table(hw, vif, true, false); | |
729 | ||
730 | mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, | |
731 | info->enable_beacon); | |
732 | } | |
733 | ||
734 | /* ensure that enable txcmd_mode after bss_info */ | |
735 | if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) | |
736 | mt7925_mcu_set_tx(dev, vif); | |
737 | ||
738 | if (changed & BSS_CHANGED_PS) | |
739 | mt7925_mcu_uni_bss_ps(dev, vif); | |
740 | ||
741 | if (changed & BSS_CHANGED_ASSOC) { | |
742 | mt7925_mcu_sta_update(dev, NULL, vif, true, | |
743 | MT76_STA_INFO_STATE_ASSOC); | |
744 | mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc); | |
745 | } | |
746 | ||
747 | if (changed & BSS_CHANGED_ARP_FILTER) { | |
748 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
749 | ||
750 | mt7925_mcu_update_arp_filter(&dev->mt76, &mvif->mt76, info); | |
751 | } | |
752 | ||
753 | mt792x_mutex_release(dev); | |
754 | } | |
755 | ||
756 | int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, | |
757 | struct ieee80211_sta *sta) | |
758 | { | |
759 | struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); | |
760 | struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; | |
761 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
762 | int ret, idx; | |
763 | ||
764 | idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); | |
765 | if (idx < 0) | |
766 | return -ENOSPC; | |
767 | ||
768 | INIT_LIST_HEAD(&msta->wcid.poll_list); | |
769 | msta->vif = mvif; | |
770 | msta->wcid.sta = 1; | |
771 | msta->wcid.idx = idx; | |
772 | msta->wcid.phy_idx = mvif->mt76.band_idx; | |
773 | msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; | |
774 | msta->last_txs = jiffies; | |
775 | ||
776 | ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm); | |
777 | if (ret) | |
778 | return ret; | |
779 | ||
780 | if (vif->type == NL80211_IFTYPE_STATION) | |
781 | mvif->wep_sta = msta; | |
782 | ||
783 | mt7925_mac_wtbl_update(dev, idx, | |
784 | MT_WTBL_UPDATE_ADM_COUNT_CLEAR); | |
785 | ||
786 | /* should update bss info before STA add */ | |
787 | if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) | |
788 | mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, sta, | |
789 | false); | |
790 | ||
791 | ret = mt7925_mcu_sta_update(dev, sta, vif, true, | |
792 | MT76_STA_INFO_STATE_NONE); | |
793 | if (ret) | |
794 | return ret; | |
795 | ||
796 | mt76_connac_power_save_sched(&dev->mphy, &dev->pm); | |
797 | ||
798 | return 0; | |
799 | } | |
800 | EXPORT_SYMBOL_GPL(mt7925_mac_sta_add); | |
801 | ||
802 | void mt7925_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, | |
803 | struct ieee80211_sta *sta) | |
804 | { | |
805 | struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); | |
806 | struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; | |
807 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
808 | ||
809 | mt792x_mutex_acquire(dev); | |
810 | ||
811 | if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) | |
812 | mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, sta, | |
813 | true); | |
814 | ||
815 | ewma_avg_signal_init(&msta->avg_ack_signal); | |
816 | ||
817 | mt7925_mac_wtbl_update(dev, msta->wcid.idx, | |
818 | MT_WTBL_UPDATE_ADM_COUNT_CLEAR); | |
819 | memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); | |
820 | ||
821 | mt7925_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC); | |
822 | ||
823 | mt792x_mutex_release(dev); | |
824 | } | |
825 | EXPORT_SYMBOL_GPL(mt7925_mac_sta_assoc); | |
826 | ||
827 | void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, | |
828 | struct ieee80211_sta *sta) | |
829 | { | |
830 | struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); | |
831 | struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; | |
832 | ||
833 | mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); | |
834 | mt76_connac_pm_wake(&dev->mphy, &dev->pm); | |
835 | ||
836 | mt7925_mcu_sta_update(dev, sta, vif, false, MT76_STA_INFO_STATE_NONE); | |
837 | mt7925_mac_wtbl_update(dev, msta->wcid.idx, | |
838 | MT_WTBL_UPDATE_ADM_COUNT_CLEAR); | |
839 | ||
840 | if (vif->type == NL80211_IFTYPE_STATION) { | |
841 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
842 | ||
843 | mvif->wep_sta = NULL; | |
844 | ewma_rssi_init(&mvif->rssi); | |
845 | if (!sta->tdls) | |
846 | mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, sta, | |
847 | false); | |
848 | } | |
849 | ||
850 | spin_lock_bh(&mdev->sta_poll_lock); | |
851 | if (!list_empty(&msta->wcid.poll_list)) | |
852 | list_del_init(&msta->wcid.poll_list); | |
853 | spin_unlock_bh(&mdev->sta_poll_lock); | |
854 | ||
855 | mt76_connac_power_save_sched(&dev->mphy, &dev->pm); | |
856 | } | |
857 | EXPORT_SYMBOL_GPL(mt7925_mac_sta_remove); | |
858 | ||
859 | static int mt7925_set_rts_threshold(struct ieee80211_hw *hw, u32 val) | |
860 | { | |
861 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
862 | ||
863 | mt792x_mutex_acquire(dev); | |
864 | mt7925_mcu_set_rts_thresh(&dev->phy, val); | |
865 | mt792x_mutex_release(dev); | |
866 | ||
867 | return 0; | |
868 | } | |
869 | ||
870 | static int | |
871 | mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |
872 | struct ieee80211_ampdu_params *params) | |
873 | { | |
874 | enum ieee80211_ampdu_mlme_action action = params->action; | |
875 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
876 | struct ieee80211_sta *sta = params->sta; | |
877 | struct ieee80211_txq *txq = sta->txq[params->tid]; | |
878 | struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; | |
879 | u16 tid = params->tid; | |
880 | u16 ssn = params->ssn; | |
881 | struct mt76_txq *mtxq; | |
882 | int ret = 0; | |
883 | ||
884 | if (!txq) | |
885 | return -EINVAL; | |
886 | ||
887 | mtxq = (struct mt76_txq *)txq->drv_priv; | |
888 | ||
889 | mt792x_mutex_acquire(dev); | |
890 | switch (action) { | |
891 | case IEEE80211_AMPDU_RX_START: | |
892 | mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, | |
893 | params->buf_size); | |
894 | mt7925_mcu_uni_rx_ba(dev, params, true); | |
895 | break; | |
896 | case IEEE80211_AMPDU_RX_STOP: | |
897 | mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); | |
898 | mt7925_mcu_uni_rx_ba(dev, params, false); | |
899 | break; | |
900 | case IEEE80211_AMPDU_TX_OPERATIONAL: | |
901 | mtxq->aggr = true; | |
902 | mtxq->send_bar = false; | |
903 | mt7925_mcu_uni_tx_ba(dev, params, true); | |
904 | break; | |
905 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | |
906 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | |
907 | mtxq->aggr = false; | |
908 | clear_bit(tid, &msta->wcid.ampdu_state); | |
909 | mt7925_mcu_uni_tx_ba(dev, params, false); | |
910 | break; | |
911 | case IEEE80211_AMPDU_TX_START: | |
912 | set_bit(tid, &msta->wcid.ampdu_state); | |
913 | ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; | |
914 | break; | |
915 | case IEEE80211_AMPDU_TX_STOP_CONT: | |
916 | mtxq->aggr = false; | |
917 | clear_bit(tid, &msta->wcid.ampdu_state); | |
918 | mt7925_mcu_uni_tx_ba(dev, params, false); | |
919 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | |
920 | break; | |
921 | } | |
922 | mt792x_mutex_release(dev); | |
923 | ||
924 | return ret; | |
925 | } | |
926 | ||
927 | static bool is_valid_alpha2(const char *alpha2) | |
928 | { | |
929 | if (!alpha2) | |
930 | return false; | |
931 | ||
932 | if (alpha2[0] == '0' && alpha2[1] == '0') | |
933 | return true; | |
934 | ||
935 | if (isalpha(alpha2[0]) && isalpha(alpha2[1])) | |
936 | return true; | |
937 | ||
938 | return false; | |
939 | } | |
940 | ||
941 | void mt7925_scan_work(struct work_struct *work) | |
942 | { | |
943 | struct mt792x_phy *phy; | |
944 | ||
945 | phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy, | |
946 | scan_work.work); | |
947 | ||
948 | while (true) { | |
949 | struct mt76_dev *mdev = &phy->dev->mt76; | |
950 | struct sk_buff *skb; | |
951 | struct tlv *tlv; | |
952 | int tlv_len; | |
953 | ||
954 | spin_lock_bh(&phy->dev->mt76.lock); | |
955 | skb = __skb_dequeue(&phy->scan_event_list); | |
956 | spin_unlock_bh(&phy->dev->mt76.lock); | |
957 | ||
958 | if (!skb) | |
959 | break; | |
960 | ||
961 | skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4); | |
962 | tlv = (struct tlv *)skb->data; | |
963 | tlv_len = skb->len; | |
964 | ||
965 | while (tlv_len > 0 && le16_to_cpu(tlv->len) <= tlv_len) { | |
966 | struct mt7925_mcu_scan_chinfo_event *evt; | |
967 | ||
968 | switch (le16_to_cpu(tlv->tag)) { | |
969 | case UNI_EVENT_SCAN_DONE_BASIC: | |
970 | if (test_and_clear_bit(MT76_HW_SCANNING, &phy->mt76->state)) { | |
971 | struct cfg80211_scan_info info = { | |
972 | .aborted = false, | |
973 | }; | |
974 | ieee80211_scan_completed(phy->mt76->hw, &info); | |
975 | } | |
976 | break; | |
977 | case UNI_EVENT_SCAN_DONE_CHNLINFO: | |
978 | evt = (struct mt7925_mcu_scan_chinfo_event *)tlv->data; | |
979 | ||
980 | if (!is_valid_alpha2(evt->alpha2)) | |
981 | break; | |
982 | ||
983 | if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0') | |
984 | break; | |
985 | ||
986 | mt7925_mcu_set_clc(phy->dev, evt->alpha2, ENVIRON_INDOOR); | |
987 | ||
988 | break; | |
989 | case UNI_EVENT_SCAN_DONE_NLO: | |
990 | ieee80211_sched_scan_results(phy->mt76->hw); | |
991 | break; | |
992 | default: | |
993 | break; | |
994 | } | |
995 | ||
996 | tlv_len -= le16_to_cpu(tlv->len); | |
997 | tlv = (struct tlv *)((char *)(tlv) + le16_to_cpu(tlv->len)); | |
998 | } | |
999 | ||
1000 | dev_kfree_skb(skb); | |
1001 | } | |
1002 | } | |
1003 | ||
1004 | static int | |
1005 | mt7925_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |
1006 | struct ieee80211_scan_request *req) | |
1007 | { | |
1008 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1009 | struct mt76_phy *mphy = hw->priv; | |
1010 | int err; | |
1011 | ||
1012 | mt792x_mutex_acquire(dev); | |
1013 | err = mt7925_mcu_hw_scan(mphy, vif, req); | |
1014 | mt792x_mutex_release(dev); | |
1015 | ||
1016 | return err; | |
1017 | } | |
1018 | ||
1019 | static void | |
1020 | mt7925_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |
1021 | { | |
1022 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1023 | struct mt76_phy *mphy = hw->priv; | |
1024 | ||
1025 | mt792x_mutex_acquire(dev); | |
1026 | mt7925_mcu_cancel_hw_scan(mphy, vif); | |
1027 | mt792x_mutex_release(dev); | |
1028 | } | |
1029 | ||
1030 | static int | |
1031 | mt7925_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |
1032 | struct cfg80211_sched_scan_request *req, | |
1033 | struct ieee80211_scan_ies *ies) | |
1034 | { | |
1035 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1036 | struct mt76_phy *mphy = hw->priv; | |
1037 | int err; | |
1038 | ||
1039 | mt792x_mutex_acquire(dev); | |
1040 | ||
1041 | err = mt7925_mcu_sched_scan_req(mphy, vif, req); | |
1042 | if (err < 0) | |
1043 | goto out; | |
1044 | ||
1045 | err = mt7925_mcu_sched_scan_enable(mphy, vif, true); | |
1046 | out: | |
1047 | mt792x_mutex_release(dev); | |
1048 | ||
1049 | return err; | |
1050 | } | |
1051 | ||
1052 | static int | |
1053 | mt7925_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |
1054 | { | |
1055 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1056 | struct mt76_phy *mphy = hw->priv; | |
1057 | int err; | |
1058 | ||
1059 | mt792x_mutex_acquire(dev); | |
1060 | err = mt7925_mcu_sched_scan_enable(mphy, vif, false); | |
1061 | mt792x_mutex_release(dev); | |
1062 | ||
1063 | return err; | |
1064 | } | |
1065 | ||
1066 | static int | |
1067 | mt7925_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) | |
1068 | { | |
1069 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1070 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
1071 | int max_nss = hweight8(hw->wiphy->available_antennas_tx); | |
1072 | ||
1073 | if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) | |
1074 | return -EINVAL; | |
1075 | ||
1076 | if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) | |
1077 | tx_ant = BIT(ffs(tx_ant) - 1) - 1; | |
1078 | ||
1079 | mt792x_mutex_acquire(dev); | |
1080 | ||
1081 | phy->mt76->antenna_mask = tx_ant; | |
1082 | phy->mt76->chainmask = tx_ant; | |
1083 | ||
1084 | mt76_set_stream_caps(phy->mt76, true); | |
1085 | mt7925_set_stream_he_eht_caps(phy); | |
1086 | ||
1087 | /* TODO: update bmc_wtbl spe_idx when antenna changes */ | |
1088 | mt792x_mutex_release(dev); | |
1089 | ||
1090 | return 0; | |
1091 | } | |
1092 | ||
1093 | #ifdef CONFIG_PM | |
1094 | static int mt7925_suspend(struct ieee80211_hw *hw, | |
1095 | struct cfg80211_wowlan *wowlan) | |
1096 | { | |
1097 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1098 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
1099 | ||
1100 | cancel_delayed_work_sync(&phy->scan_work); | |
1101 | cancel_delayed_work_sync(&phy->mt76->mac_work); | |
1102 | ||
1103 | cancel_delayed_work_sync(&dev->pm.ps_work); | |
1104 | mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); | |
1105 | ||
1106 | mt792x_mutex_acquire(dev); | |
1107 | ||
1108 | clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); | |
1109 | ieee80211_iterate_active_interfaces(hw, | |
1110 | IEEE80211_IFACE_ITER_RESUME_ALL, | |
1111 | mt7925_mcu_set_suspend_iter, | |
1112 | &dev->mphy); | |
1113 | ||
1114 | mt792x_mutex_release(dev); | |
1115 | ||
1116 | return 0; | |
1117 | } | |
1118 | ||
1119 | static int mt7925_resume(struct ieee80211_hw *hw) | |
1120 | { | |
1121 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1122 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
1123 | ||
1124 | mt792x_mutex_acquire(dev); | |
1125 | ||
1126 | set_bit(MT76_STATE_RUNNING, &phy->mt76->state); | |
1127 | ieee80211_iterate_active_interfaces(hw, | |
1128 | IEEE80211_IFACE_ITER_RESUME_ALL, | |
1129 | mt7925_mcu_set_suspend_iter, | |
1130 | &dev->mphy); | |
1131 | ||
1132 | ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, | |
1133 | MT792x_WATCHDOG_TIME); | |
1134 | ||
1135 | mt792x_mutex_release(dev); | |
1136 | ||
1137 | return 0; | |
1138 | } | |
1139 | ||
1140 | static void mt7925_set_rekey_data(struct ieee80211_hw *hw, | |
1141 | struct ieee80211_vif *vif, | |
1142 | struct cfg80211_gtk_rekey_data *data) | |
1143 | { | |
1144 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1145 | ||
1146 | mt792x_mutex_acquire(dev); | |
1147 | mt76_connac_mcu_update_gtk_rekey(hw, vif, data); | |
1148 | mt792x_mutex_release(dev); | |
1149 | } | |
1150 | #endif /* CONFIG_PM */ | |
1151 | ||
1152 | static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, | |
1153 | struct ieee80211_vif *vif, | |
1154 | struct ieee80211_sta *sta, | |
1155 | bool enabled) | |
1156 | { | |
1157 | struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; | |
1158 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1159 | ||
1160 | mt792x_mutex_acquire(dev); | |
1161 | ||
1162 | if (enabled) | |
1163 | set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); | |
1164 | else | |
1165 | clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); | |
1166 | ||
1167 | mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta); | |
1168 | ||
1169 | mt792x_mutex_release(dev); | |
1170 | } | |
1171 | ||
1172 | #if IS_ENABLED(CONFIG_IPV6) | |
1173 | static void mt7925_ipv6_addr_change(struct ieee80211_hw *hw, | |
1174 | struct ieee80211_vif *vif, | |
1175 | struct inet6_dev *idev) | |
1176 | { | |
1177 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
1178 | struct mt792x_dev *dev = mvif->phy->dev; | |
1179 | struct inet6_ifaddr *ifa; | |
1180 | struct sk_buff *skb; | |
1181 | u8 idx = 0; | |
1182 | ||
1183 | struct { | |
1184 | struct { | |
1185 | u8 bss_idx; | |
1186 | u8 pad[3]; | |
1187 | } __packed hdr; | |
1188 | struct mt7925_arpns_tlv arpns; | |
1189 | struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; | |
1190 | } req_hdr = { | |
1191 | .hdr = { | |
1192 | .bss_idx = mvif->mt76.idx, | |
1193 | }, | |
1194 | .arpns = { | |
1195 | .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND), | |
1196 | .len = cpu_to_le16(sizeof(req_hdr) - 4), | |
1197 | .enable = true, | |
1198 | }, | |
1199 | }; | |
1200 | ||
1201 | read_lock_bh(&idev->lock); | |
1202 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | |
1203 | if (ifa->flags & IFA_F_TENTATIVE) | |
1204 | continue; | |
1205 | req_hdr.ns_addrs[idx] = ifa->addr; | |
1206 | if (++idx >= IEEE80211_BSS_ARP_ADDR_LIST_LEN) | |
1207 | break; | |
1208 | } | |
1209 | read_unlock_bh(&idev->lock); | |
1210 | ||
1211 | if (!idx) | |
1212 | return; | |
1213 | ||
1214 | req_hdr.arpns.ips_num = idx; | |
1215 | ||
1216 | skb = __mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr), | |
1217 | 0, GFP_ATOMIC); | |
1218 | if (!skb) | |
1219 | return; | |
1220 | ||
1221 | skb_put_data(skb, &req_hdr, sizeof(req_hdr)); | |
1222 | ||
1223 | skb_queue_tail(&dev->ipv6_ns_list, skb); | |
1224 | ||
1225 | ieee80211_queue_work(dev->mt76.hw, &dev->ipv6_ns_work); | |
1226 | } | |
1227 | #endif | |
1228 | ||
1229 | int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw, | |
1230 | const struct cfg80211_sar_specs *sar) | |
1231 | { | |
1232 | struct mt76_phy *mphy = hw->priv; | |
1233 | ||
1234 | if (sar) { | |
1235 | int err = mt76_init_sar_power(hw, sar); | |
1236 | ||
1237 | if (err) | |
1238 | return err; | |
1239 | } | |
1240 | mt792x_init_acpi_sar_power(mt792x_hw_phy(hw), !sar); | |
1241 | ||
1242 | return mt7925_mcu_set_rate_txpower(mphy); | |
1243 | } | |
1244 | ||
1245 | static int mt7925_set_sar_specs(struct ieee80211_hw *hw, | |
1246 | const struct cfg80211_sar_specs *sar) | |
1247 | { | |
1248 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1249 | int err; | |
1250 | ||
1251 | mt792x_mutex_acquire(dev); | |
1252 | err = mt7925_mcu_set_clc(dev, dev->mt76.alpha2, | |
1253 | dev->country_ie_env); | |
1254 | if (err < 0) | |
1255 | goto out; | |
1256 | ||
1257 | err = mt7925_set_tx_sar_pwr(hw, sar); | |
1258 | out: | |
1259 | mt792x_mutex_release(dev); | |
1260 | ||
1261 | return err; | |
1262 | } | |
1263 | ||
1264 | static void | |
1265 | mt7925_channel_switch_beacon(struct ieee80211_hw *hw, | |
1266 | struct ieee80211_vif *vif, | |
1267 | struct cfg80211_chan_def *chandef) | |
1268 | { | |
1269 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1270 | ||
1271 | mt792x_mutex_acquire(dev); | |
1272 | mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true); | |
1273 | mt792x_mutex_release(dev); | |
1274 | } | |
1275 | ||
1276 | static int | |
1277 | mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |
1278 | struct ieee80211_bss_conf *link_conf) | |
1279 | { | |
1280 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
1281 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1282 | int err; | |
1283 | ||
1284 | mt792x_mutex_acquire(dev); | |
1285 | ||
1286 | err = mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, NULL, | |
1287 | true); | |
1288 | if (err) | |
1289 | goto out; | |
1290 | ||
1291 | err = mt7925_mcu_set_bss_pm(dev, vif, true); | |
1292 | if (err) | |
1293 | goto out; | |
1294 | ||
1295 | err = mt7925_mcu_sta_update(dev, NULL, vif, true, | |
1296 | MT76_STA_INFO_STATE_NONE); | |
1297 | out: | |
1298 | mt792x_mutex_release(dev); | |
1299 | ||
1300 | return err; | |
1301 | } | |
1302 | ||
1303 | static void | |
1304 | mt7925_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |
1305 | struct ieee80211_bss_conf *link_conf) | |
1306 | { | |
1307 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
1308 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1309 | int err; | |
1310 | ||
1311 | mt792x_mutex_acquire(dev); | |
1312 | ||
1313 | err = mt7925_mcu_set_bss_pm(dev, vif, false); | |
1314 | if (err) | |
1315 | goto out; | |
1316 | ||
1317 | mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, NULL, | |
1318 | false); | |
1319 | ||
1320 | out: | |
1321 | mt792x_mutex_release(dev); | |
1322 | } | |
1323 | ||
1324 | static int | |
1325 | mt7925_add_chanctx(struct ieee80211_hw *hw, | |
1326 | struct ieee80211_chanctx_conf *ctx) | |
1327 | { | |
1328 | return 0; | |
1329 | } | |
1330 | ||
1331 | static void | |
1332 | mt7925_remove_chanctx(struct ieee80211_hw *hw, | |
1333 | struct ieee80211_chanctx_conf *ctx) | |
1334 | { | |
1335 | } | |
1336 | ||
1337 | static void mt7925_ctx_iter(void *priv, u8 *mac, | |
1338 | struct ieee80211_vif *vif) | |
1339 | { | |
1340 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
1341 | struct ieee80211_chanctx_conf *ctx = priv; | |
1342 | ||
1343 | if (ctx != mvif->mt76.ctx) | |
1344 | return; | |
1345 | ||
1346 | if (vif->type == NL80211_IFTYPE_MONITOR) { | |
1347 | mt7925_mcu_set_sniffer(mvif->phy->dev, vif, true); | |
1348 | mt7925_mcu_config_sniffer(mvif, ctx); | |
1349 | } else { | |
1350 | mt7925_mcu_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx); | |
1351 | } | |
1352 | } | |
1353 | ||
1354 | static void | |
1355 | mt7925_change_chanctx(struct ieee80211_hw *hw, | |
1356 | struct ieee80211_chanctx_conf *ctx, | |
1357 | u32 changed) | |
1358 | { | |
1359 | struct mt792x_phy *phy = mt792x_hw_phy(hw); | |
1360 | ||
1361 | mt792x_mutex_acquire(phy->dev); | |
1362 | ieee80211_iterate_active_interfaces(phy->mt76->hw, | |
1363 | IEEE80211_IFACE_ITER_ACTIVE, | |
1364 | mt7925_ctx_iter, ctx); | |
1365 | mt792x_mutex_release(phy->dev); | |
1366 | } | |
1367 | ||
1368 | static void mt7925_mgd_prepare_tx(struct ieee80211_hw *hw, | |
1369 | struct ieee80211_vif *vif, | |
1370 | struct ieee80211_prep_tx_info *info) | |
1371 | { | |
1372 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
1373 | struct mt792x_dev *dev = mt792x_hw_dev(hw); | |
1374 | u16 duration = info->duration ? info->duration : | |
1375 | jiffies_to_msecs(HZ); | |
1376 | ||
1377 | mt792x_mutex_acquire(dev); | |
1378 | mt7925_set_roc(mvif->phy, mvif, mvif->mt76.ctx->def.chan, duration, | |
1379 | MT7925_ROC_REQ_JOIN); | |
1380 | mt792x_mutex_release(dev); | |
1381 | } | |
1382 | ||
1383 | static void mt7925_mgd_complete_tx(struct ieee80211_hw *hw, | |
1384 | struct ieee80211_vif *vif, | |
1385 | struct ieee80211_prep_tx_info *info) | |
1386 | { | |
1387 | struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; | |
1388 | ||
1389 | mt7925_abort_roc(mvif->phy, mvif); | |
1390 | } | |
1391 | ||
1392 | const struct ieee80211_ops mt7925_ops = { | |
1393 | .tx = mt792x_tx, | |
1394 | .start = mt7925_start, | |
5ab7d466 | 1395 | .stop = mt792x_stop, |
c948b5da DW |
1396 | .add_interface = mt7925_add_interface, |
1397 | .remove_interface = mt792x_remove_interface, | |
1398 | .config = mt7925_config, | |
1399 | .conf_tx = mt792x_conf_tx, | |
1400 | .configure_filter = mt7925_configure_filter, | |
1401 | .bss_info_changed = mt7925_bss_info_changed, | |
1402 | .start_ap = mt7925_start_ap, | |
1403 | .stop_ap = mt7925_stop_ap, | |
1404 | .sta_state = mt76_sta_state, | |
1405 | .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, | |
1406 | .set_key = mt7925_set_key, | |
1407 | .sta_set_decap_offload = mt7925_sta_set_decap_offload, | |
1408 | #if IS_ENABLED(CONFIG_IPV6) | |
1409 | .ipv6_addr_change = mt7925_ipv6_addr_change, | |
1410 | #endif /* CONFIG_IPV6 */ | |
1411 | .ampdu_action = mt7925_ampdu_action, | |
1412 | .set_rts_threshold = mt7925_set_rts_threshold, | |
1413 | .wake_tx_queue = mt76_wake_tx_queue, | |
1414 | .release_buffered_frames = mt76_release_buffered_frames, | |
1415 | .channel_switch_beacon = mt7925_channel_switch_beacon, | |
1416 | .get_txpower = mt76_get_txpower, | |
1417 | .get_stats = mt792x_get_stats, | |
1418 | .get_et_sset_count = mt792x_get_et_sset_count, | |
1419 | .get_et_strings = mt792x_get_et_strings, | |
1420 | .get_et_stats = mt792x_get_et_stats, | |
1421 | .get_tsf = mt792x_get_tsf, | |
1422 | .set_tsf = mt792x_set_tsf, | |
1423 | .get_survey = mt76_get_survey, | |
1424 | .get_antenna = mt76_get_antenna, | |
1425 | .set_antenna = mt7925_set_antenna, | |
1426 | .set_coverage_class = mt792x_set_coverage_class, | |
1427 | .hw_scan = mt7925_hw_scan, | |
1428 | .cancel_hw_scan = mt7925_cancel_hw_scan, | |
1429 | .sta_statistics = mt792x_sta_statistics, | |
1430 | .sched_scan_start = mt7925_start_sched_scan, | |
1431 | .sched_scan_stop = mt7925_stop_sched_scan, | |
1432 | #ifdef CONFIG_PM | |
1433 | .suspend = mt7925_suspend, | |
1434 | .resume = mt7925_resume, | |
1435 | .set_wakeup = mt792x_set_wakeup, | |
1436 | .set_rekey_data = mt7925_set_rekey_data, | |
1437 | #endif /* CONFIG_PM */ | |
1438 | .flush = mt792x_flush, | |
1439 | .set_sar_specs = mt7925_set_sar_specs, | |
1440 | .remain_on_channel = mt7925_remain_on_channel, | |
1441 | .cancel_remain_on_channel = mt7925_cancel_remain_on_channel, | |
1442 | .add_chanctx = mt7925_add_chanctx, | |
1443 | .remove_chanctx = mt7925_remove_chanctx, | |
1444 | .change_chanctx = mt7925_change_chanctx, | |
1445 | .assign_vif_chanctx = mt792x_assign_vif_chanctx, | |
1446 | .unassign_vif_chanctx = mt792x_unassign_vif_chanctx, | |
1447 | .mgd_prepare_tx = mt7925_mgd_prepare_tx, | |
1448 | .mgd_complete_tx = mt7925_mgd_complete_tx, | |
1449 | }; | |
1450 | EXPORT_SYMBOL_GPL(mt7925_ops); | |
1451 | ||
1452 | MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>"); | |
f3f8f050 | 1453 | MODULE_DESCRIPTION("MediaTek MT7925 core driver"); |
c948b5da | 1454 | MODULE_LICENSE("Dual BSD/GPL"); |