Commit | Line | Data |
---|---|---|
e3ec7017 PKS |
1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
2 | /* Copyright(c) 2019-2020 Realtek Corporation | |
3 | */ | |
15fcb103 JK |
4 | #include <linux/ip.h> |
5 | #include <linux/udp.h> | |
e3ec7017 | 6 | |
2ab856cc | 7 | #include "cam.h" |
967439c7 | 8 | #include "chan.h" |
e3ec7017 PKS |
9 | #include "coex.h" |
10 | #include "core.h" | |
11 | #include "efuse.h" | |
12 | #include "fw.h" | |
13 | #include "mac.h" | |
14 | #include "phy.h" | |
15 | #include "ps.h" | |
16 | #include "reg.h" | |
17 | #include "sar.h" | |
18 | #include "ser.h" | |
19 | #include "txrx.h" | |
20 | #include "util.h" | |
21 | ||
22 | static bool rtw89_disable_ps_mode; | |
23 | module_param_named(disable_ps_mode, rtw89_disable_ps_mode, bool, 0644); | |
24 | MODULE_PARM_DESC(disable_ps_mode, "Set Y to disable low power mode"); | |
25 | ||
0237f65a ZZY |
26 | #define RTW89_DEF_CHAN(_freq, _hw_val, _flags, _band) \ |
27 | { .center_freq = _freq, .hw_value = _hw_val, .flags = _flags, .band = _band, } | |
28 | #define RTW89_DEF_CHAN_2G(_freq, _hw_val) \ | |
29 | RTW89_DEF_CHAN(_freq, _hw_val, 0, NL80211_BAND_2GHZ) | |
30 | #define RTW89_DEF_CHAN_5G(_freq, _hw_val) \ | |
31 | RTW89_DEF_CHAN(_freq, _hw_val, 0, NL80211_BAND_5GHZ) | |
32 | #define RTW89_DEF_CHAN_5G_NO_HT40MINUS(_freq, _hw_val) \ | |
33 | RTW89_DEF_CHAN(_freq, _hw_val, IEEE80211_CHAN_NO_HT40MINUS, NL80211_BAND_5GHZ) | |
34 | #define RTW89_DEF_CHAN_6G(_freq, _hw_val) \ | |
35 | RTW89_DEF_CHAN(_freq, _hw_val, 0, NL80211_BAND_6GHZ) | |
36 | ||
e3ec7017 | 37 | static struct ieee80211_channel rtw89_channels_2ghz[] = { |
0237f65a ZZY |
38 | RTW89_DEF_CHAN_2G(2412, 1), |
39 | RTW89_DEF_CHAN_2G(2417, 2), | |
40 | RTW89_DEF_CHAN_2G(2422, 3), | |
41 | RTW89_DEF_CHAN_2G(2427, 4), | |
42 | RTW89_DEF_CHAN_2G(2432, 5), | |
43 | RTW89_DEF_CHAN_2G(2437, 6), | |
44 | RTW89_DEF_CHAN_2G(2442, 7), | |
45 | RTW89_DEF_CHAN_2G(2447, 8), | |
46 | RTW89_DEF_CHAN_2G(2452, 9), | |
47 | RTW89_DEF_CHAN_2G(2457, 10), | |
48 | RTW89_DEF_CHAN_2G(2462, 11), | |
49 | RTW89_DEF_CHAN_2G(2467, 12), | |
50 | RTW89_DEF_CHAN_2G(2472, 13), | |
51 | RTW89_DEF_CHAN_2G(2484, 14), | |
e3ec7017 PKS |
52 | }; |
53 | ||
54 | static struct ieee80211_channel rtw89_channels_5ghz[] = { | |
0237f65a ZZY |
55 | RTW89_DEF_CHAN_5G(5180, 36), |
56 | RTW89_DEF_CHAN_5G(5200, 40), | |
57 | RTW89_DEF_CHAN_5G(5220, 44), | |
58 | RTW89_DEF_CHAN_5G(5240, 48), | |
59 | RTW89_DEF_CHAN_5G(5260, 52), | |
60 | RTW89_DEF_CHAN_5G(5280, 56), | |
61 | RTW89_DEF_CHAN_5G(5300, 60), | |
62 | RTW89_DEF_CHAN_5G(5320, 64), | |
63 | RTW89_DEF_CHAN_5G(5500, 100), | |
64 | RTW89_DEF_CHAN_5G(5520, 104), | |
65 | RTW89_DEF_CHAN_5G(5540, 108), | |
66 | RTW89_DEF_CHAN_5G(5560, 112), | |
67 | RTW89_DEF_CHAN_5G(5580, 116), | |
68 | RTW89_DEF_CHAN_5G(5600, 120), | |
69 | RTW89_DEF_CHAN_5G(5620, 124), | |
70 | RTW89_DEF_CHAN_5G(5640, 128), | |
71 | RTW89_DEF_CHAN_5G(5660, 132), | |
72 | RTW89_DEF_CHAN_5G(5680, 136), | |
73 | RTW89_DEF_CHAN_5G(5700, 140), | |
74 | RTW89_DEF_CHAN_5G(5720, 144), | |
75 | RTW89_DEF_CHAN_5G(5745, 149), | |
76 | RTW89_DEF_CHAN_5G(5765, 153), | |
77 | RTW89_DEF_CHAN_5G(5785, 157), | |
78 | RTW89_DEF_CHAN_5G(5805, 161), | |
79 | RTW89_DEF_CHAN_5G_NO_HT40MINUS(5825, 165), | |
80 | }; | |
81 | ||
82 | static struct ieee80211_channel rtw89_channels_6ghz[] = { | |
83 | RTW89_DEF_CHAN_6G(5955, 1), | |
84 | RTW89_DEF_CHAN_6G(5975, 5), | |
85 | RTW89_DEF_CHAN_6G(5995, 9), | |
86 | RTW89_DEF_CHAN_6G(6015, 13), | |
87 | RTW89_DEF_CHAN_6G(6035, 17), | |
88 | RTW89_DEF_CHAN_6G(6055, 21), | |
89 | RTW89_DEF_CHAN_6G(6075, 25), | |
90 | RTW89_DEF_CHAN_6G(6095, 29), | |
91 | RTW89_DEF_CHAN_6G(6115, 33), | |
92 | RTW89_DEF_CHAN_6G(6135, 37), | |
93 | RTW89_DEF_CHAN_6G(6155, 41), | |
94 | RTW89_DEF_CHAN_6G(6175, 45), | |
95 | RTW89_DEF_CHAN_6G(6195, 49), | |
96 | RTW89_DEF_CHAN_6G(6215, 53), | |
97 | RTW89_DEF_CHAN_6G(6235, 57), | |
98 | RTW89_DEF_CHAN_6G(6255, 61), | |
99 | RTW89_DEF_CHAN_6G(6275, 65), | |
100 | RTW89_DEF_CHAN_6G(6295, 69), | |
101 | RTW89_DEF_CHAN_6G(6315, 73), | |
102 | RTW89_DEF_CHAN_6G(6335, 77), | |
103 | RTW89_DEF_CHAN_6G(6355, 81), | |
104 | RTW89_DEF_CHAN_6G(6375, 85), | |
105 | RTW89_DEF_CHAN_6G(6395, 89), | |
106 | RTW89_DEF_CHAN_6G(6415, 93), | |
107 | RTW89_DEF_CHAN_6G(6435, 97), | |
108 | RTW89_DEF_CHAN_6G(6455, 101), | |
109 | RTW89_DEF_CHAN_6G(6475, 105), | |
110 | RTW89_DEF_CHAN_6G(6495, 109), | |
111 | RTW89_DEF_CHAN_6G(6515, 113), | |
112 | RTW89_DEF_CHAN_6G(6535, 117), | |
113 | RTW89_DEF_CHAN_6G(6555, 121), | |
114 | RTW89_DEF_CHAN_6G(6575, 125), | |
115 | RTW89_DEF_CHAN_6G(6595, 129), | |
116 | RTW89_DEF_CHAN_6G(6615, 133), | |
117 | RTW89_DEF_CHAN_6G(6635, 137), | |
118 | RTW89_DEF_CHAN_6G(6655, 141), | |
119 | RTW89_DEF_CHAN_6G(6675, 145), | |
120 | RTW89_DEF_CHAN_6G(6695, 149), | |
121 | RTW89_DEF_CHAN_6G(6715, 153), | |
122 | RTW89_DEF_CHAN_6G(6735, 157), | |
123 | RTW89_DEF_CHAN_6G(6755, 161), | |
124 | RTW89_DEF_CHAN_6G(6775, 165), | |
125 | RTW89_DEF_CHAN_6G(6795, 169), | |
126 | RTW89_DEF_CHAN_6G(6815, 173), | |
127 | RTW89_DEF_CHAN_6G(6835, 177), | |
128 | RTW89_DEF_CHAN_6G(6855, 181), | |
129 | RTW89_DEF_CHAN_6G(6875, 185), | |
130 | RTW89_DEF_CHAN_6G(6895, 189), | |
131 | RTW89_DEF_CHAN_6G(6915, 193), | |
132 | RTW89_DEF_CHAN_6G(6935, 197), | |
133 | RTW89_DEF_CHAN_6G(6955, 201), | |
134 | RTW89_DEF_CHAN_6G(6975, 205), | |
135 | RTW89_DEF_CHAN_6G(6995, 209), | |
136 | RTW89_DEF_CHAN_6G(7015, 213), | |
137 | RTW89_DEF_CHAN_6G(7035, 217), | |
138 | RTW89_DEF_CHAN_6G(7055, 221), | |
139 | RTW89_DEF_CHAN_6G(7075, 225), | |
140 | RTW89_DEF_CHAN_6G(7095, 229), | |
141 | RTW89_DEF_CHAN_6G(7115, 233), | |
e3ec7017 PKS |
142 | }; |
143 | ||
144 | static struct ieee80211_rate rtw89_bitrates[] = { | |
145 | { .bitrate = 10, .hw_value = 0x00, }, | |
146 | { .bitrate = 20, .hw_value = 0x01, }, | |
147 | { .bitrate = 55, .hw_value = 0x02, }, | |
148 | { .bitrate = 110, .hw_value = 0x03, }, | |
149 | { .bitrate = 60, .hw_value = 0x04, }, | |
150 | { .bitrate = 90, .hw_value = 0x05, }, | |
151 | { .bitrate = 120, .hw_value = 0x06, }, | |
152 | { .bitrate = 180, .hw_value = 0x07, }, | |
153 | { .bitrate = 240, .hw_value = 0x08, }, | |
154 | { .bitrate = 360, .hw_value = 0x09, }, | |
155 | { .bitrate = 480, .hw_value = 0x0a, }, | |
156 | { .bitrate = 540, .hw_value = 0x0b, }, | |
157 | }; | |
158 | ||
9a3a593c | 159 | bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate) |
e3ec7017 PKS |
160 | { |
161 | struct ieee80211_rate rate; | |
162 | ||
163 | if (unlikely(rpt_rate >= ARRAY_SIZE(rtw89_bitrates))) { | |
9a3a593c PKS |
164 | rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "invalid rpt rate %d\n", rpt_rate); |
165 | return false; | |
e3ec7017 PKS |
166 | } |
167 | ||
168 | rate = rtw89_bitrates[rpt_rate]; | |
9a3a593c | 169 | *bitrate = rate.bitrate; |
e3ec7017 | 170 | |
9a3a593c | 171 | return true; |
e3ec7017 PKS |
172 | } |
173 | ||
174 | static struct ieee80211_supported_band rtw89_sband_2ghz = { | |
175 | .band = NL80211_BAND_2GHZ, | |
176 | .channels = rtw89_channels_2ghz, | |
177 | .n_channels = ARRAY_SIZE(rtw89_channels_2ghz), | |
178 | .bitrates = rtw89_bitrates, | |
179 | .n_bitrates = ARRAY_SIZE(rtw89_bitrates), | |
180 | .ht_cap = {0}, | |
181 | .vht_cap = {0}, | |
182 | }; | |
183 | ||
184 | static struct ieee80211_supported_band rtw89_sband_5ghz = { | |
185 | .band = NL80211_BAND_5GHZ, | |
186 | .channels = rtw89_channels_5ghz, | |
187 | .n_channels = ARRAY_SIZE(rtw89_channels_5ghz), | |
188 | ||
189 | /* 5G has no CCK rates, 1M/2M/5.5M/11M */ | |
190 | .bitrates = rtw89_bitrates + 4, | |
191 | .n_bitrates = ARRAY_SIZE(rtw89_bitrates) - 4, | |
192 | .ht_cap = {0}, | |
193 | .vht_cap = {0}, | |
194 | }; | |
195 | ||
0237f65a ZZY |
196 | static struct ieee80211_supported_band rtw89_sband_6ghz = { |
197 | .band = NL80211_BAND_6GHZ, | |
198 | .channels = rtw89_channels_6ghz, | |
199 | .n_channels = ARRAY_SIZE(rtw89_channels_6ghz), | |
200 | ||
201 | /* 6G has no CCK rates, 1M/2M/5.5M/11M */ | |
202 | .bitrates = rtw89_bitrates + 4, | |
203 | .n_bitrates = ARRAY_SIZE(rtw89_bitrates) - 4, | |
204 | }; | |
205 | ||
e3ec7017 PKS |
206 | static void rtw89_traffic_stats_accu(struct rtw89_dev *rtwdev, |
207 | struct rtw89_traffic_stats *stats, | |
208 | struct sk_buff *skb, bool tx) | |
209 | { | |
210 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | |
211 | ||
212 | if (!ieee80211_is_data(hdr->frame_control)) | |
213 | return; | |
214 | ||
215 | if (is_broadcast_ether_addr(hdr->addr1) || | |
216 | is_multicast_ether_addr(hdr->addr1)) | |
217 | return; | |
218 | ||
219 | if (tx) { | |
220 | stats->tx_cnt++; | |
221 | stats->tx_unicast += skb->len; | |
222 | } else { | |
223 | stats->rx_cnt++; | |
224 | stats->rx_unicast += skb->len; | |
225 | } | |
226 | } | |
227 | ||
a88b6cc4 ZZY |
228 | void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef) |
229 | { | |
230 | cfg80211_chandef_create(chandef, &rtw89_channels_2ghz[0], | |
231 | NL80211_CHAN_NO_HT); | |
232 | } | |
233 | ||
494399b2 | 234 | static void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, |
3e5831ca | 235 | struct rtw89_chan *chan) |
e3ec7017 PKS |
236 | { |
237 | struct ieee80211_channel *channel = chandef->chan; | |
238 | enum nl80211_chan_width width = chandef->width; | |
e3ec7017 PKS |
239 | u32 primary_freq, center_freq; |
240 | u8 center_chan; | |
241 | u8 bandwidth = RTW89_CHANNEL_WIDTH_20; | |
e715f10f | 242 | u32 offset; |
0237f65a | 243 | u8 band; |
e3ec7017 PKS |
244 | |
245 | center_chan = channel->hw_value; | |
246 | primary_freq = channel->center_freq; | |
247 | center_freq = chandef->center_freq1; | |
248 | ||
e3ec7017 PKS |
249 | switch (width) { |
250 | case NL80211_CHAN_WIDTH_20_NOHT: | |
251 | case NL80211_CHAN_WIDTH_20: | |
252 | bandwidth = RTW89_CHANNEL_WIDTH_20; | |
e3ec7017 PKS |
253 | break; |
254 | case NL80211_CHAN_WIDTH_40: | |
255 | bandwidth = RTW89_CHANNEL_WIDTH_40; | |
256 | if (primary_freq > center_freq) { | |
e3ec7017 PKS |
257 | center_chan -= 2; |
258 | } else { | |
e3ec7017 PKS |
259 | center_chan += 2; |
260 | } | |
261 | break; | |
262 | case NL80211_CHAN_WIDTH_80: | |
e715f10f PKS |
263 | case NL80211_CHAN_WIDTH_160: |
264 | bandwidth = nl_to_rtw89_bandwidth(width); | |
e3ec7017 | 265 | if (primary_freq > center_freq) { |
e715f10f | 266 | offset = (primary_freq - center_freq - 10) / 20; |
e715f10f | 267 | center_chan -= 2 + offset * 4; |
e3ec7017 | 268 | } else { |
e715f10f | 269 | offset = (center_freq - primary_freq - 10) / 20; |
e715f10f | 270 | center_chan += 2 + offset * 4; |
e3ec7017 PKS |
271 | } |
272 | break; | |
273 | default: | |
274 | center_chan = 0; | |
275 | break; | |
276 | } | |
277 | ||
0237f65a ZZY |
278 | switch (channel->band) { |
279 | default: | |
280 | case NL80211_BAND_2GHZ: | |
281 | band = RTW89_BAND_2G; | |
282 | break; | |
283 | case NL80211_BAND_5GHZ: | |
284 | band = RTW89_BAND_5G; | |
285 | break; | |
286 | case NL80211_BAND_6GHZ: | |
287 | band = RTW89_BAND_6G; | |
288 | break; | |
289 | } | |
290 | ||
bb8152b3 | 291 | rtw89_chan_create(chan, center_chan, channel->hw_value, band, bandwidth); |
e3ec7017 PKS |
292 | } |
293 | ||
967439c7 ZZY |
294 | void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) |
295 | { | |
296 | const struct rtw89_chip_info *chip = rtwdev->chip; | |
07ef5f2f | 297 | const struct rtw89_chan *chan; |
7cf674ff ZZY |
298 | enum rtw89_sub_entity_idx sub_entity_idx; |
299 | enum rtw89_phy_idx phy_idx; | |
300 | enum rtw89_entity_mode mode; | |
967439c7 ZZY |
301 | bool entity_active; |
302 | ||
303 | entity_active = rtw89_get_entity_state(rtwdev); | |
304 | if (!entity_active) | |
305 | return; | |
306 | ||
7cf674ff ZZY |
307 | mode = rtw89_get_entity_mode(rtwdev); |
308 | if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode)) | |
309 | return; | |
310 | ||
311 | sub_entity_idx = RTW89_SUB_ENTITY_0; | |
312 | phy_idx = RTW89_PHY_0; | |
313 | chan = rtw89_chan_get(rtwdev, sub_entity_idx); | |
967439c7 | 314 | if (chip->ops->set_txpwr) |
7cf674ff | 315 | chip->ops->set_txpwr(rtwdev, chan, phy_idx); |
967439c7 ZZY |
316 | } |
317 | ||
e3ec7017 PKS |
318 | void rtw89_set_channel(struct rtw89_dev *rtwdev) |
319 | { | |
e3ec7017 | 320 | const struct rtw89_chip_info *chip = rtwdev->chip; |
7cf674ff ZZY |
321 | const struct cfg80211_chan_def *chandef; |
322 | enum rtw89_sub_entity_idx sub_entity_idx; | |
323 | enum rtw89_mac_idx mac_idx; | |
324 | enum rtw89_phy_idx phy_idx; | |
3e5831ca | 325 | struct rtw89_chan chan; |
e3ec7017 | 326 | struct rtw89_channel_help_params bak; |
7cf674ff | 327 | enum rtw89_entity_mode mode; |
e3ec7017 | 328 | bool band_changed; |
967439c7 ZZY |
329 | bool entity_active; |
330 | ||
331 | entity_active = rtw89_get_entity_state(rtwdev); | |
e3ec7017 | 332 | |
7cf674ff ZZY |
333 | mode = rtw89_entity_recalc(rtwdev); |
334 | if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode)) | |
335 | return; | |
336 | ||
337 | sub_entity_idx = RTW89_SUB_ENTITY_0; | |
338 | mac_idx = RTW89_MAC_0; | |
339 | phy_idx = RTW89_PHY_0; | |
340 | chandef = rtw89_chandef_get(rtwdev, sub_entity_idx); | |
494399b2 | 341 | rtw89_get_channel_params(chandef, &chan); |
3e5831ca | 342 | if (WARN(chan.channel == 0, "Invalid channel\n")) |
e3ec7017 PKS |
343 | return; |
344 | ||
7cf674ff | 345 | band_changed = rtw89_assign_entity_chan(rtwdev, sub_entity_idx, &chan); |
e3ec7017 | 346 | |
7cf674ff | 347 | rtw89_chip_set_channel_prepare(rtwdev, &bak, &chan, mac_idx, phy_idx); |
e3ec7017 | 348 | |
7cf674ff | 349 | chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx); |
e3ec7017 | 350 | |
967439c7 | 351 | rtw89_core_set_chip_txpwr(rtwdev); |
e3ec7017 | 352 | |
7cf674ff | 353 | rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx); |
e3ec7017 | 354 | |
967439c7 | 355 | if (!entity_active || band_changed) { |
7cf674ff ZZY |
356 | rtw89_btc_ntfy_switch_band(rtwdev, phy_idx, chan.band_type); |
357 | rtw89_chip_rfk_band_changed(rtwdev, phy_idx); | |
e3ec7017 | 358 | } |
7cf674ff ZZY |
359 | |
360 | rtw89_set_entity_state(rtwdev, true); | |
e3ec7017 PKS |
361 | } |
362 | ||
363 | static enum rtw89_core_tx_type | |
364 | rtw89_core_get_tx_type(struct rtw89_dev *rtwdev, | |
365 | struct sk_buff *skb) | |
366 | { | |
367 | struct ieee80211_hdr *hdr = (void *)skb->data; | |
368 | __le16 fc = hdr->frame_control; | |
369 | ||
370 | if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc)) | |
371 | return RTW89_CORE_TX_TYPE_MGMT; | |
372 | ||
373 | return RTW89_CORE_TX_TYPE_DATA; | |
374 | } | |
375 | ||
376 | static void | |
377 | rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, | |
679955d5 KCC |
378 | struct rtw89_core_tx_request *tx_req, |
379 | enum btc_pkt_type pkt_type) | |
e3ec7017 PKS |
380 | { |
381 | struct ieee80211_sta *sta = tx_req->sta; | |
382 | struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; | |
679955d5 | 383 | struct sk_buff *skb = tx_req->skb; |
e3ec7017 PKS |
384 | struct rtw89_sta *rtwsta; |
385 | u8 ampdu_num; | |
679955d5 KCC |
386 | u8 tid; |
387 | ||
388 | if (pkt_type == PACKET_EAPOL) { | |
389 | desc_info->bk = true; | |
390 | return; | |
391 | } | |
392 | ||
393 | if (!(IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU)) | |
394 | return; | |
e3ec7017 PKS |
395 | |
396 | if (!sta) { | |
397 | rtw89_warn(rtwdev, "cannot set ampdu info without sta\n"); | |
398 | return; | |
399 | } | |
400 | ||
679955d5 | 401 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
e3ec7017 PKS |
402 | rtwsta = (struct rtw89_sta *)sta->drv_priv; |
403 | ||
404 | ampdu_num = (u8)((rtwsta->ampdu_params[tid].agg_num ? | |
405 | rtwsta->ampdu_params[tid].agg_num : | |
046d2e7c | 406 | 4 << sta->deflink.ht_cap.ampdu_factor) - 1); |
e3ec7017 PKS |
407 | |
408 | desc_info->agg_en = true; | |
046d2e7c | 409 | desc_info->ampdu_density = sta->deflink.ht_cap.ampdu_density; |
e3ec7017 PKS |
410 | desc_info->ampdu_num = ampdu_num; |
411 | } | |
412 | ||
413 | static void | |
414 | rtw89_core_tx_update_sec_key(struct rtw89_dev *rtwdev, | |
415 | struct rtw89_core_tx_request *tx_req) | |
416 | { | |
79a6c9a4 | 417 | const struct rtw89_chip_info *chip = rtwdev->chip; |
e3ec7017 | 418 | struct ieee80211_vif *vif = tx_req->vif; |
2ab856cc | 419 | struct ieee80211_sta *sta = tx_req->sta; |
e3ec7017 PKS |
420 | struct ieee80211_tx_info *info; |
421 | struct ieee80211_key_conf *key; | |
422 | struct rtw89_vif *rtwvif; | |
2ab856cc | 423 | struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); |
e3ec7017 PKS |
424 | struct rtw89_addr_cam_entry *addr_cam; |
425 | struct rtw89_sec_cam_entry *sec_cam; | |
426 | struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; | |
427 | struct sk_buff *skb = tx_req->skb; | |
428 | u8 sec_type = RTW89_SEC_KEY_TYPE_NONE; | |
79a6c9a4 | 429 | u64 pn64; |
e3ec7017 PKS |
430 | |
431 | if (!vif) { | |
432 | rtw89_warn(rtwdev, "cannot set sec key without vif\n"); | |
433 | return; | |
434 | } | |
435 | ||
436 | rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
2ab856cc | 437 | addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); |
e3ec7017 PKS |
438 | |
439 | info = IEEE80211_SKB_CB(skb); | |
440 | key = info->control.hw_key; | |
441 | sec_cam = addr_cam->sec_entries[key->hw_key_idx]; | |
442 | if (!sec_cam) { | |
443 | rtw89_warn(rtwdev, "sec cam entry is empty\n"); | |
444 | return; | |
445 | } | |
446 | ||
447 | switch (key->cipher) { | |
448 | case WLAN_CIPHER_SUITE_WEP40: | |
449 | sec_type = RTW89_SEC_KEY_TYPE_WEP40; | |
450 | break; | |
451 | case WLAN_CIPHER_SUITE_WEP104: | |
452 | sec_type = RTW89_SEC_KEY_TYPE_WEP104; | |
453 | break; | |
454 | case WLAN_CIPHER_SUITE_TKIP: | |
455 | sec_type = RTW89_SEC_KEY_TYPE_TKIP; | |
456 | break; | |
457 | case WLAN_CIPHER_SUITE_CCMP: | |
458 | sec_type = RTW89_SEC_KEY_TYPE_CCMP128; | |
459 | break; | |
460 | case WLAN_CIPHER_SUITE_CCMP_256: | |
461 | sec_type = RTW89_SEC_KEY_TYPE_CCMP256; | |
462 | break; | |
463 | case WLAN_CIPHER_SUITE_GCMP: | |
464 | sec_type = RTW89_SEC_KEY_TYPE_GCMP128; | |
465 | break; | |
466 | case WLAN_CIPHER_SUITE_GCMP_256: | |
467 | sec_type = RTW89_SEC_KEY_TYPE_GCMP256; | |
468 | break; | |
469 | default: | |
470 | rtw89_warn(rtwdev, "key cipher not supported %d\n", key->cipher); | |
471 | return; | |
472 | } | |
473 | ||
474 | desc_info->sec_en = true; | |
79a6c9a4 | 475 | desc_info->sec_keyid = key->keyidx; |
e3ec7017 PKS |
476 | desc_info->sec_type = sec_type; |
477 | desc_info->sec_cam_idx = sec_cam->sec_cam_idx; | |
79a6c9a4 PKS |
478 | |
479 | if (!chip->hw_sec_hdr) | |
480 | return; | |
481 | ||
482 | pn64 = atomic64_inc_return(&key->tx_pn); | |
483 | desc_info->sec_seq[0] = pn64; | |
484 | desc_info->sec_seq[1] = pn64 >> 8; | |
485 | desc_info->sec_seq[2] = pn64 >> 16; | |
486 | desc_info->sec_seq[3] = pn64 >> 24; | |
487 | desc_info->sec_seq[4] = pn64 >> 32; | |
488 | desc_info->sec_seq[5] = pn64 >> 40; | |
489 | desc_info->wp_offset = 1; /* in unit of 8 bytes for security header */ | |
e3ec7017 PKS |
490 | } |
491 | ||
492 | static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, | |
493 | struct rtw89_core_tx_request *tx_req) | |
494 | { | |
495 | struct sk_buff *skb = tx_req->skb; | |
496 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | |
497 | struct ieee80211_vif *vif = tx_info->control.vif; | |
cbb145b9 ZZY |
498 | const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); |
499 | u16 lowest_rate = chan->band_type == RTW89_BAND_2G ? | |
e3ec7017 PKS |
500 | RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6; |
501 | ||
502 | if (!vif || !vif->bss_conf.basic_rates || !tx_req->sta) | |
503 | return lowest_rate; | |
504 | ||
505 | return __ffs(vif->bss_conf.basic_rates) + lowest_rate; | |
506 | } | |
507 | ||
508 | static void | |
509 | rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, | |
510 | struct rtw89_core_tx_request *tx_req) | |
511 | { | |
9eecaec2 PKS |
512 | struct ieee80211_vif *vif = tx_req->vif; |
513 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
e3ec7017 | 514 | struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; |
cbb145b9 | 515 | const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); |
e3ec7017 PKS |
516 | u8 qsel, ch_dma; |
517 | ||
11d261f2 | 518 | qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : RTW89_TX_QSEL_B0_MGMT; |
e3ec7017 PKS |
519 | ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel); |
520 | ||
11d261f2 | 521 | desc_info->qsel = qsel; |
e3ec7017 | 522 | desc_info->ch_dma = ch_dma; |
9eecaec2 | 523 | desc_info->port = desc_info->hiq ? rtwvif->port : 0; |
91644020 PKS |
524 | desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL; |
525 | desc_info->hw_seq_mode = RTW89_MGMT_HW_SEQ_MODE; | |
e3ec7017 PKS |
526 | |
527 | /* fixed data rate for mgmt frames */ | |
528 | desc_info->en_wd_info = true; | |
529 | desc_info->use_rate = true; | |
530 | desc_info->dis_data_fb = true; | |
531 | desc_info->data_rate = rtw89_core_get_mgmt_rate(rtwdev, tx_req); | |
532 | ||
533 | rtw89_debug(rtwdev, RTW89_DBG_TXRX, | |
cbb145b9 ZZY |
534 | "tx mgmt frame with rate 0x%x on channel %d (band %d, bw %d)\n", |
535 | desc_info->data_rate, chan->channel, chan->band_type, | |
536 | chan->band_width); | |
e3ec7017 PKS |
537 | } |
538 | ||
539 | static void | |
540 | rtw89_core_tx_update_h2c_info(struct rtw89_dev *rtwdev, | |
541 | struct rtw89_core_tx_request *tx_req) | |
542 | { | |
543 | struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; | |
544 | ||
545 | desc_info->is_bmc = false; | |
546 | desc_info->wd_page = false; | |
547 | desc_info->ch_dma = RTW89_DMA_H2C; | |
548 | } | |
549 | ||
550 | static void rtw89_core_get_no_ul_ofdma_htc(struct rtw89_dev *rtwdev, __le32 *htc) | |
551 | { | |
552 | static const u8 rtw89_bandwidth_to_om[] = { | |
553 | [RTW89_CHANNEL_WIDTH_20] = HTC_OM_CHANNEL_WIDTH_20, | |
554 | [RTW89_CHANNEL_WIDTH_40] = HTC_OM_CHANNEL_WIDTH_40, | |
555 | [RTW89_CHANNEL_WIDTH_80] = HTC_OM_CHANNEL_WIDTH_80, | |
556 | [RTW89_CHANNEL_WIDTH_160] = HTC_OM_CHANNEL_WIDTH_160_OR_80_80, | |
557 | [RTW89_CHANNEL_WIDTH_80_80] = HTC_OM_CHANNEL_WIDTH_160_OR_80_80, | |
558 | }; | |
559 | const struct rtw89_chip_info *chip = rtwdev->chip; | |
560 | struct rtw89_hal *hal = &rtwdev->hal; | |
cbb145b9 | 561 | const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); |
e3ec7017 PKS |
562 | u8 om_bandwidth; |
563 | ||
564 | if (!chip->dis_2g_40m_ul_ofdma || | |
cbb145b9 ZZY |
565 | chan->band_type != RTW89_BAND_2G || |
566 | chan->band_width != RTW89_CHANNEL_WIDTH_40) | |
e3ec7017 PKS |
567 | return; |
568 | ||
cbb145b9 ZZY |
569 | om_bandwidth = chan->band_width < ARRAY_SIZE(rtw89_bandwidth_to_om) ? |
570 | rtw89_bandwidth_to_om[chan->band_width] : 0; | |
e3ec7017 PKS |
571 | *htc = le32_encode_bits(RTW89_HTC_VARIANT_HE, RTW89_HTC_MASK_VARIANT) | |
572 | le32_encode_bits(RTW89_HTC_VARIANT_HE_CID_OM, RTW89_HTC_MASK_CTL_ID) | | |
573 | le32_encode_bits(hal->rx_nss - 1, RTW89_HTC_MASK_HTC_OM_RX_NSS) | | |
574 | le32_encode_bits(om_bandwidth, RTW89_HTC_MASK_HTC_OM_CH_WIDTH) | | |
575 | le32_encode_bits(1, RTW89_HTC_MASK_HTC_OM_UL_MU_DIS) | | |
576 | le32_encode_bits(hal->tx_nss - 1, RTW89_HTC_MASK_HTC_OM_TX_NSTS) | | |
577 | le32_encode_bits(0, RTW89_HTC_MASK_HTC_OM_ER_SU_DIS) | | |
578 | le32_encode_bits(0, RTW89_HTC_MASK_HTC_OM_DL_MU_MIMO_RR) | | |
579 | le32_encode_bits(0, RTW89_HTC_MASK_HTC_OM_UL_MU_DATA_DIS); | |
580 | } | |
581 | ||
582 | static bool | |
583 | __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev, | |
584 | struct rtw89_core_tx_request *tx_req, | |
585 | enum btc_pkt_type pkt_type) | |
586 | { | |
587 | struct ieee80211_sta *sta = tx_req->sta; | |
588 | struct sk_buff *skb = tx_req->skb; | |
589 | struct ieee80211_hdr *hdr = (void *)skb->data; | |
590 | __le16 fc = hdr->frame_control; | |
591 | ||
592 | /* AP IOT issue with EAPoL, ARP and DHCP */ | |
593 | if (pkt_type < PACKET_MAX) | |
594 | return false; | |
595 | ||
046d2e7c | 596 | if (!sta || !sta->deflink.he_cap.has_he) |
e3ec7017 PKS |
597 | return false; |
598 | ||
599 | if (!ieee80211_is_data_qos(fc)) | |
600 | return false; | |
601 | ||
602 | if (skb_headroom(skb) < IEEE80211_HT_CTL_LEN) | |
603 | return false; | |
604 | ||
605 | return true; | |
606 | } | |
607 | ||
608 | static void | |
609 | __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev, | |
610 | struct rtw89_core_tx_request *tx_req) | |
611 | { | |
612 | struct ieee80211_sta *sta = tx_req->sta; | |
613 | struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; | |
614 | struct sk_buff *skb = tx_req->skb; | |
615 | struct ieee80211_hdr *hdr = (void *)skb->data; | |
616 | __le16 fc = hdr->frame_control; | |
617 | void *data; | |
618 | __le32 *htc; | |
619 | u8 *qc; | |
620 | int hdr_len; | |
621 | ||
622 | hdr_len = ieee80211_has_a4(fc) ? 32 : 26; | |
623 | data = skb_push(skb, IEEE80211_HT_CTL_LEN); | |
624 | memmove(data, data + IEEE80211_HT_CTL_LEN, hdr_len); | |
625 | ||
626 | hdr = data; | |
627 | htc = data + hdr_len; | |
628 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_ORDER); | |
629 | *htc = rtwsta->htc_template ? rtwsta->htc_template : | |
630 | le32_encode_bits(RTW89_HTC_VARIANT_HE, RTW89_HTC_MASK_VARIANT) | | |
631 | le32_encode_bits(RTW89_HTC_VARIANT_HE_CID_CAS, RTW89_HTC_MASK_CTL_ID); | |
632 | ||
633 | qc = data + hdr_len - IEEE80211_QOS_CTL_LEN; | |
634 | qc[0] |= IEEE80211_QOS_CTL_EOSP; | |
635 | } | |
636 | ||
637 | static void | |
638 | rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev, | |
639 | struct rtw89_core_tx_request *tx_req, | |
640 | enum btc_pkt_type pkt_type) | |
641 | { | |
642 | struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; | |
643 | struct ieee80211_vif *vif = tx_req->vif; | |
644 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
645 | ||
646 | if (!__rtw89_core_tx_check_he_qos_htc(rtwdev, tx_req, pkt_type)) | |
647 | goto desc_bk; | |
648 | ||
649 | __rtw89_core_tx_adjust_he_qos_htc(rtwdev, tx_req); | |
650 | ||
651 | desc_info->pkt_size += IEEE80211_HT_CTL_LEN; | |
652 | desc_info->a_ctrl_bsr = true; | |
653 | ||
654 | desc_bk: | |
655 | if (!rtwvif || rtwvif->last_a_ctrl == desc_info->a_ctrl_bsr) | |
656 | return; | |
657 | ||
658 | rtwvif->last_a_ctrl = desc_info->a_ctrl_bsr; | |
659 | desc_info->bk = true; | |
660 | } | |
661 | ||
9eecaec2 PKS |
662 | static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev, |
663 | struct rtw89_core_tx_request *tx_req) | |
664 | { | |
665 | struct ieee80211_vif *vif = tx_req->vif; | |
666 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
667 | struct ieee80211_sta *sta = tx_req->sta; | |
668 | struct rtw89_sta *rtwsta; | |
669 | ||
670 | if (!sta) | |
671 | return rtwvif->mac_id; | |
672 | ||
673 | rtwsta = (struct rtw89_sta *)sta->drv_priv; | |
674 | return rtwsta->mac_id; | |
675 | } | |
676 | ||
e3ec7017 PKS |
677 | static void |
678 | rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, | |
679 | struct rtw89_core_tx_request *tx_req) | |
680 | { | |
681 | struct ieee80211_vif *vif = tx_req->vif; | |
682 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
683 | struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; | |
cbb145b9 | 684 | const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); |
e3ec7017 PKS |
685 | struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; |
686 | struct sk_buff *skb = tx_req->skb; | |
687 | u8 tid, tid_indicate; | |
688 | u8 qsel, ch_dma; | |
689 | ||
690 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | |
691 | tid_indicate = rtw89_core_get_tid_indicate(rtwdev, tid); | |
11d261f2 | 692 | qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : rtw89_core_get_qsel(rtwdev, tid); |
e3ec7017 PKS |
693 | ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel); |
694 | ||
695 | desc_info->ch_dma = ch_dma; | |
696 | desc_info->tid_indicate = tid_indicate; | |
697 | desc_info->qsel = qsel; | |
9eecaec2 PKS |
698 | desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); |
699 | desc_info->port = desc_info->hiq ? rtwvif->port : 0; | |
e3ec7017 PKS |
700 | |
701 | /* enable wd_info for AMPDU */ | |
702 | desc_info->en_wd_info = true; | |
703 | ||
e3ec7017 PKS |
704 | if (IEEE80211_SKB_CB(skb)->control.hw_key) |
705 | rtw89_core_tx_update_sec_key(rtwdev, tx_req); | |
706 | ||
707 | if (rate_pattern->enable) | |
708 | desc_info->data_retry_lowest_rate = rate_pattern->rate; | |
cbb145b9 | 709 | else if (chan->band_type == RTW89_BAND_2G) |
e3ec7017 PKS |
710 | desc_info->data_retry_lowest_rate = RTW89_HW_RATE_CCK1; |
711 | else | |
712 | desc_info->data_retry_lowest_rate = RTW89_HW_RATE_OFDM6; | |
713 | } | |
714 | ||
715 | static enum btc_pkt_type | |
716 | rtw89_core_tx_btc_spec_pkt_notify(struct rtw89_dev *rtwdev, | |
717 | struct rtw89_core_tx_request *tx_req) | |
718 | { | |
719 | struct sk_buff *skb = tx_req->skb; | |
720 | struct udphdr *udphdr; | |
721 | ||
722 | if (IEEE80211_SKB_CB(skb)->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) { | |
723 | ieee80211_queue_work(rtwdev->hw, &rtwdev->btc.eapol_notify_work); | |
724 | return PACKET_EAPOL; | |
725 | } | |
726 | ||
727 | if (skb->protocol == htons(ETH_P_ARP)) { | |
728 | ieee80211_queue_work(rtwdev->hw, &rtwdev->btc.arp_notify_work); | |
729 | return PACKET_ARP; | |
730 | } | |
731 | ||
732 | if (skb->protocol == htons(ETH_P_IP) && | |
733 | ip_hdr(skb)->protocol == IPPROTO_UDP) { | |
734 | udphdr = udp_hdr(skb); | |
735 | if (((udphdr->source == htons(67) && udphdr->dest == htons(68)) || | |
736 | (udphdr->source == htons(68) && udphdr->dest == htons(67))) && | |
737 | skb->len > 282) { | |
738 | ieee80211_queue_work(rtwdev->hw, &rtwdev->btc.dhcp_notify_work); | |
739 | return PACKET_DHCP; | |
740 | } | |
741 | } | |
742 | ||
743 | if (skb->protocol == htons(ETH_P_IP) && | |
744 | ip_hdr(skb)->protocol == IPPROTO_ICMP) { | |
745 | ieee80211_queue_work(rtwdev->hw, &rtwdev->btc.icmp_notify_work); | |
746 | return PACKET_ICMP; | |
747 | } | |
748 | ||
749 | return PACKET_MAX; | |
750 | } | |
751 | ||
79a6c9a4 PKS |
752 | static void rtw89_core_tx_update_llc_hdr(struct rtw89_dev *rtwdev, |
753 | struct rtw89_tx_desc_info *desc_info, | |
754 | struct sk_buff *skb) | |
755 | { | |
756 | struct ieee80211_hdr *hdr = (void *)skb->data; | |
757 | __le16 fc = hdr->frame_control; | |
758 | ||
759 | desc_info->hdr_llc_len = ieee80211_hdrlen(fc); | |
760 | desc_info->hdr_llc_len >>= 1; /* in unit of 2 bytes */ | |
761 | } | |
762 | ||
7bfd05ff CYL |
763 | static void |
764 | rtw89_core_tx_wake(struct rtw89_dev *rtwdev, | |
765 | struct rtw89_core_tx_request *tx_req) | |
766 | { | |
11fe4ccd | 767 | if (!RTW89_CHK_FW_FEATURE(TX_WAKE, &rtwdev->fw)) |
7bfd05ff CYL |
768 | return; |
769 | ||
770 | if (!test_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags)) | |
771 | return; | |
772 | ||
773 | if (tx_req->tx_type != RTW89_CORE_TX_TYPE_MGMT) | |
774 | return; | |
775 | ||
776 | rtw89_mac_notify_wake(rtwdev); | |
777 | } | |
778 | ||
e3ec7017 PKS |
779 | static void |
780 | rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev, | |
781 | struct rtw89_core_tx_request *tx_req) | |
782 | { | |
783 | struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; | |
784 | struct sk_buff *skb = tx_req->skb; | |
11d261f2 | 785 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
e3ec7017 PKS |
786 | struct ieee80211_hdr *hdr = (void *)skb->data; |
787 | enum rtw89_core_tx_type tx_type; | |
788 | enum btc_pkt_type pkt_type; | |
789 | bool is_bmc; | |
790 | u16 seq; | |
791 | ||
792 | seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; | |
793 | if (tx_req->tx_type != RTW89_CORE_TX_TYPE_FWCMD) { | |
794 | tx_type = rtw89_core_get_tx_type(rtwdev, skb); | |
795 | tx_req->tx_type = tx_type; | |
796 | } | |
797 | is_bmc = (is_broadcast_ether_addr(hdr->addr1) || | |
798 | is_multicast_ether_addr(hdr->addr1)); | |
799 | ||
800 | desc_info->seq = seq; | |
801 | desc_info->pkt_size = skb->len; | |
802 | desc_info->is_bmc = is_bmc; | |
803 | desc_info->wd_page = true; | |
11d261f2 | 804 | desc_info->hiq = info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM; |
e3ec7017 PKS |
805 | |
806 | switch (tx_req->tx_type) { | |
807 | case RTW89_CORE_TX_TYPE_MGMT: | |
808 | rtw89_core_tx_update_mgmt_info(rtwdev, tx_req); | |
809 | break; | |
810 | case RTW89_CORE_TX_TYPE_DATA: | |
811 | rtw89_core_tx_update_data_info(rtwdev, tx_req); | |
812 | pkt_type = rtw89_core_tx_btc_spec_pkt_notify(rtwdev, tx_req); | |
813 | rtw89_core_tx_update_he_qos_htc(rtwdev, tx_req, pkt_type); | |
679955d5 | 814 | rtw89_core_tx_update_ampdu_info(rtwdev, tx_req, pkt_type); |
79a6c9a4 | 815 | rtw89_core_tx_update_llc_hdr(rtwdev, desc_info, skb); |
e3ec7017 PKS |
816 | break; |
817 | case RTW89_CORE_TX_TYPE_FWCMD: | |
818 | rtw89_core_tx_update_h2c_info(rtwdev, tx_req); | |
819 | break; | |
820 | } | |
821 | } | |
822 | ||
823 | void rtw89_core_tx_kick_off(struct rtw89_dev *rtwdev, u8 qsel) | |
824 | { | |
825 | u8 ch_dma; | |
826 | ||
827 | ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel); | |
828 | ||
829 | rtw89_hci_tx_kick_off(rtwdev, ch_dma); | |
830 | } | |
831 | ||
832 | int rtw89_h2c_tx(struct rtw89_dev *rtwdev, | |
833 | struct sk_buff *skb, bool fwdl) | |
834 | { | |
835 | struct rtw89_core_tx_request tx_req = {0}; | |
836 | u32 cnt; | |
837 | int ret; | |
838 | ||
fc5f311f PKS |
839 | if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) { |
840 | rtw89_debug(rtwdev, RTW89_DBG_FW, | |
841 | "ignore h2c due to power is off with firmware state=%d\n", | |
842 | test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags)); | |
843 | return 0; | |
844 | } | |
845 | ||
e3ec7017 PKS |
846 | tx_req.skb = skb; |
847 | tx_req.tx_type = RTW89_CORE_TX_TYPE_FWCMD; | |
848 | if (fwdl) | |
849 | tx_req.desc_info.fw_dl = true; | |
850 | ||
851 | rtw89_core_tx_update_desc_info(rtwdev, &tx_req); | |
852 | ||
853 | if (!fwdl) | |
854 | rtw89_hex_dump(rtwdev, RTW89_DBG_FW, "H2C: ", skb->data, skb->len); | |
855 | ||
856 | cnt = rtw89_hci_check_and_reclaim_tx_resource(rtwdev, RTW89_TXCH_CH12); | |
857 | if (cnt == 0) { | |
858 | rtw89_err(rtwdev, "no tx fwcmd resource\n"); | |
859 | return -ENOSPC; | |
860 | } | |
861 | ||
862 | ret = rtw89_hci_tx_write(rtwdev, &tx_req); | |
863 | if (ret) { | |
864 | rtw89_err(rtwdev, "failed to transmit skb to HCI\n"); | |
865 | return ret; | |
866 | } | |
867 | rtw89_hci_tx_kick_off(rtwdev, RTW89_TXCH_CH12); | |
868 | ||
869 | return 0; | |
870 | } | |
871 | ||
872 | int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, | |
873 | struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel) | |
874 | { | |
875 | struct rtw89_core_tx_request tx_req = {0}; | |
876 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
877 | int ret; | |
878 | ||
879 | tx_req.skb = skb; | |
880 | tx_req.sta = sta; | |
881 | tx_req.vif = vif; | |
882 | ||
883 | rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true); | |
884 | rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true); | |
885 | rtw89_core_tx_update_desc_info(rtwdev, &tx_req); | |
7bfd05ff CYL |
886 | rtw89_core_tx_wake(rtwdev, &tx_req); |
887 | ||
e3ec7017 PKS |
888 | ret = rtw89_hci_tx_write(rtwdev, &tx_req); |
889 | if (ret) { | |
890 | rtw89_err(rtwdev, "failed to transmit skb to HCI\n"); | |
891 | return ret; | |
892 | } | |
893 | ||
894 | if (qsel) | |
895 | *qsel = tx_req.desc_info.qsel; | |
896 | ||
897 | return 0; | |
898 | } | |
899 | ||
900 | static __le32 rtw89_build_txwd_body0(struct rtw89_tx_desc_info *desc_info) | |
901 | { | |
902 | u32 dword = FIELD_PREP(RTW89_TXWD_BODY0_WP_OFFSET, desc_info->wp_offset) | | |
903 | FIELD_PREP(RTW89_TXWD_BODY0_WD_INFO_EN, desc_info->en_wd_info) | | |
904 | FIELD_PREP(RTW89_TXWD_BODY0_CHANNEL_DMA, desc_info->ch_dma) | | |
905 | FIELD_PREP(RTW89_TXWD_BODY0_HDR_LLC_LEN, desc_info->hdr_llc_len) | | |
906 | FIELD_PREP(RTW89_TXWD_BODY0_WD_PAGE, desc_info->wd_page) | | |
91644020 PKS |
907 | FIELD_PREP(RTW89_TXWD_BODY0_FW_DL, desc_info->fw_dl) | |
908 | FIELD_PREP(RTW89_TXWD_BODY0_HW_SSN_SEL, desc_info->hw_ssn_sel) | | |
909 | FIELD_PREP(RTW89_TXWD_BODY0_HW_SSN_MODE, desc_info->hw_seq_mode); | |
e3ec7017 PKS |
910 | |
911 | return cpu_to_le32(dword); | |
912 | } | |
913 | ||
f59acdde PKS |
914 | static __le32 rtw89_build_txwd_body0_v1(struct rtw89_tx_desc_info *desc_info) |
915 | { | |
916 | u32 dword = FIELD_PREP(RTW89_TXWD_BODY0_WP_OFFSET_V1, desc_info->wp_offset) | | |
917 | FIELD_PREP(RTW89_TXWD_BODY0_WD_INFO_EN, desc_info->en_wd_info) | | |
918 | FIELD_PREP(RTW89_TXWD_BODY0_CHANNEL_DMA, desc_info->ch_dma) | | |
919 | FIELD_PREP(RTW89_TXWD_BODY0_HDR_LLC_LEN, desc_info->hdr_llc_len) | | |
920 | FIELD_PREP(RTW89_TXWD_BODY0_WD_PAGE, desc_info->wd_page) | | |
921 | FIELD_PREP(RTW89_TXWD_BODY0_FW_DL, desc_info->fw_dl); | |
922 | ||
923 | return cpu_to_le32(dword); | |
924 | } | |
925 | ||
926 | static __le32 rtw89_build_txwd_body1_v1(struct rtw89_tx_desc_info *desc_info) | |
927 | { | |
928 | u32 dword = FIELD_PREP(RTW89_TXWD_BODY1_ADDR_INFO_NUM, desc_info->addr_info_nr) | | |
79a6c9a4 | 929 | FIELD_PREP(RTW89_TXWD_BODY1_SEC_KEYID, desc_info->sec_keyid) | |
f59acdde PKS |
930 | FIELD_PREP(RTW89_TXWD_BODY1_SEC_TYPE, desc_info->sec_type); |
931 | ||
932 | return cpu_to_le32(dword); | |
933 | } | |
934 | ||
e3ec7017 PKS |
935 | static __le32 rtw89_build_txwd_body2(struct rtw89_tx_desc_info *desc_info) |
936 | { | |
937 | u32 dword = FIELD_PREP(RTW89_TXWD_BODY2_TID_INDICATE, desc_info->tid_indicate) | | |
938 | FIELD_PREP(RTW89_TXWD_BODY2_QSEL, desc_info->qsel) | | |
9eecaec2 PKS |
939 | FIELD_PREP(RTW89_TXWD_BODY2_TXPKT_SIZE, desc_info->pkt_size) | |
940 | FIELD_PREP(RTW89_TXWD_BODY2_MACID, desc_info->mac_id); | |
e3ec7017 PKS |
941 | |
942 | return cpu_to_le32(dword); | |
943 | } | |
944 | ||
945 | static __le32 rtw89_build_txwd_body3(struct rtw89_tx_desc_info *desc_info) | |
946 | { | |
947 | u32 dword = FIELD_PREP(RTW89_TXWD_BODY3_SW_SEQ, desc_info->seq) | | |
948 | FIELD_PREP(RTW89_TXWD_BODY3_AGG_EN, desc_info->agg_en) | | |
949 | FIELD_PREP(RTW89_TXWD_BODY3_BK, desc_info->bk); | |
950 | ||
951 | return cpu_to_le32(dword); | |
952 | } | |
953 | ||
79a6c9a4 PKS |
954 | static __le32 rtw89_build_txwd_body4(struct rtw89_tx_desc_info *desc_info) |
955 | { | |
956 | u32 dword = FIELD_PREP(RTW89_TXWD_BODY4_SEC_IV_L0, desc_info->sec_seq[0]) | | |
957 | FIELD_PREP(RTW89_TXWD_BODY4_SEC_IV_L1, desc_info->sec_seq[1]); | |
958 | ||
959 | return cpu_to_le32(dword); | |
960 | } | |
961 | ||
962 | static __le32 rtw89_build_txwd_body5(struct rtw89_tx_desc_info *desc_info) | |
963 | { | |
964 | u32 dword = FIELD_PREP(RTW89_TXWD_BODY5_SEC_IV_H2, desc_info->sec_seq[2]) | | |
965 | FIELD_PREP(RTW89_TXWD_BODY5_SEC_IV_H3, desc_info->sec_seq[3]) | | |
966 | FIELD_PREP(RTW89_TXWD_BODY5_SEC_IV_H4, desc_info->sec_seq[4]) | | |
967 | FIELD_PREP(RTW89_TXWD_BODY5_SEC_IV_H5, desc_info->sec_seq[5]); | |
968 | ||
969 | return cpu_to_le32(dword); | |
970 | } | |
971 | ||
f59acdde PKS |
972 | static __le32 rtw89_build_txwd_body7_v1(struct rtw89_tx_desc_info *desc_info) |
973 | { | |
974 | u32 dword = FIELD_PREP(RTW89_TXWD_BODY7_USE_RATE_V1, desc_info->use_rate) | | |
975 | FIELD_PREP(RTW89_TXWD_BODY7_DATA_RATE, desc_info->data_rate); | |
976 | ||
977 | return cpu_to_le32(dword); | |
978 | } | |
979 | ||
e3ec7017 PKS |
980 | static __le32 rtw89_build_txwd_info0(struct rtw89_tx_desc_info *desc_info) |
981 | { | |
982 | u32 dword = FIELD_PREP(RTW89_TXWD_INFO0_USE_RATE, desc_info->use_rate) | | |
983 | FIELD_PREP(RTW89_TXWD_INFO0_DATA_RATE, desc_info->data_rate) | | |
9eecaec2 PKS |
984 | FIELD_PREP(RTW89_TXWD_INFO0_DISDATAFB, desc_info->dis_data_fb) | |
985 | FIELD_PREP(RTW89_TXWD_INFO0_MULTIPORT_ID, desc_info->port); | |
e3ec7017 PKS |
986 | |
987 | return cpu_to_le32(dword); | |
988 | } | |
989 | ||
f59acdde PKS |
990 | static __le32 rtw89_build_txwd_info0_v1(struct rtw89_tx_desc_info *desc_info) |
991 | { | |
992 | u32 dword = FIELD_PREP(RTW89_TXWD_INFO0_DISDATAFB, desc_info->dis_data_fb); | |
993 | ||
994 | return cpu_to_le32(dword); | |
995 | } | |
996 | ||
e3ec7017 PKS |
997 | static __le32 rtw89_build_txwd_info1(struct rtw89_tx_desc_info *desc_info) |
998 | { | |
999 | u32 dword = FIELD_PREP(RTW89_TXWD_INFO1_MAX_AGGNUM, desc_info->ampdu_num) | | |
1000 | FIELD_PREP(RTW89_TXWD_INFO1_A_CTRL_BSR, desc_info->a_ctrl_bsr) | | |
1001 | FIELD_PREP(RTW89_TXWD_INFO1_DATA_RTY_LOWEST_RATE, | |
1002 | desc_info->data_retry_lowest_rate); | |
1003 | ||
1004 | return cpu_to_le32(dword); | |
1005 | } | |
1006 | ||
1007 | static __le32 rtw89_build_txwd_info2(struct rtw89_tx_desc_info *desc_info) | |
1008 | { | |
1009 | u32 dword = FIELD_PREP(RTW89_TXWD_INFO2_AMPDU_DENSITY, desc_info->ampdu_density) | | |
1010 | FIELD_PREP(RTW89_TXWD_INFO2_SEC_TYPE, desc_info->sec_type) | | |
1011 | FIELD_PREP(RTW89_TXWD_INFO2_SEC_HW_ENC, desc_info->sec_en) | | |
1012 | FIELD_PREP(RTW89_TXWD_INFO2_SEC_CAM_IDX, desc_info->sec_cam_idx); | |
1013 | ||
1014 | return cpu_to_le32(dword); | |
1015 | } | |
1016 | ||
f59acdde PKS |
1017 | static __le32 rtw89_build_txwd_info2_v1(struct rtw89_tx_desc_info *desc_info) |
1018 | { | |
1019 | u32 dword = FIELD_PREP(RTW89_TXWD_INFO2_AMPDU_DENSITY, desc_info->ampdu_density) | | |
1020 | FIELD_PREP(RTW89_TXWD_INFO2_FORCE_KEY_EN, desc_info->sec_en) | | |
1021 | FIELD_PREP(RTW89_TXWD_INFO2_SEC_CAM_IDX, desc_info->sec_cam_idx); | |
1022 | ||
1023 | return cpu_to_le32(dword); | |
1024 | } | |
1025 | ||
e3ec7017 PKS |
1026 | static __le32 rtw89_build_txwd_info4(struct rtw89_tx_desc_info *desc_info) |
1027 | { | |
1028 | u32 dword = FIELD_PREP(RTW89_TXWD_INFO4_RTS_EN, 1) | | |
1029 | FIELD_PREP(RTW89_TXWD_INFO4_HW_RTS_EN, 1); | |
1030 | ||
1031 | return cpu_to_le32(dword); | |
1032 | } | |
1033 | ||
1034 | void rtw89_core_fill_txdesc(struct rtw89_dev *rtwdev, | |
1035 | struct rtw89_tx_desc_info *desc_info, | |
1036 | void *txdesc) | |
1037 | { | |
1038 | struct rtw89_txwd_body *txwd_body = (struct rtw89_txwd_body *)txdesc; | |
1039 | struct rtw89_txwd_info *txwd_info; | |
1040 | ||
1041 | txwd_body->dword0 = rtw89_build_txwd_body0(desc_info); | |
1042 | txwd_body->dword2 = rtw89_build_txwd_body2(desc_info); | |
1043 | txwd_body->dword3 = rtw89_build_txwd_body3(desc_info); | |
1044 | ||
1045 | if (!desc_info->en_wd_info) | |
1046 | return; | |
1047 | ||
1048 | txwd_info = (struct rtw89_txwd_info *)(txwd_body + 1); | |
1049 | txwd_info->dword0 = rtw89_build_txwd_info0(desc_info); | |
1050 | txwd_info->dword1 = rtw89_build_txwd_info1(desc_info); | |
1051 | txwd_info->dword2 = rtw89_build_txwd_info2(desc_info); | |
1052 | txwd_info->dword4 = rtw89_build_txwd_info4(desc_info); | |
1053 | ||
1054 | } | |
1055 | EXPORT_SYMBOL(rtw89_core_fill_txdesc); | |
1056 | ||
f59acdde PKS |
1057 | void rtw89_core_fill_txdesc_v1(struct rtw89_dev *rtwdev, |
1058 | struct rtw89_tx_desc_info *desc_info, | |
1059 | void *txdesc) | |
1060 | { | |
1061 | struct rtw89_txwd_body_v1 *txwd_body = (struct rtw89_txwd_body_v1 *)txdesc; | |
1062 | struct rtw89_txwd_info *txwd_info; | |
1063 | ||
1064 | txwd_body->dword0 = rtw89_build_txwd_body0_v1(desc_info); | |
1065 | txwd_body->dword1 = rtw89_build_txwd_body1_v1(desc_info); | |
1066 | txwd_body->dword2 = rtw89_build_txwd_body2(desc_info); | |
1067 | txwd_body->dword3 = rtw89_build_txwd_body3(desc_info); | |
79a6c9a4 PKS |
1068 | if (desc_info->sec_en) { |
1069 | txwd_body->dword4 = rtw89_build_txwd_body4(desc_info); | |
1070 | txwd_body->dword5 = rtw89_build_txwd_body5(desc_info); | |
1071 | } | |
f59acdde PKS |
1072 | txwd_body->dword7 = rtw89_build_txwd_body7_v1(desc_info); |
1073 | ||
1074 | if (!desc_info->en_wd_info) | |
1075 | return; | |
1076 | ||
1077 | txwd_info = (struct rtw89_txwd_info *)(txwd_body + 1); | |
1078 | txwd_info->dword0 = rtw89_build_txwd_info0_v1(desc_info); | |
1079 | txwd_info->dword1 = rtw89_build_txwd_info1(desc_info); | |
1080 | txwd_info->dword2 = rtw89_build_txwd_info2_v1(desc_info); | |
1081 | txwd_info->dword4 = rtw89_build_txwd_info4(desc_info); | |
1082 | } | |
1083 | EXPORT_SYMBOL(rtw89_core_fill_txdesc_v1); | |
1084 | ||
a95bd62e PKS |
1085 | static __le32 rtw89_build_txwd_fwcmd0_v1(struct rtw89_tx_desc_info *desc_info) |
1086 | { | |
1087 | u32 dword = FIELD_PREP(AX_RXD_RPKT_LEN_MASK, desc_info->pkt_size) | | |
1088 | FIELD_PREP(AX_RXD_RPKT_TYPE_MASK, desc_info->fw_dl ? | |
1089 | RTW89_CORE_RX_TYPE_FWDL : | |
1090 | RTW89_CORE_RX_TYPE_H2C); | |
1091 | ||
1092 | return cpu_to_le32(dword); | |
1093 | } | |
1094 | ||
1095 | void rtw89_core_fill_txdesc_fwcmd_v1(struct rtw89_dev *rtwdev, | |
1096 | struct rtw89_tx_desc_info *desc_info, | |
1097 | void *txdesc) | |
1098 | { | |
1099 | struct rtw89_rxdesc_short *txwd_v1 = (struct rtw89_rxdesc_short *)txdesc; | |
1100 | ||
1101 | txwd_v1->dword0 = rtw89_build_txwd_fwcmd0_v1(desc_info); | |
1102 | } | |
1103 | EXPORT_SYMBOL(rtw89_core_fill_txdesc_fwcmd_v1); | |
1104 | ||
e3ec7017 PKS |
1105 | static int rtw89_core_rx_process_mac_ppdu(struct rtw89_dev *rtwdev, |
1106 | struct sk_buff *skb, | |
1107 | struct rtw89_rx_phy_ppdu *phy_ppdu) | |
1108 | { | |
1109 | bool rx_cnt_valid = false; | |
1110 | u8 plcp_size = 0; | |
1111 | u8 usr_num = 0; | |
1112 | u8 *phy_sts; | |
1113 | ||
1114 | rx_cnt_valid = RTW89_GET_RXINFO_RX_CNT_VLD(skb->data); | |
1115 | plcp_size = RTW89_GET_RXINFO_PLCP_LEN(skb->data) << 3; | |
1116 | usr_num = RTW89_GET_RXINFO_USR_NUM(skb->data); | |
1117 | if (usr_num > RTW89_PPDU_MAX_USR) { | |
1118 | rtw89_warn(rtwdev, "Invalid user number in mac info\n"); | |
1119 | return -EINVAL; | |
1120 | } | |
1121 | ||
1122 | phy_sts = skb->data + RTW89_PPDU_MAC_INFO_SIZE; | |
1123 | phy_sts += usr_num * RTW89_PPDU_MAC_INFO_USR_SIZE; | |
1124 | /* 8-byte alignment */ | |
1125 | if (usr_num & BIT(0)) | |
1126 | phy_sts += RTW89_PPDU_MAC_INFO_USR_SIZE; | |
1127 | if (rx_cnt_valid) | |
1128 | phy_sts += RTW89_PPDU_MAC_RX_CNT_SIZE; | |
1129 | phy_sts += plcp_size; | |
1130 | ||
1131 | phy_ppdu->buf = phy_sts; | |
1132 | phy_ppdu->len = skb->data + skb->len - phy_sts; | |
1133 | ||
1134 | return 0; | |
1135 | } | |
1136 | ||
1137 | static void rtw89_core_rx_process_phy_ppdu_iter(void *data, | |
1138 | struct ieee80211_sta *sta) | |
1139 | { | |
1140 | struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; | |
1141 | struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data; | |
1142 | ||
1143 | if (rtwsta->mac_id == phy_ppdu->mac_id && phy_ppdu->to_self) | |
1144 | ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg); | |
1145 | } | |
1146 | ||
1147 | #define VAR_LEN 0xff | |
1148 | #define VAR_LEN_UNIT 8 | |
1149 | static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, u8 *addr) | |
1150 | { | |
1151 | static const u8 physts_ie_len_tab[32] = { | |
1152 | 16, 32, 24, 24, 8, 8, 8, 8, VAR_LEN, 8, VAR_LEN, 176, VAR_LEN, | |
1153 | VAR_LEN, VAR_LEN, VAR_LEN, VAR_LEN, VAR_LEN, 16, 24, VAR_LEN, | |
1154 | VAR_LEN, VAR_LEN, 0, 24, 24, 24, 24, 32, 32, 32, 32 | |
1155 | }; | |
1156 | u16 ie_len; | |
1157 | u8 ie; | |
1158 | ||
1159 | ie = RTW89_GET_PHY_STS_IE_TYPE(addr); | |
1160 | if (physts_ie_len_tab[ie] != VAR_LEN) | |
1161 | ie_len = physts_ie_len_tab[ie]; | |
1162 | else | |
1163 | ie_len = RTW89_GET_PHY_STS_IE_LEN(addr) * VAR_LEN_UNIT; | |
1164 | ||
1165 | return ie_len; | |
1166 | } | |
1167 | ||
1168 | static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev, u8 *addr, | |
1169 | struct rtw89_rx_phy_ppdu *phy_ppdu) | |
1170 | { | |
1171 | s16 cfo; | |
1172 | ||
eb4e52b3 PHH |
1173 | phy_ppdu->chan_idx = RTW89_GET_PHY_STS_IE01_CH_IDX(addr); |
1174 | if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6) | |
1175 | return; | |
e3ec7017 | 1176 | /* sign conversion for S(12,2) */ |
eb4e52b3 | 1177 | cfo = sign_extend32(RTW89_GET_PHY_STS_IE01_CFO(addr), 11); |
e3ec7017 PKS |
1178 | rtw89_phy_cfo_parse(rtwdev, cfo, phy_ppdu); |
1179 | } | |
1180 | ||
1181 | static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, u8 *addr, | |
1182 | struct rtw89_rx_phy_ppdu *phy_ppdu) | |
1183 | { | |
1184 | u8 ie; | |
1185 | ||
1186 | ie = RTW89_GET_PHY_STS_IE_TYPE(addr); | |
1187 | switch (ie) { | |
1188 | case RTW89_PHYSTS_IE01_CMN_OFDM: | |
1189 | rtw89_core_parse_phy_status_ie01(rtwdev, addr, phy_ppdu); | |
1190 | break; | |
1191 | default: | |
1192 | break; | |
1193 | } | |
1194 | ||
1195 | return 0; | |
1196 | } | |
1197 | ||
1198 | static void rtw89_core_update_phy_ppdu(struct rtw89_rx_phy_ppdu *phy_ppdu) | |
1199 | { | |
1200 | s8 *rssi = phy_ppdu->rssi; | |
1201 | u8 *buf = phy_ppdu->buf; | |
1202 | ||
eb4e52b3 | 1203 | phy_ppdu->ie = RTW89_GET_PHY_STS_IE_MAP(buf); |
e3ec7017 PKS |
1204 | phy_ppdu->rssi_avg = RTW89_GET_PHY_STS_RSSI_AVG(buf); |
1205 | rssi[RF_PATH_A] = RTW89_RSSI_RAW_TO_DBM(RTW89_GET_PHY_STS_RSSI_A(buf)); | |
1206 | rssi[RF_PATH_B] = RTW89_RSSI_RAW_TO_DBM(RTW89_GET_PHY_STS_RSSI_B(buf)); | |
1207 | rssi[RF_PATH_C] = RTW89_RSSI_RAW_TO_DBM(RTW89_GET_PHY_STS_RSSI_C(buf)); | |
1208 | rssi[RF_PATH_D] = RTW89_RSSI_RAW_TO_DBM(RTW89_GET_PHY_STS_RSSI_D(buf)); | |
1209 | } | |
1210 | ||
1211 | static int rtw89_core_rx_process_phy_ppdu(struct rtw89_dev *rtwdev, | |
1212 | struct rtw89_rx_phy_ppdu *phy_ppdu) | |
1213 | { | |
1214 | if (RTW89_GET_PHY_STS_LEN(phy_ppdu->buf) << 3 != phy_ppdu->len) { | |
ad663693 | 1215 | rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "phy ppdu len mismatch\n"); |
e3ec7017 PKS |
1216 | return -EINVAL; |
1217 | } | |
1218 | rtw89_core_update_phy_ppdu(phy_ppdu); | |
1219 | ieee80211_iterate_stations_atomic(rtwdev->hw, | |
1220 | rtw89_core_rx_process_phy_ppdu_iter, | |
1221 | phy_ppdu); | |
1222 | ||
1223 | return 0; | |
1224 | } | |
1225 | ||
1226 | static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev, | |
1227 | struct rtw89_rx_phy_ppdu *phy_ppdu) | |
1228 | { | |
1229 | u16 ie_len; | |
1230 | u8 *pos, *end; | |
1231 | ||
eb4e52b3 PHH |
1232 | /* mark invalid reports and bypass them */ |
1233 | if (phy_ppdu->ie < RTW89_CCK_PKT) | |
1234 | return -EINVAL; | |
e3ec7017 PKS |
1235 | |
1236 | pos = (u8 *)phy_ppdu->buf + PHY_STS_HDR_LEN; | |
1237 | end = (u8 *)phy_ppdu->buf + phy_ppdu->len; | |
1238 | while (pos < end) { | |
1239 | ie_len = rtw89_core_get_phy_status_ie_len(rtwdev, pos); | |
1240 | rtw89_core_process_phy_status_ie(rtwdev, pos, phy_ppdu); | |
1241 | pos += ie_len; | |
1242 | if (pos > end || ie_len == 0) { | |
1243 | rtw89_debug(rtwdev, RTW89_DBG_TXRX, | |
1244 | "phy status parse failed\n"); | |
1245 | return -EINVAL; | |
1246 | } | |
1247 | } | |
1248 | ||
1249 | return 0; | |
1250 | } | |
1251 | ||
1252 | static void rtw89_core_rx_process_phy_sts(struct rtw89_dev *rtwdev, | |
1253 | struct rtw89_rx_phy_ppdu *phy_ppdu) | |
1254 | { | |
1255 | int ret; | |
1256 | ||
1257 | ret = rtw89_core_rx_parse_phy_sts(rtwdev, phy_ppdu); | |
1258 | if (ret) | |
1259 | rtw89_debug(rtwdev, RTW89_DBG_TXRX, "parse phy sts failed\n"); | |
1260 | else | |
1261 | phy_ppdu->valid = true; | |
1262 | } | |
1263 | ||
1264 | static u8 rtw89_rxdesc_to_nl_he_gi(struct rtw89_dev *rtwdev, | |
1265 | const struct rtw89_rx_desc_info *desc_info, | |
1266 | bool rx_status) | |
1267 | { | |
1268 | switch (desc_info->gi_ltf) { | |
1269 | case RTW89_GILTF_SGI_4XHE08: | |
1270 | case RTW89_GILTF_2XHE08: | |
1271 | case RTW89_GILTF_1XHE08: | |
1272 | return NL80211_RATE_INFO_HE_GI_0_8; | |
1273 | case RTW89_GILTF_2XHE16: | |
1274 | case RTW89_GILTF_1XHE16: | |
1275 | return NL80211_RATE_INFO_HE_GI_1_6; | |
1276 | case RTW89_GILTF_LGI_4XHE32: | |
1277 | return NL80211_RATE_INFO_HE_GI_3_2; | |
1278 | default: | |
1279 | rtw89_warn(rtwdev, "invalid gi_ltf=%d", desc_info->gi_ltf); | |
1280 | return rx_status ? NL80211_RATE_INFO_HE_GI_3_2 : U8_MAX; | |
1281 | } | |
1282 | } | |
1283 | ||
1284 | static bool rtw89_core_rx_ppdu_match(struct rtw89_dev *rtwdev, | |
1285 | struct rtw89_rx_desc_info *desc_info, | |
1286 | struct ieee80211_rx_status *status) | |
1287 | { | |
1288 | u8 band = desc_info->bb_sel ? RTW89_PHY_1 : RTW89_PHY_0; | |
1289 | u8 data_rate_mode, bw, rate_idx = MASKBYTE0, gi_ltf; | |
1290 | u16 data_rate; | |
1291 | bool ret; | |
1292 | ||
1293 | data_rate = desc_info->data_rate; | |
1294 | data_rate_mode = GET_DATA_RATE_MODE(data_rate); | |
1295 | if (data_rate_mode == DATA_RATE_MODE_NON_HT) { | |
1296 | rate_idx = GET_DATA_RATE_NOT_HT_IDX(data_rate); | |
eb4e52b3 | 1297 | /* rate_idx is still hardware value here */ |
e3ec7017 PKS |
1298 | } else if (data_rate_mode == DATA_RATE_MODE_HT) { |
1299 | rate_idx = GET_DATA_RATE_HT_IDX(data_rate); | |
1300 | } else if (data_rate_mode == DATA_RATE_MODE_VHT) { | |
1301 | rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); | |
1302 | } else if (data_rate_mode == DATA_RATE_MODE_HE) { | |
1303 | rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); | |
1304 | } else { | |
1305 | rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode); | |
1306 | } | |
1307 | ||
167044af | 1308 | bw = rtw89_hw_to_rate_info_bw(desc_info->bw); |
e3ec7017 PKS |
1309 | gi_ltf = rtw89_rxdesc_to_nl_he_gi(rtwdev, desc_info, false); |
1310 | ret = rtwdev->ppdu_sts.curr_rx_ppdu_cnt[band] == desc_info->ppdu_cnt && | |
1311 | status->rate_idx == rate_idx && | |
1312 | status->he_gi == gi_ltf && | |
1313 | status->bw == bw; | |
1314 | ||
1315 | return ret; | |
1316 | } | |
1317 | ||
1318 | struct rtw89_vif_rx_stats_iter_data { | |
1319 | struct rtw89_dev *rtwdev; | |
1320 | struct rtw89_rx_phy_ppdu *phy_ppdu; | |
1321 | struct rtw89_rx_desc_info *desc_info; | |
1322 | struct sk_buff *skb; | |
1323 | const u8 *bssid; | |
1324 | }; | |
1325 | ||
5165f168 PHH |
1326 | static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, |
1327 | struct ieee80211_vif *vif, | |
1328 | struct sk_buff *skb) | |
1329 | { | |
1330 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
1331 | struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data; | |
1332 | u8 *pos, *end, type; | |
1333 | u16 aid; | |
1334 | ||
1335 | if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) || | |
1336 | rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || | |
1337 | rtwvif->net_type == RTW89_NET_TYPE_NO_LINK) | |
1338 | return; | |
1339 | ||
1340 | type = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_TYPE_MASK); | |
1341 | if (type != IEEE80211_TRIGGER_TYPE_BASIC) | |
1342 | return; | |
1343 | ||
1344 | end = (u8 *)tf + skb->len; | |
1345 | pos = tf->variable; | |
1346 | ||
1347 | while (end - pos >= RTW89_TF_BASIC_USER_INFO_SZ) { | |
1348 | aid = RTW89_GET_TF_USER_INFO_AID12(pos); | |
1349 | rtw89_debug(rtwdev, RTW89_DBG_TXRX, | |
1350 | "[TF] aid: %d, ul_mcs: %d, rua: %d\n", | |
1351 | aid, RTW89_GET_TF_USER_INFO_UL_MCS(pos), | |
1352 | RTW89_GET_TF_USER_INFO_RUA(pos)); | |
1353 | ||
1354 | if (aid == RTW89_TF_PAD) | |
1355 | break; | |
1356 | ||
f276e20b | 1357 | if (aid == vif->cfg.aid) { |
5165f168 PHH |
1358 | rtwvif->stats.rx_tf_acc++; |
1359 | rtwdev->stats.rx_tf_acc++; | |
1360 | break; | |
1361 | } | |
1362 | ||
1363 | pos += RTW89_TF_BASIC_USER_INFO_SZ; | |
1364 | } | |
1365 | } | |
1366 | ||
e3ec7017 PKS |
1367 | static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, |
1368 | struct ieee80211_vif *vif) | |
1369 | { | |
1370 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
1371 | struct rtw89_vif_rx_stats_iter_data *iter_data = data; | |
1372 | struct rtw89_dev *rtwdev = iter_data->rtwdev; | |
1373 | struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat; | |
1374 | struct rtw89_rx_desc_info *desc_info = iter_data->desc_info; | |
1375 | struct sk_buff *skb = iter_data->skb; | |
1376 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | |
1377 | const u8 *bssid = iter_data->bssid; | |
1378 | ||
5165f168 PHH |
1379 | if (ieee80211_is_trigger(hdr->frame_control)) { |
1380 | rtw89_stats_trigger_frame(rtwdev, vif, skb); | |
1381 | return; | |
1382 | } | |
1383 | ||
e3ec7017 PKS |
1384 | if (!ether_addr_equal(vif->bss_conf.bssid, bssid)) |
1385 | return; | |
1386 | ||
1387 | if (ieee80211_is_beacon(hdr->frame_control)) | |
1388 | pkt_stat->beacon_nr++; | |
1389 | ||
1390 | if (!ether_addr_equal(vif->addr, hdr->addr1)) | |
1391 | return; | |
1392 | ||
1393 | if (desc_info->data_rate < RTW89_HW_RATE_NR) | |
1394 | pkt_stat->rx_rate_cnt[desc_info->data_rate]++; | |
1395 | ||
1396 | rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, false); | |
1397 | } | |
1398 | ||
1399 | static void rtw89_core_rx_stats(struct rtw89_dev *rtwdev, | |
1400 | struct rtw89_rx_phy_ppdu *phy_ppdu, | |
1401 | struct rtw89_rx_desc_info *desc_info, | |
1402 | struct sk_buff *skb) | |
1403 | { | |
1404 | struct rtw89_vif_rx_stats_iter_data iter_data; | |
1405 | ||
1406 | rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, false); | |
1407 | ||
1408 | iter_data.rtwdev = rtwdev; | |
1409 | iter_data.phy_ppdu = phy_ppdu; | |
1410 | iter_data.desc_info = desc_info; | |
1411 | iter_data.skb = skb; | |
1412 | iter_data.bssid = get_hdr_bssid((struct ieee80211_hdr *)skb->data); | |
1413 | rtw89_iterate_vifs_bh(rtwdev, rtw89_vif_rx_stats_iter, &iter_data); | |
1414 | } | |
1415 | ||
eb4e52b3 PHH |
1416 | static void rtw89_correct_cck_chan(struct rtw89_dev *rtwdev, |
1417 | struct ieee80211_rx_status *status) | |
1418 | { | |
cbb145b9 ZZY |
1419 | const struct rtw89_chan_rcd *rcd = |
1420 | rtw89_chan_rcd_get(rtwdev, RTW89_SUB_ENTITY_0); | |
1421 | u16 chan = rcd->prev_primary_channel; | |
1422 | u8 band = rcd->prev_band_type == RTW89_BAND_2G ? | |
1423 | NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; | |
eb4e52b3 PHH |
1424 | |
1425 | if (status->band != NL80211_BAND_2GHZ && | |
1426 | status->encoding == RX_ENC_LEGACY && | |
1427 | status->rate_idx < RTW89_HW_RATE_OFDM6) { | |
1428 | status->freq = ieee80211_channel_to_frequency(chan, band); | |
1429 | status->band = band; | |
1430 | } | |
1431 | } | |
1432 | ||
1433 | static void rtw89_core_hw_to_sband_rate(struct ieee80211_rx_status *rx_status) | |
1434 | { | |
1435 | if (rx_status->band == NL80211_BAND_2GHZ || | |
1436 | rx_status->encoding != RX_ENC_LEGACY) | |
1437 | return; | |
89590777 PHH |
1438 | |
1439 | /* Some control frames' freq(ACKs in this case) are reported wrong due | |
1440 | * to FW notify timing, set to lowest rate to prevent overflow. | |
1441 | */ | |
1442 | if (rx_status->rate_idx < RTW89_HW_RATE_OFDM6) { | |
1443 | rx_status->rate_idx = 0; | |
1444 | return; | |
1445 | } | |
1446 | ||
eb4e52b3 PHH |
1447 | /* No 4 CCK rates for non-2G */ |
1448 | rx_status->rate_idx -= 4; | |
1449 | } | |
1450 | ||
c1ea345d PKS |
1451 | static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev, |
1452 | struct rtw89_rx_phy_ppdu *phy_ppdu, | |
1453 | struct rtw89_rx_desc_info *desc_info, | |
1454 | struct sk_buff *skb_ppdu, | |
1455 | struct ieee80211_rx_status *rx_status) | |
1456 | { | |
c4756d5d PKS |
1457 | struct napi_struct *napi = &rtwdev->napi; |
1458 | ||
1459 | /* In low power mode, napi isn't scheduled. Receive it to netif. */ | |
1460 | if (unlikely(!test_bit(NAPI_STATE_SCHED, &napi->state))) | |
1461 | napi = NULL; | |
1462 | ||
c1ea345d PKS |
1463 | rtw89_core_hw_to_sband_rate(rx_status); |
1464 | rtw89_core_rx_stats(rtwdev, phy_ppdu, desc_info, skb_ppdu); | |
c83dcd05 PKS |
1465 | /* In low power mode, it does RX in thread context. */ |
1466 | local_bh_disable(); | |
c4756d5d | 1467 | ieee80211_rx_napi(rtwdev->hw, NULL, skb_ppdu, napi); |
c83dcd05 | 1468 | local_bh_enable(); |
c1ea345d PKS |
1469 | rtwdev->napi_budget_countdown--; |
1470 | } | |
1471 | ||
e3ec7017 PKS |
1472 | static void rtw89_core_rx_pending_skb(struct rtw89_dev *rtwdev, |
1473 | struct rtw89_rx_phy_ppdu *phy_ppdu, | |
1474 | struct rtw89_rx_desc_info *desc_info, | |
1475 | struct sk_buff *skb) | |
1476 | { | |
1477 | u8 band = desc_info->bb_sel ? RTW89_PHY_1 : RTW89_PHY_0; | |
1478 | int curr = rtwdev->ppdu_sts.curr_rx_ppdu_cnt[band]; | |
1479 | struct sk_buff *skb_ppdu = NULL, *tmp; | |
1480 | struct ieee80211_rx_status *rx_status; | |
1481 | ||
1482 | if (curr > RTW89_MAX_PPDU_CNT) | |
1483 | return; | |
1484 | ||
1485 | skb_queue_walk_safe(&rtwdev->ppdu_sts.rx_queue[band], skb_ppdu, tmp) { | |
1486 | skb_unlink(skb_ppdu, &rtwdev->ppdu_sts.rx_queue[band]); | |
1487 | rx_status = IEEE80211_SKB_RXCB(skb_ppdu); | |
1488 | if (rtw89_core_rx_ppdu_match(rtwdev, desc_info, rx_status)) | |
1489 | rtw89_chip_query_ppdu(rtwdev, phy_ppdu, rx_status); | |
eb4e52b3 | 1490 | rtw89_correct_cck_chan(rtwdev, rx_status); |
c1ea345d | 1491 | rtw89_core_rx_to_mac80211(rtwdev, phy_ppdu, desc_info, skb_ppdu, rx_status); |
e3ec7017 PKS |
1492 | } |
1493 | } | |
1494 | ||
1495 | static void rtw89_core_rx_process_ppdu_sts(struct rtw89_dev *rtwdev, | |
1496 | struct rtw89_rx_desc_info *desc_info, | |
1497 | struct sk_buff *skb) | |
1498 | { | |
1499 | struct rtw89_rx_phy_ppdu phy_ppdu = {.buf = skb->data, .valid = false, | |
1500 | .len = skb->len, | |
1501 | .to_self = desc_info->addr1_match, | |
eb4e52b3 | 1502 | .rate = desc_info->data_rate, |
e3ec7017 PKS |
1503 | .mac_id = desc_info->mac_id}; |
1504 | int ret; | |
1505 | ||
1506 | if (desc_info->mac_info_valid) | |
1507 | rtw89_core_rx_process_mac_ppdu(rtwdev, skb, &phy_ppdu); | |
1508 | ret = rtw89_core_rx_process_phy_ppdu(rtwdev, &phy_ppdu); | |
1509 | if (ret) | |
1510 | rtw89_debug(rtwdev, RTW89_DBG_TXRX, "process ppdu failed\n"); | |
1511 | ||
1512 | rtw89_core_rx_process_phy_sts(rtwdev, &phy_ppdu); | |
1513 | rtw89_core_rx_pending_skb(rtwdev, &phy_ppdu, desc_info, skb); | |
1514 | dev_kfree_skb_any(skb); | |
1515 | } | |
1516 | ||
1517 | static void rtw89_core_rx_process_report(struct rtw89_dev *rtwdev, | |
1518 | struct rtw89_rx_desc_info *desc_info, | |
1519 | struct sk_buff *skb) | |
1520 | { | |
1521 | switch (desc_info->pkt_type) { | |
1522 | case RTW89_CORE_RX_TYPE_C2H: | |
1523 | rtw89_fw_c2h_irqsafe(rtwdev, skb); | |
1524 | break; | |
1525 | case RTW89_CORE_RX_TYPE_PPDU_STAT: | |
1526 | rtw89_core_rx_process_ppdu_sts(rtwdev, desc_info, skb); | |
1527 | break; | |
1528 | default: | |
1529 | rtw89_debug(rtwdev, RTW89_DBG_TXRX, "unhandled pkt_type=%d\n", | |
1530 | desc_info->pkt_type); | |
1531 | dev_kfree_skb_any(skb); | |
1532 | break; | |
1533 | } | |
1534 | } | |
1535 | ||
1536 | void rtw89_core_query_rxdesc(struct rtw89_dev *rtwdev, | |
1537 | struct rtw89_rx_desc_info *desc_info, | |
1538 | u8 *data, u32 data_offset) | |
1539 | { | |
84fc6999 | 1540 | const struct rtw89_chip_info *chip = rtwdev->chip; |
e3ec7017 PKS |
1541 | struct rtw89_rxdesc_short *rxd_s; |
1542 | struct rtw89_rxdesc_long *rxd_l; | |
1543 | u8 shift_len, drv_info_len; | |
1544 | ||
1545 | rxd_s = (struct rtw89_rxdesc_short *)(data + data_offset); | |
1546 | desc_info->pkt_size = RTW89_GET_RXWD_PKT_SIZE(rxd_s); | |
1547 | desc_info->drv_info_size = RTW89_GET_RXWD_DRV_INFO_SIZE(rxd_s); | |
1548 | desc_info->long_rxdesc = RTW89_GET_RXWD_LONG_RXD(rxd_s); | |
1549 | desc_info->pkt_type = RTW89_GET_RXWD_RPKT_TYPE(rxd_s); | |
1550 | desc_info->mac_info_valid = RTW89_GET_RXWD_MAC_INFO_VALID(rxd_s); | |
84fc6999 PKS |
1551 | if (chip->chip_id == RTL8852C) |
1552 | desc_info->bw = RTW89_GET_RXWD_BW_V1(rxd_s); | |
1553 | else | |
1554 | desc_info->bw = RTW89_GET_RXWD_BW(rxd_s); | |
e3ec7017 PKS |
1555 | desc_info->data_rate = RTW89_GET_RXWD_DATA_RATE(rxd_s); |
1556 | desc_info->gi_ltf = RTW89_GET_RXWD_GI_LTF(rxd_s); | |
1557 | desc_info->user_id = RTW89_GET_RXWD_USER_ID(rxd_s); | |
1558 | desc_info->sr_en = RTW89_GET_RXWD_SR_EN(rxd_s); | |
1559 | desc_info->ppdu_cnt = RTW89_GET_RXWD_PPDU_CNT(rxd_s); | |
1560 | desc_info->ppdu_type = RTW89_GET_RXWD_PPDU_TYPE(rxd_s); | |
1561 | desc_info->free_run_cnt = RTW89_GET_RXWD_FREE_RUN_CNT(rxd_s); | |
1562 | desc_info->icv_err = RTW89_GET_RXWD_ICV_ERR(rxd_s); | |
1563 | desc_info->crc32_err = RTW89_GET_RXWD_CRC32_ERR(rxd_s); | |
1564 | desc_info->hw_dec = RTW89_GET_RXWD_HW_DEC(rxd_s); | |
1565 | desc_info->sw_dec = RTW89_GET_RXWD_SW_DEC(rxd_s); | |
1566 | desc_info->addr1_match = RTW89_GET_RXWD_A1_MATCH(rxd_s); | |
1567 | ||
1568 | shift_len = desc_info->shift << 1; /* 2-byte unit */ | |
1569 | drv_info_len = desc_info->drv_info_size << 3; /* 8-byte unit */ | |
1570 | desc_info->offset = data_offset + shift_len + drv_info_len; | |
1571 | desc_info->ready = true; | |
1572 | ||
1573 | if (!desc_info->long_rxdesc) | |
1574 | return; | |
1575 | ||
1576 | rxd_l = (struct rtw89_rxdesc_long *)(data + data_offset); | |
1577 | desc_info->frame_type = RTW89_GET_RXWD_TYPE(rxd_l); | |
1578 | desc_info->addr_cam_valid = RTW89_GET_RXWD_ADDR_CAM_VLD(rxd_l); | |
1579 | desc_info->addr_cam_id = RTW89_GET_RXWD_ADDR_CAM_ID(rxd_l); | |
1580 | desc_info->sec_cam_id = RTW89_GET_RXWD_SEC_CAM_ID(rxd_l); | |
1581 | desc_info->mac_id = RTW89_GET_RXWD_MAC_ID(rxd_l); | |
1582 | desc_info->rx_pl_id = RTW89_GET_RXWD_RX_PL_ID(rxd_l); | |
1583 | } | |
1584 | EXPORT_SYMBOL(rtw89_core_query_rxdesc); | |
1585 | ||
1586 | struct rtw89_core_iter_rx_status { | |
1587 | struct rtw89_dev *rtwdev; | |
1588 | struct ieee80211_rx_status *rx_status; | |
1589 | struct rtw89_rx_desc_info *desc_info; | |
1590 | u8 mac_id; | |
1591 | }; | |
1592 | ||
1593 | static | |
1594 | void rtw89_core_stats_sta_rx_status_iter(void *data, struct ieee80211_sta *sta) | |
1595 | { | |
1596 | struct rtw89_core_iter_rx_status *iter_data = | |
1597 | (struct rtw89_core_iter_rx_status *)data; | |
1598 | struct ieee80211_rx_status *rx_status = iter_data->rx_status; | |
1599 | struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; | |
1600 | struct rtw89_rx_desc_info *desc_info = iter_data->desc_info; | |
1601 | u8 mac_id = iter_data->mac_id; | |
1602 | ||
1603 | if (mac_id != rtwsta->mac_id) | |
1604 | return; | |
1605 | ||
1606 | rtwsta->rx_status = *rx_status; | |
1607 | rtwsta->rx_hw_rate = desc_info->data_rate; | |
1608 | } | |
1609 | ||
1610 | static void rtw89_core_stats_sta_rx_status(struct rtw89_dev *rtwdev, | |
1611 | struct rtw89_rx_desc_info *desc_info, | |
1612 | struct ieee80211_rx_status *rx_status) | |
1613 | { | |
1614 | struct rtw89_core_iter_rx_status iter_data; | |
1615 | ||
1616 | if (!desc_info->addr1_match || !desc_info->long_rxdesc) | |
1617 | return; | |
1618 | ||
1619 | if (desc_info->frame_type != RTW89_RX_TYPE_DATA) | |
1620 | return; | |
1621 | ||
1622 | iter_data.rtwdev = rtwdev; | |
1623 | iter_data.rx_status = rx_status; | |
1624 | iter_data.desc_info = desc_info; | |
1625 | iter_data.mac_id = desc_info->mac_id; | |
1626 | ieee80211_iterate_stations_atomic(rtwdev->hw, | |
1627 | rtw89_core_stats_sta_rx_status_iter, | |
1628 | &iter_data); | |
1629 | } | |
1630 | ||
1631 | static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, | |
1632 | struct rtw89_rx_desc_info *desc_info, | |
1633 | struct ieee80211_rx_status *rx_status) | |
1634 | { | |
494399b2 ZZY |
1635 | const struct cfg80211_chan_def *chandef = |
1636 | rtw89_chandef_get(rtwdev, RTW89_SUB_ENTITY_0); | |
cbb145b9 | 1637 | const struct rtw89_chan *cur = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); |
e3ec7017 PKS |
1638 | u16 data_rate; |
1639 | u8 data_rate_mode; | |
1640 | ||
1641 | /* currently using single PHY */ | |
494399b2 ZZY |
1642 | rx_status->freq = chandef->chan->center_freq; |
1643 | rx_status->band = chandef->chan->band; | |
e3ec7017 | 1644 | |
11fe4ccd ZZY |
1645 | if (rtwdev->scanning && |
1646 | RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { | |
cbb145b9 ZZY |
1647 | u8 chan = cur->primary_channel; |
1648 | u8 band = cur->band_type; | |
a06d2dd7 ZZY |
1649 | enum nl80211_band nl_band; |
1650 | ||
1651 | nl_band = rtw89_hw_to_nl80211_band(band); | |
1652 | rx_status->freq = ieee80211_channel_to_frequency(chan, nl_band); | |
1653 | rx_status->band = nl_band; | |
89590777 PHH |
1654 | } |
1655 | ||
e3ec7017 PKS |
1656 | if (desc_info->icv_err || desc_info->crc32_err) |
1657 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | |
1658 | ||
1659 | if (desc_info->hw_dec && | |
1660 | !(desc_info->sw_dec || desc_info->icv_err)) | |
1661 | rx_status->flag |= RX_FLAG_DECRYPTED; | |
1662 | ||
167044af | 1663 | rx_status->bw = rtw89_hw_to_rate_info_bw(desc_info->bw); |
e3ec7017 PKS |
1664 | |
1665 | data_rate = desc_info->data_rate; | |
1666 | data_rate_mode = GET_DATA_RATE_MODE(data_rate); | |
1667 | if (data_rate_mode == DATA_RATE_MODE_NON_HT) { | |
1668 | rx_status->encoding = RX_ENC_LEGACY; | |
1669 | rx_status->rate_idx = GET_DATA_RATE_NOT_HT_IDX(data_rate); | |
eb4e52b3 | 1670 | /* convert rate_idx after we get the correct band */ |
e3ec7017 PKS |
1671 | } else if (data_rate_mode == DATA_RATE_MODE_HT) { |
1672 | rx_status->encoding = RX_ENC_HT; | |
1673 | rx_status->rate_idx = GET_DATA_RATE_HT_IDX(data_rate); | |
1674 | if (desc_info->gi_ltf) | |
1675 | rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; | |
1676 | } else if (data_rate_mode == DATA_RATE_MODE_VHT) { | |
1677 | rx_status->encoding = RX_ENC_VHT; | |
1678 | rx_status->rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); | |
1679 | rx_status->nss = GET_DATA_RATE_NSS(data_rate) + 1; | |
1680 | if (desc_info->gi_ltf) | |
1681 | rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; | |
1682 | } else if (data_rate_mode == DATA_RATE_MODE_HE) { | |
1683 | rx_status->encoding = RX_ENC_HE; | |
1684 | rx_status->rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); | |
1685 | rx_status->nss = GET_DATA_RATE_NSS(data_rate) + 1; | |
1686 | } else { | |
1687 | rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode); | |
1688 | } | |
1689 | ||
1690 | /* he_gi is used to match ppdu, so we always fill it. */ | |
1691 | rx_status->he_gi = rtw89_rxdesc_to_nl_he_gi(rtwdev, desc_info, true); | |
1692 | rx_status->flag |= RX_FLAG_MACTIME_START; | |
1693 | rx_status->mactime = desc_info->free_run_cnt; | |
1694 | ||
1695 | rtw89_core_stats_sta_rx_status(rtwdev, desc_info, rx_status); | |
1696 | } | |
1697 | ||
1698 | static enum rtw89_ps_mode rtw89_update_ps_mode(struct rtw89_dev *rtwdev) | |
1699 | { | |
1700 | const struct rtw89_chip_info *chip = rtwdev->chip; | |
1701 | ||
1702 | if (rtw89_disable_ps_mode || !chip->ps_mode_supported) | |
1703 | return RTW89_PS_MODE_NONE; | |
1704 | ||
1705 | if (chip->ps_mode_supported & BIT(RTW89_PS_MODE_PWR_GATED)) | |
1706 | return RTW89_PS_MODE_PWR_GATED; | |
1707 | ||
1708 | if (chip->ps_mode_supported & BIT(RTW89_PS_MODE_CLK_GATED)) | |
1709 | return RTW89_PS_MODE_CLK_GATED; | |
1710 | ||
1711 | if (chip->ps_mode_supported & BIT(RTW89_PS_MODE_RFOFF)) | |
1712 | return RTW89_PS_MODE_RFOFF; | |
1713 | ||
1714 | return RTW89_PS_MODE_NONE; | |
1715 | } | |
1716 | ||
1717 | static void rtw89_core_flush_ppdu_rx_queue(struct rtw89_dev *rtwdev, | |
1718 | struct rtw89_rx_desc_info *desc_info) | |
1719 | { | |
1720 | struct rtw89_ppdu_sts_info *ppdu_sts = &rtwdev->ppdu_sts; | |
1721 | u8 band = desc_info->bb_sel ? RTW89_PHY_1 : RTW89_PHY_0; | |
eb4e52b3 | 1722 | struct ieee80211_rx_status *rx_status; |
e3ec7017 PKS |
1723 | struct sk_buff *skb_ppdu, *tmp; |
1724 | ||
1725 | skb_queue_walk_safe(&ppdu_sts->rx_queue[band], skb_ppdu, tmp) { | |
1726 | skb_unlink(skb_ppdu, &ppdu_sts->rx_queue[band]); | |
eb4e52b3 | 1727 | rx_status = IEEE80211_SKB_RXCB(skb_ppdu); |
c1ea345d | 1728 | rtw89_core_rx_to_mac80211(rtwdev, NULL, desc_info, skb_ppdu, rx_status); |
e3ec7017 PKS |
1729 | } |
1730 | } | |
1731 | ||
1732 | void rtw89_core_rx(struct rtw89_dev *rtwdev, | |
1733 | struct rtw89_rx_desc_info *desc_info, | |
1734 | struct sk_buff *skb) | |
1735 | { | |
1736 | struct ieee80211_rx_status *rx_status; | |
1737 | struct rtw89_ppdu_sts_info *ppdu_sts = &rtwdev->ppdu_sts; | |
1738 | u8 ppdu_cnt = desc_info->ppdu_cnt; | |
1739 | u8 band = desc_info->bb_sel ? RTW89_PHY_1 : RTW89_PHY_0; | |
1740 | ||
1741 | if (desc_info->pkt_type != RTW89_CORE_RX_TYPE_WIFI) { | |
1742 | rtw89_core_rx_process_report(rtwdev, desc_info, skb); | |
1743 | return; | |
1744 | } | |
1745 | ||
1746 | if (ppdu_sts->curr_rx_ppdu_cnt[band] != ppdu_cnt) { | |
1747 | rtw89_core_flush_ppdu_rx_queue(rtwdev, desc_info); | |
1748 | ppdu_sts->curr_rx_ppdu_cnt[band] = ppdu_cnt; | |
1749 | } | |
1750 | ||
1751 | rx_status = IEEE80211_SKB_RXCB(skb); | |
1752 | memset(rx_status, 0, sizeof(*rx_status)); | |
1753 | rtw89_core_update_rx_status(rtwdev, desc_info, rx_status); | |
1754 | if (desc_info->long_rxdesc && | |
c1ea345d | 1755 | BIT(desc_info->frame_type) & PPDU_FILTER_BITMAP) |
e3ec7017 | 1756 | skb_queue_tail(&ppdu_sts->rx_queue[band], skb); |
c1ea345d PKS |
1757 | else |
1758 | rtw89_core_rx_to_mac80211(rtwdev, NULL, desc_info, skb, rx_status); | |
e3ec7017 PKS |
1759 | } |
1760 | EXPORT_SYMBOL(rtw89_core_rx); | |
1761 | ||
1762 | void rtw89_core_napi_start(struct rtw89_dev *rtwdev) | |
1763 | { | |
1764 | if (test_and_set_bit(RTW89_FLAG_NAPI_RUNNING, rtwdev->flags)) | |
1765 | return; | |
1766 | ||
1767 | napi_enable(&rtwdev->napi); | |
1768 | } | |
1769 | EXPORT_SYMBOL(rtw89_core_napi_start); | |
1770 | ||
1771 | void rtw89_core_napi_stop(struct rtw89_dev *rtwdev) | |
1772 | { | |
1773 | if (!test_and_clear_bit(RTW89_FLAG_NAPI_RUNNING, rtwdev->flags)) | |
1774 | return; | |
1775 | ||
1776 | napi_synchronize(&rtwdev->napi); | |
1777 | napi_disable(&rtwdev->napi); | |
1778 | } | |
1779 | EXPORT_SYMBOL(rtw89_core_napi_stop); | |
1780 | ||
1781 | void rtw89_core_napi_init(struct rtw89_dev *rtwdev) | |
1782 | { | |
1783 | init_dummy_netdev(&rtwdev->netdev); | |
1784 | netif_napi_add(&rtwdev->netdev, &rtwdev->napi, | |
1785 | rtwdev->hci.ops->napi_poll, NAPI_POLL_WEIGHT); | |
1786 | } | |
1787 | EXPORT_SYMBOL(rtw89_core_napi_init); | |
1788 | ||
1789 | void rtw89_core_napi_deinit(struct rtw89_dev *rtwdev) | |
1790 | { | |
1791 | rtw89_core_napi_stop(rtwdev); | |
1792 | netif_napi_del(&rtwdev->napi); | |
1793 | } | |
1794 | EXPORT_SYMBOL(rtw89_core_napi_deinit); | |
1795 | ||
1796 | static void rtw89_core_ba_work(struct work_struct *work) | |
1797 | { | |
1798 | struct rtw89_dev *rtwdev = | |
1799 | container_of(work, struct rtw89_dev, ba_work); | |
1800 | struct rtw89_txq *rtwtxq, *tmp; | |
1801 | int ret; | |
1802 | ||
1803 | spin_lock_bh(&rtwdev->ba_lock); | |
1804 | list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) { | |
1805 | struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); | |
1806 | struct ieee80211_sta *sta = txq->sta; | |
5d44f067 | 1807 | struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; |
e3ec7017 PKS |
1808 | u8 tid = txq->tid; |
1809 | ||
1810 | if (!sta) { | |
1811 | rtw89_warn(rtwdev, "cannot start BA without sta\n"); | |
1812 | goto skip_ba_work; | |
1813 | } | |
1814 | ||
1815 | if (rtwsta->disassoc) { | |
1816 | rtw89_debug(rtwdev, RTW89_DBG_TXRX, | |
1817 | "cannot start BA with disassoc sta\n"); | |
1818 | goto skip_ba_work; | |
1819 | } | |
1820 | ||
1821 | ret = ieee80211_start_tx_ba_session(sta, tid, 0); | |
1822 | if (ret) { | |
1823 | rtw89_debug(rtwdev, RTW89_DBG_TXRX, | |
1824 | "failed to setup BA session for %pM:%2d: %d\n", | |
1825 | sta->addr, tid, ret); | |
1826 | if (ret == -EINVAL) | |
1827 | set_bit(RTW89_TXQ_F_BLOCK_BA, &rtwtxq->flags); | |
1828 | } | |
1829 | skip_ba_work: | |
1830 | list_del_init(&rtwtxq->list); | |
1831 | } | |
1832 | spin_unlock_bh(&rtwdev->ba_lock); | |
1833 | } | |
1834 | ||
1835 | static void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, | |
1836 | struct ieee80211_sta *sta) | |
1837 | { | |
1838 | struct rtw89_txq *rtwtxq, *tmp; | |
1839 | ||
1840 | spin_lock_bh(&rtwdev->ba_lock); | |
1841 | list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) { | |
1842 | struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); | |
1843 | ||
1844 | if (sta == txq->sta) | |
1845 | list_del_init(&rtwtxq->list); | |
1846 | } | |
1847 | spin_unlock_bh(&rtwdev->ba_lock); | |
1848 | } | |
1849 | ||
679955d5 KCC |
1850 | static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, |
1851 | struct ieee80211_sta *sta) | |
1852 | { | |
1853 | struct rtw89_txq *rtwtxq, *tmp; | |
1854 | ||
1855 | spin_lock_bh(&rtwdev->ba_lock); | |
1856 | list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->forbid_ba_list, list) { | |
1857 | struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); | |
1858 | ||
1859 | if (sta == txq->sta) { | |
1860 | clear_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags); | |
1861 | list_del_init(&rtwtxq->list); | |
1862 | } | |
1863 | } | |
1864 | spin_unlock_bh(&rtwdev->ba_lock); | |
1865 | } | |
1866 | ||
1867 | static void rtw89_core_stop_tx_ba_session(struct rtw89_dev *rtwdev, | |
1868 | struct rtw89_txq *rtwtxq) | |
1869 | { | |
1870 | struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); | |
1871 | struct ieee80211_sta *sta = txq->sta; | |
1872 | struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); | |
1873 | ||
1874 | if (unlikely(!rtwsta) || unlikely(rtwsta->disassoc)) | |
1875 | return; | |
1876 | ||
1877 | if (!test_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags) || | |
1878 | test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags)) | |
1879 | return; | |
1880 | ||
1881 | spin_lock_bh(&rtwdev->ba_lock); | |
1882 | if (!list_empty(&rtwtxq->list)) { | |
1883 | list_del_init(&rtwtxq->list); | |
1884 | goto out; | |
1885 | } | |
1886 | ||
1887 | set_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags); | |
1888 | ||
1889 | list_add_tail(&rtwtxq->list, &rtwdev->forbid_ba_list); | |
1890 | ieee80211_stop_tx_ba_session(sta, txq->tid); | |
1891 | cancel_delayed_work(&rtwdev->forbid_ba_work); | |
1892 | ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->forbid_ba_work, | |
1893 | RTW89_FORBID_BA_TIMER); | |
1894 | ||
1895 | out: | |
1896 | spin_unlock_bh(&rtwdev->ba_lock); | |
1897 | } | |
1898 | ||
e3ec7017 PKS |
1899 | static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, |
1900 | struct rtw89_txq *rtwtxq, | |
1901 | struct sk_buff *skb) | |
1902 | { | |
1903 | struct ieee80211_hw *hw = rtwdev->hw; | |
1904 | struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); | |
1905 | struct ieee80211_sta *sta = txq->sta; | |
5d44f067 | 1906 | struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; |
e3ec7017 | 1907 | |
679955d5 KCC |
1908 | if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))) { |
1909 | rtw89_core_stop_tx_ba_session(rtwdev, rtwtxq); | |
e3ec7017 | 1910 | return; |
679955d5 | 1911 | } |
e3ec7017 | 1912 | |
679955d5 | 1913 | if (unlikely(!sta)) |
e3ec7017 PKS |
1914 | return; |
1915 | ||
679955d5 | 1916 | if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags)) |
e3ec7017 PKS |
1917 | return; |
1918 | ||
1919 | if (unlikely(test_bit(RTW89_TXQ_F_BLOCK_BA, &rtwtxq->flags))) | |
1920 | return; | |
1921 | ||
1922 | if (test_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags)) { | |
1923 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_AMPDU; | |
1924 | return; | |
1925 | } | |
1926 | ||
1927 | spin_lock_bh(&rtwdev->ba_lock); | |
1928 | if (!rtwsta->disassoc && list_empty(&rtwtxq->list)) { | |
1929 | list_add_tail(&rtwtxq->list, &rtwdev->ba_list); | |
1930 | ieee80211_queue_work(hw, &rtwdev->ba_work); | |
1931 | } | |
1932 | spin_unlock_bh(&rtwdev->ba_lock); | |
1933 | } | |
1934 | ||
1935 | static void rtw89_core_txq_push(struct rtw89_dev *rtwdev, | |
1936 | struct rtw89_txq *rtwtxq, | |
1937 | unsigned long frame_cnt, | |
1938 | unsigned long byte_cnt) | |
1939 | { | |
1940 | struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); | |
1941 | struct ieee80211_vif *vif = txq->vif; | |
1942 | struct ieee80211_sta *sta = txq->sta; | |
1943 | struct sk_buff *skb; | |
1944 | unsigned long i; | |
1945 | int ret; | |
1946 | ||
f3d825a3 | 1947 | rcu_read_lock(); |
e3ec7017 PKS |
1948 | for (i = 0; i < frame_cnt; i++) { |
1949 | skb = ieee80211_tx_dequeue_ni(rtwdev->hw, txq); | |
1950 | if (!skb) { | |
1951 | rtw89_debug(rtwdev, RTW89_DBG_TXRX, "dequeue a NULL skb\n"); | |
f3d825a3 | 1952 | goto out; |
e3ec7017 PKS |
1953 | } |
1954 | rtw89_core_txq_check_agg(rtwdev, rtwtxq, skb); | |
1955 | ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, NULL); | |
1956 | if (ret) { | |
1957 | rtw89_err(rtwdev, "failed to push txq: %d\n", ret); | |
1958 | ieee80211_free_txskb(rtwdev->hw, skb); | |
1959 | break; | |
1960 | } | |
1961 | } | |
f3d825a3 JK |
1962 | out: |
1963 | rcu_read_unlock(); | |
e3ec7017 PKS |
1964 | } |
1965 | ||
1966 | static u32 rtw89_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, u8 tid) | |
1967 | { | |
1968 | u8 qsel, ch_dma; | |
1969 | ||
1970 | qsel = rtw89_core_get_qsel(rtwdev, tid); | |
1971 | ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel); | |
1972 | ||
1973 | return rtw89_hci_check_and_reclaim_tx_resource(rtwdev, ch_dma); | |
1974 | } | |
1975 | ||
1976 | static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev, | |
1977 | struct ieee80211_txq *txq, | |
1978 | unsigned long *frame_cnt, | |
1979 | bool *sched_txq, bool *reinvoke) | |
1980 | { | |
1981 | struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; | |
1982 | struct ieee80211_sta *sta = txq->sta; | |
5d44f067 | 1983 | struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; |
e3ec7017 PKS |
1984 | |
1985 | if (!sta || rtwsta->max_agg_wait <= 0) | |
1986 | return false; | |
1987 | ||
1988 | if (rtwdev->stats.tx_tfc_lv <= RTW89_TFC_MID) | |
1989 | return false; | |
1990 | ||
1991 | if (*frame_cnt > 1) { | |
1992 | *frame_cnt -= 1; | |
1993 | *sched_txq = true; | |
1994 | *reinvoke = true; | |
1995 | rtwtxq->wait_cnt = 1; | |
1996 | return false; | |
1997 | } | |
1998 | ||
1999 | if (*frame_cnt == 1 && rtwtxq->wait_cnt < rtwsta->max_agg_wait) { | |
2000 | *reinvoke = true; | |
2001 | rtwtxq->wait_cnt++; | |
2002 | return true; | |
2003 | } | |
2004 | ||
2005 | rtwtxq->wait_cnt = 0; | |
2006 | return false; | |
2007 | } | |
2008 | ||
2009 | static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinvoke) | |
2010 | { | |
2011 | struct ieee80211_hw *hw = rtwdev->hw; | |
2012 | struct ieee80211_txq *txq; | |
2013 | struct rtw89_txq *rtwtxq; | |
2014 | unsigned long frame_cnt; | |
2015 | unsigned long byte_cnt; | |
2016 | u32 tx_resource; | |
2017 | bool sched_txq; | |
2018 | ||
2019 | ieee80211_txq_schedule_start(hw, ac); | |
2020 | while ((txq = ieee80211_next_txq(hw, ac))) { | |
2021 | rtwtxq = (struct rtw89_txq *)txq->drv_priv; | |
2022 | tx_resource = rtw89_check_and_reclaim_tx_resource(rtwdev, txq->tid); | |
2023 | sched_txq = false; | |
2024 | ||
2025 | ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt); | |
2026 | if (rtw89_core_txq_agg_wait(rtwdev, txq, &frame_cnt, &sched_txq, reinvoke)) { | |
2027 | ieee80211_return_txq(hw, txq, true); | |
2028 | continue; | |
2029 | } | |
2030 | frame_cnt = min_t(unsigned long, frame_cnt, tx_resource); | |
2031 | rtw89_core_txq_push(rtwdev, rtwtxq, frame_cnt, byte_cnt); | |
2032 | ieee80211_return_txq(hw, txq, sched_txq); | |
2033 | if (frame_cnt != 0) | |
2034 | rtw89_core_tx_kick_off(rtwdev, rtw89_core_get_qsel(rtwdev, txq->tid)); | |
29363fb6 KCC |
2035 | |
2036 | /* bound of tx_resource could get stuck due to burst traffic */ | |
2037 | if (frame_cnt == tx_resource) | |
2038 | *reinvoke = true; | |
e3ec7017 PKS |
2039 | } |
2040 | ieee80211_txq_schedule_end(hw, ac); | |
2041 | } | |
2042 | ||
89590777 PHH |
2043 | static void rtw89_ips_work(struct work_struct *work) |
2044 | { | |
2045 | struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, | |
2046 | ips_work); | |
89590777 | 2047 | mutex_lock(&rtwdev->mutex); |
ee20d538 PHH |
2048 | if (rtwdev->hw->conf.flags & IEEE80211_CONF_IDLE) |
2049 | rtw89_enter_ips(rtwdev); | |
89590777 PHH |
2050 | mutex_unlock(&rtwdev->mutex); |
2051 | } | |
2052 | ||
e3ec7017 PKS |
2053 | static void rtw89_core_txq_work(struct work_struct *w) |
2054 | { | |
2055 | struct rtw89_dev *rtwdev = container_of(w, struct rtw89_dev, txq_work); | |
2056 | bool reinvoke = false; | |
2057 | u8 ac; | |
2058 | ||
2059 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | |
2060 | rtw89_core_txq_schedule(rtwdev, ac, &reinvoke); | |
2061 | ||
2062 | if (reinvoke) { | |
2063 | /* reinvoke to process the last frame */ | |
2064 | mod_delayed_work(rtwdev->txq_wq, &rtwdev->txq_reinvoke_work, 1); | |
2065 | } | |
2066 | } | |
2067 | ||
2068 | static void rtw89_core_txq_reinvoke_work(struct work_struct *w) | |
2069 | { | |
2070 | struct rtw89_dev *rtwdev = container_of(w, struct rtw89_dev, | |
2071 | txq_reinvoke_work.work); | |
2072 | ||
2073 | queue_work(rtwdev->txq_wq, &rtwdev->txq_work); | |
2074 | } | |
2075 | ||
679955d5 KCC |
2076 | static void rtw89_forbid_ba_work(struct work_struct *w) |
2077 | { | |
2078 | struct rtw89_dev *rtwdev = container_of(w, struct rtw89_dev, | |
2079 | forbid_ba_work.work); | |
2080 | struct rtw89_txq *rtwtxq, *tmp; | |
2081 | ||
2082 | spin_lock_bh(&rtwdev->ba_lock); | |
2083 | list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->forbid_ba_list, list) { | |
2084 | clear_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags); | |
2085 | list_del_init(&rtwtxq->list); | |
2086 | } | |
2087 | spin_unlock_bh(&rtwdev->ba_lock); | |
2088 | } | |
2089 | ||
e3ec7017 PKS |
2090 | static enum rtw89_tfc_lv rtw89_get_traffic_level(struct rtw89_dev *rtwdev, |
2091 | u32 throughput, u64 cnt) | |
2092 | { | |
2093 | if (cnt < 100) | |
2094 | return RTW89_TFC_IDLE; | |
2095 | if (throughput > 50) | |
2096 | return RTW89_TFC_HIGH; | |
2097 | if (throughput > 10) | |
2098 | return RTW89_TFC_MID; | |
2099 | if (throughput > 2) | |
2100 | return RTW89_TFC_LOW; | |
2101 | return RTW89_TFC_ULTRA_LOW; | |
2102 | } | |
2103 | ||
2104 | static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, | |
2105 | struct rtw89_traffic_stats *stats) | |
2106 | { | |
2107 | enum rtw89_tfc_lv tx_tfc_lv = stats->tx_tfc_lv; | |
2108 | enum rtw89_tfc_lv rx_tfc_lv = stats->rx_tfc_lv; | |
2109 | ||
2110 | stats->tx_throughput_raw = (u32)(stats->tx_unicast >> RTW89_TP_SHIFT); | |
2111 | stats->rx_throughput_raw = (u32)(stats->rx_unicast >> RTW89_TP_SHIFT); | |
2112 | ||
2113 | ewma_tp_add(&stats->tx_ewma_tp, stats->tx_throughput_raw); | |
2114 | ewma_tp_add(&stats->rx_ewma_tp, stats->rx_throughput_raw); | |
2115 | ||
2116 | stats->tx_throughput = ewma_tp_read(&stats->tx_ewma_tp); | |
2117 | stats->rx_throughput = ewma_tp_read(&stats->rx_ewma_tp); | |
2118 | stats->tx_tfc_lv = rtw89_get_traffic_level(rtwdev, stats->tx_throughput, | |
2119 | stats->tx_cnt); | |
2120 | stats->rx_tfc_lv = rtw89_get_traffic_level(rtwdev, stats->rx_throughput, | |
2121 | stats->rx_cnt); | |
2122 | stats->tx_avg_len = stats->tx_cnt ? | |
2123 | DIV_ROUND_DOWN_ULL(stats->tx_unicast, stats->tx_cnt) : 0; | |
2124 | stats->rx_avg_len = stats->rx_cnt ? | |
2125 | DIV_ROUND_DOWN_ULL(stats->rx_unicast, stats->rx_cnt) : 0; | |
2126 | ||
2127 | stats->tx_unicast = 0; | |
2128 | stats->rx_unicast = 0; | |
2129 | stats->tx_cnt = 0; | |
2130 | stats->rx_cnt = 0; | |
5165f168 PHH |
2131 | stats->rx_tf_periodic = stats->rx_tf_acc; |
2132 | stats->rx_tf_acc = 0; | |
e3ec7017 PKS |
2133 | |
2134 | if (tx_tfc_lv != stats->tx_tfc_lv || rx_tfc_lv != stats->rx_tfc_lv) | |
2135 | return true; | |
2136 | ||
2137 | return false; | |
2138 | } | |
2139 | ||
2140 | static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) | |
2141 | { | |
2142 | struct rtw89_vif *rtwvif; | |
2143 | bool tfc_changed; | |
2144 | ||
2145 | tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats); | |
2146 | rtw89_for_each_rtwvif(rtwdev, rtwvif) | |
2147 | rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats); | |
2148 | ||
2149 | return tfc_changed; | |
2150 | } | |
2151 | ||
2152 | static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) | |
2153 | { | |
2154 | if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION) | |
2155 | return; | |
2156 | ||
2157 | if (rtwvif->stats.tx_tfc_lv == RTW89_TFC_IDLE && | |
2158 | rtwvif->stats.rx_tfc_lv == RTW89_TFC_IDLE) | |
2159 | rtw89_enter_lps(rtwdev, rtwvif->mac_id); | |
2160 | } | |
2161 | ||
2162 | static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) | |
2163 | { | |
2164 | struct rtw89_vif *rtwvif; | |
2165 | ||
2166 | rtw89_for_each_rtwvif(rtwdev, rtwvif) | |
2167 | rtw89_vif_enter_lps(rtwdev, rtwvif); | |
2168 | } | |
2169 | ||
2170 | void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev, | |
2171 | struct rtw89_traffic_stats *stats) | |
2172 | { | |
2173 | stats->tx_unicast = 0; | |
2174 | stats->rx_unicast = 0; | |
2175 | stats->tx_cnt = 0; | |
2176 | stats->rx_cnt = 0; | |
2177 | ewma_tp_init(&stats->tx_ewma_tp); | |
2178 | ewma_tp_init(&stats->rx_ewma_tp); | |
2179 | } | |
2180 | ||
2181 | static void rtw89_track_work(struct work_struct *work) | |
2182 | { | |
2183 | struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, | |
2184 | track_work.work); | |
2185 | bool tfc_changed; | |
2186 | ||
2187 | mutex_lock(&rtwdev->mutex); | |
2188 | ||
2189 | if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags)) | |
2190 | goto out; | |
2191 | ||
2192 | ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->track_work, | |
2193 | RTW89_TRACK_WORK_PERIOD); | |
2194 | ||
2195 | tfc_changed = rtw89_traffic_stats_track(rtwdev); | |
2196 | if (rtwdev->scanning) | |
2197 | goto out; | |
2198 | ||
2199 | rtw89_leave_lps(rtwdev); | |
2200 | ||
2201 | if (tfc_changed) { | |
2202 | rtw89_hci_recalc_int_mit(rtwdev); | |
2203 | rtw89_btc_ntfy_wl_sta(rtwdev); | |
2204 | } | |
2205 | rtw89_mac_bf_monitor_track(rtwdev); | |
2206 | rtw89_phy_stat_track(rtwdev); | |
2207 | rtw89_phy_env_monitor_track(rtwdev); | |
2208 | rtw89_phy_dig(rtwdev); | |
2209 | rtw89_chip_rfk_track(rtwdev); | |
2210 | rtw89_phy_ra_update(rtwdev); | |
2211 | rtw89_phy_cfo_track(rtwdev); | |
2212 | ||
2213 | if (rtwdev->lps_enabled && !rtwdev->btc.lps) | |
2214 | rtw89_enter_lps_track(rtwdev); | |
2215 | ||
2216 | out: | |
2217 | mutex_unlock(&rtwdev->mutex); | |
2218 | } | |
2219 | ||
2220 | u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size) | |
2221 | { | |
2222 | unsigned long bit; | |
2223 | ||
2224 | bit = find_first_zero_bit(addr, size); | |
2225 | if (bit < size) | |
2226 | set_bit(bit, addr); | |
2227 | ||
2228 | return bit; | |
2229 | } | |
2230 | ||
2231 | void rtw89_core_release_bit_map(unsigned long *addr, u8 bit) | |
2232 | { | |
2233 | clear_bit(bit, addr); | |
2234 | } | |
2235 | ||
2236 | void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits) | |
2237 | { | |
2238 | bitmap_zero(addr, nbits); | |
2239 | } | |
2240 | ||
3ffbb5a8 PKS |
2241 | int rtw89_core_acquire_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx) |
2242 | { | |
2243 | struct rtw89_ba_cam_entry *entry; | |
2244 | u8 idx; | |
2245 | ||
2246 | idx = rtw89_core_acquire_bit_map(rtwsta->ba_cam_map, RTW89_BA_CAM_NUM); | |
2247 | if (idx == RTW89_BA_CAM_NUM) { | |
2248 | /* allocate a static BA CAM to tid=0, so replace the existing | |
2249 | * one if BA CAM is full. Hardware will process the original tid | |
2250 | * automatically. | |
2251 | */ | |
2252 | if (tid != 0) | |
2253 | return -ENOSPC; | |
2254 | ||
2255 | idx = 0; | |
2256 | } | |
2257 | ||
2258 | entry = &rtwsta->ba_cam_entry[idx]; | |
2259 | entry->tid = tid; | |
2260 | *cam_idx = idx; | |
2261 | ||
2262 | return 0; | |
2263 | } | |
2264 | ||
2265 | int rtw89_core_release_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx) | |
2266 | { | |
2267 | struct rtw89_ba_cam_entry *entry; | |
2268 | int i; | |
2269 | ||
2270 | for (i = 0; i < RTW89_BA_CAM_NUM; i++) { | |
2271 | if (!test_bit(i, rtwsta->ba_cam_map)) | |
2272 | continue; | |
2273 | ||
2274 | entry = &rtwsta->ba_cam_entry[i]; | |
2275 | if (entry->tid != tid) | |
2276 | continue; | |
2277 | ||
2278 | rtw89_core_release_bit_map(rtwsta->ba_cam_map, i); | |
2279 | *cam_idx = i; | |
2280 | return 0; | |
2281 | } | |
2282 | ||
2283 | return -ENOENT; | |
2284 | } | |
2285 | ||
e3ec7017 PKS |
2286 | #define RTW89_TYPE_MAPPING(_type) \ |
2287 | case NL80211_IFTYPE_ ## _type: \ | |
2288 | rtwvif->wifi_role = RTW89_WIFI_ROLE_ ## _type; \ | |
2289 | break | |
2290 | void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) | |
2291 | { | |
2292 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
2293 | ||
2294 | switch (vif->type) { | |
2295 | RTW89_TYPE_MAPPING(ADHOC); | |
2296 | RTW89_TYPE_MAPPING(STATION); | |
2297 | RTW89_TYPE_MAPPING(AP); | |
2298 | RTW89_TYPE_MAPPING(MONITOR); | |
2299 | RTW89_TYPE_MAPPING(MESH_POINT); | |
2300 | default: | |
2301 | WARN_ON(1); | |
2302 | break; | |
2303 | } | |
2304 | ||
2305 | switch (vif->type) { | |
2306 | case NL80211_IFTYPE_AP: | |
2307 | case NL80211_IFTYPE_MESH_POINT: | |
2308 | rtwvif->net_type = RTW89_NET_TYPE_AP_MODE; | |
2309 | rtwvif->self_role = RTW89_SELF_ROLE_AP; | |
2310 | break; | |
2311 | case NL80211_IFTYPE_ADHOC: | |
2312 | rtwvif->net_type = RTW89_NET_TYPE_AD_HOC; | |
2313 | rtwvif->self_role = RTW89_SELF_ROLE_CLIENT; | |
2314 | break; | |
2315 | case NL80211_IFTYPE_STATION: | |
2316 | if (assoc) { | |
2317 | rtwvif->net_type = RTW89_NET_TYPE_INFRA; | |
2318 | rtwvif->trigger = vif->bss_conf.he_support; | |
2319 | } else { | |
2320 | rtwvif->net_type = RTW89_NET_TYPE_NO_LINK; | |
2321 | rtwvif->trigger = false; | |
2322 | } | |
2323 | rtwvif->self_role = RTW89_SELF_ROLE_CLIENT; | |
2324 | rtwvif->addr_cam.sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL; | |
2325 | break; | |
2326 | default: | |
2327 | WARN_ON(1); | |
2328 | break; | |
2329 | } | |
2330 | } | |
2331 | ||
2332 | int rtw89_core_sta_add(struct rtw89_dev *rtwdev, | |
2333 | struct ieee80211_vif *vif, | |
2334 | struct ieee80211_sta *sta) | |
2335 | { | |
2336 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
2337 | struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; | |
2338 | int i; | |
2339 | ||
2340 | rtwsta->rtwvif = rtwvif; | |
2341 | rtwsta->prev_rssi = 0; | |
2342 | ||
2343 | for (i = 0; i < ARRAY_SIZE(sta->txq); i++) | |
2344 | rtw89_core_txq_init(rtwdev, sta->txq[i]); | |
2345 | ||
2346 | ewma_rssi_init(&rtwsta->avg_rssi); | |
2347 | ||
7312100d | 2348 | if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { |
40822e07 PKS |
2349 | /* for station mode, assign the mac_id from itself */ |
2350 | rtwsta->mac_id = rtwvif->mac_id; | |
e3ec7017 PKS |
2351 | rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, |
2352 | BTC_ROLE_MSTS_STA_CONN_START); | |
2353 | rtw89_chip_rfk_channel(rtwdev); | |
7312100d | 2354 | } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { |
c7df64c1 PKS |
2355 | rtwsta->mac_id = rtw89_core_acquire_bit_map(rtwdev->mac_id_map, |
2356 | RTW89_MAX_MAC_ID_NUM); | |
e3ec7017 PKS |
2357 | } |
2358 | ||
2359 | return 0; | |
2360 | } | |
2361 | ||
2362 | int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, | |
2363 | struct ieee80211_vif *vif, | |
2364 | struct ieee80211_sta *sta) | |
2365 | { | |
2366 | struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; | |
2367 | ||
2368 | rtwdev->total_sta_assoc--; | |
2369 | rtwsta->disassoc = true; | |
2370 | ||
2371 | return 0; | |
2372 | } | |
2373 | ||
2374 | int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, | |
2375 | struct ieee80211_vif *vif, | |
2376 | struct ieee80211_sta *sta) | |
2377 | { | |
2378 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
40822e07 | 2379 | struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; |
e3ec7017 PKS |
2380 | int ret; |
2381 | ||
2382 | rtw89_mac_bf_monitor_calc(rtwdev, sta, true); | |
2383 | rtw89_mac_bf_disassoc(rtwdev, vif, sta); | |
2384 | rtw89_core_free_sta_pending_ba(rtwdev, sta); | |
679955d5 | 2385 | rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta); |
7312100d | 2386 | if (vif->type == NL80211_IFTYPE_AP || sta->tdls) |
1b73e77d | 2387 | rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam); |
39913cc8 PKS |
2388 | if (sta->tdls) |
2389 | rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam); | |
e3ec7017 | 2390 | |
7312100d | 2391 | if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) |
fd7ee4c8 | 2392 | rtw89_vif_type_mapping(vif, false); |
e3ec7017 PKS |
2393 | |
2394 | ret = rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, sta); | |
2395 | if (ret) { | |
2396 | rtw89_warn(rtwdev, "failed to send h2c cmac table\n"); | |
2397 | return ret; | |
2398 | } | |
2399 | ||
742c470b | 2400 | ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, true); |
e3ec7017 PKS |
2401 | if (ret) { |
2402 | rtw89_warn(rtwdev, "failed to send h2c join info\n"); | |
2403 | return ret; | |
2404 | } | |
2405 | ||
7312100d | 2406 | if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { |
1b73e77d PKS |
2407 | ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, RTW89_ROLE_REMOVE); |
2408 | if (ret) { | |
2409 | rtw89_warn(rtwdev, "failed to send h2c role info\n"); | |
2410 | return ret; | |
2411 | } | |
2412 | } | |
2413 | ||
e3ec7017 | 2414 | /* update cam aid mac_id net_type */ |
1b73e77d | 2415 | ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); |
e3ec7017 PKS |
2416 | if (ret) { |
2417 | rtw89_warn(rtwdev, "failed to send h2c cam\n"); | |
2418 | return ret; | |
2419 | } | |
2420 | ||
2421 | return ret; | |
2422 | } | |
2423 | ||
2424 | int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, | |
2425 | struct ieee80211_vif *vif, | |
2426 | struct ieee80211_sta *sta) | |
2427 | { | |
2428 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
2429 | struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; | |
39913cc8 | 2430 | struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta); |
e3ec7017 PKS |
2431 | int ret; |
2432 | ||
7312100d | 2433 | if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { |
1b73e77d PKS |
2434 | ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta->mac_id, false); |
2435 | if (ret) { | |
2436 | rtw89_warn(rtwdev, "failed to send h2c macid pause\n"); | |
2437 | return ret; | |
2438 | } | |
2439 | ||
2440 | ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, RTW89_ROLE_CREATE); | |
2441 | if (ret) { | |
2442 | rtw89_warn(rtwdev, "failed to send h2c role info\n"); | |
2443 | return ret; | |
2444 | } | |
2445 | ||
39913cc8 PKS |
2446 | if (sta->tdls) { |
2447 | ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, sta->addr); | |
2448 | if (ret) { | |
2449 | rtw89_warn(rtwdev, "failed to send h2c init bssid cam for TDLS\n"); | |
2450 | return ret; | |
2451 | } | |
2452 | } | |
2453 | ||
2454 | ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta->addr_cam, bssid_cam); | |
1b73e77d PKS |
2455 | if (ret) { |
2456 | rtw89_warn(rtwdev, "failed to send h2c init addr cam\n"); | |
2457 | return ret; | |
2458 | } | |
2459 | } | |
e3ec7017 PKS |
2460 | |
2461 | ret = rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, sta); | |
2462 | if (ret) { | |
2463 | rtw89_warn(rtwdev, "failed to send h2c cmac table\n"); | |
2464 | return ret; | |
2465 | } | |
2466 | ||
742c470b | 2467 | ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, false); |
e3ec7017 PKS |
2468 | if (ret) { |
2469 | rtw89_warn(rtwdev, "failed to send h2c join info\n"); | |
2470 | return ret; | |
2471 | } | |
2472 | ||
2473 | /* update cam aid mac_id net_type */ | |
40822e07 | 2474 | rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); |
e3ec7017 PKS |
2475 | if (ret) { |
2476 | rtw89_warn(rtwdev, "failed to send h2c cam\n"); | |
2477 | return ret; | |
2478 | } | |
2479 | ||
2480 | ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwsta->mac_id); | |
2481 | if (ret) { | |
2482 | rtw89_warn(rtwdev, "failed to send h2c general packet\n"); | |
2483 | return ret; | |
2484 | } | |
2485 | ||
2486 | rtwdev->total_sta_assoc++; | |
2487 | rtw89_phy_ra_assoc(rtwdev, sta); | |
2488 | rtw89_mac_bf_assoc(rtwdev, vif, sta); | |
2489 | rtw89_mac_bf_monitor_calc(rtwdev, sta, false); | |
2490 | ||
7312100d | 2491 | if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { |
e3ec7017 PKS |
2492 | rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, |
2493 | BTC_ROLE_MSTS_STA_CONN_END); | |
2494 | rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template); | |
2495 | } | |
2496 | ||
2497 | return ret; | |
2498 | } | |
2499 | ||
2500 | int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, | |
2501 | struct ieee80211_vif *vif, | |
2502 | struct ieee80211_sta *sta) | |
2503 | { | |
2504 | struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; | |
2505 | struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; | |
2506 | ||
7312100d | 2507 | if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) |
e3ec7017 PKS |
2508 | rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, |
2509 | BTC_ROLE_MSTS_STA_DIS_CONN); | |
7312100d | 2510 | else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) |
c7df64c1 | 2511 | rtw89_core_release_bit_map(rtwdev->mac_id_map, rtwsta->mac_id); |
e3ec7017 PKS |
2512 | |
2513 | return 0; | |
2514 | } | |
2515 | ||
2516 | static void rtw89_init_ht_cap(struct rtw89_dev *rtwdev, | |
2517 | struct ieee80211_sta_ht_cap *ht_cap) | |
2518 | { | |
2519 | static const __le16 highest[RF_PATH_MAX] = { | |
2520 | cpu_to_le16(150), cpu_to_le16(300), cpu_to_le16(450), cpu_to_le16(600), | |
2521 | }; | |
2522 | struct rtw89_hal *hal = &rtwdev->hal; | |
2523 | u8 nss = hal->rx_nss; | |
2524 | int i; | |
2525 | ||
2526 | ht_cap->ht_supported = true; | |
2527 | ht_cap->cap = 0; | |
2528 | ht_cap->cap |= IEEE80211_HT_CAP_SGI_20 | | |
2529 | IEEE80211_HT_CAP_MAX_AMSDU | | |
2530 | IEEE80211_HT_CAP_TX_STBC | | |
2531 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); | |
2532 | ht_cap->cap |= IEEE80211_HT_CAP_LDPC_CODING; | |
2533 | ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | |
2534 | IEEE80211_HT_CAP_DSSSCCK40 | | |
2535 | IEEE80211_HT_CAP_SGI_40; | |
2536 | ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | |
2537 | ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; | |
2538 | ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | |
2539 | for (i = 0; i < nss; i++) | |
2540 | ht_cap->mcs.rx_mask[i] = 0xFF; | |
2541 | ht_cap->mcs.rx_mask[4] = 0x01; | |
2542 | ht_cap->mcs.rx_highest = highest[nss - 1]; | |
2543 | } | |
2544 | ||
2545 | static void rtw89_init_vht_cap(struct rtw89_dev *rtwdev, | |
2546 | struct ieee80211_sta_vht_cap *vht_cap) | |
2547 | { | |
d221270a | 2548 | static const __le16 highest_bw80[RF_PATH_MAX] = { |
e3ec7017 PKS |
2549 | cpu_to_le16(433), cpu_to_le16(867), cpu_to_le16(1300), cpu_to_le16(1733), |
2550 | }; | |
d221270a PKS |
2551 | static const __le16 highest_bw160[RF_PATH_MAX] = { |
2552 | cpu_to_le16(867), cpu_to_le16(1733), cpu_to_le16(2600), cpu_to_le16(3467), | |
2553 | }; | |
2554 | const struct rtw89_chip_info *chip = rtwdev->chip; | |
2555 | const __le16 *highest = chip->support_bw160 ? highest_bw160 : highest_bw80; | |
e3ec7017 PKS |
2556 | struct rtw89_hal *hal = &rtwdev->hal; |
2557 | u16 tx_mcs_map = 0, rx_mcs_map = 0; | |
2558 | u8 sts_cap = 3; | |
2559 | int i; | |
2560 | ||
2561 | for (i = 0; i < 8; i++) { | |
2562 | if (i < hal->tx_nss) | |
2563 | tx_mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); | |
2564 | else | |
2565 | tx_mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); | |
2566 | if (i < hal->rx_nss) | |
2567 | rx_mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); | |
2568 | else | |
2569 | rx_mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); | |
2570 | } | |
2571 | ||
2572 | vht_cap->vht_supported = true; | |
2573 | vht_cap->cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | | |
2574 | IEEE80211_VHT_CAP_SHORT_GI_80 | | |
2575 | IEEE80211_VHT_CAP_RXSTBC_1 | | |
2576 | IEEE80211_VHT_CAP_HTC_VHT | | |
2577 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | | |
2578 | 0; | |
2579 | vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; | |
2580 | vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC; | |
2581 | vht_cap->cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | | |
2582 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | |
2583 | vht_cap->cap |= sts_cap << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; | |
d221270a PKS |
2584 | if (chip->support_bw160) |
2585 | vht_cap->cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | | |
2586 | IEEE80211_VHT_CAP_SHORT_GI_160; | |
e3ec7017 PKS |
2587 | vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(rx_mcs_map); |
2588 | vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(tx_mcs_map); | |
2589 | vht_cap->vht_mcs.rx_highest = highest[hal->rx_nss - 1]; | |
2590 | vht_cap->vht_mcs.tx_highest = highest[hal->tx_nss - 1]; | |
2591 | } | |
2592 | ||
2593 | #define RTW89_SBAND_IFTYPES_NR 2 | |
2594 | ||
2595 | static void rtw89_init_he_cap(struct rtw89_dev *rtwdev, | |
2596 | enum nl80211_band band, | |
2597 | struct ieee80211_supported_band *sband) | |
2598 | { | |
2599 | const struct rtw89_chip_info *chip = rtwdev->chip; | |
2600 | struct rtw89_hal *hal = &rtwdev->hal; | |
2601 | struct ieee80211_sband_iftype_data *iftype_data; | |
2602 | bool no_ng16 = (chip->chip_id == RTL8852A && hal->cv == CHIP_CBV) || | |
2603 | (chip->chip_id == RTL8852B && hal->cv == CHIP_CAV); | |
2604 | u16 mcs_map = 0; | |
2605 | int i; | |
2606 | int nss = hal->rx_nss; | |
2607 | int idx = 0; | |
2608 | ||
2609 | iftype_data = kcalloc(RTW89_SBAND_IFTYPES_NR, sizeof(*iftype_data), GFP_KERNEL); | |
2610 | if (!iftype_data) | |
2611 | return; | |
2612 | ||
2613 | for (i = 0; i < 8; i++) { | |
2614 | if (i < nss) | |
2615 | mcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); | |
2616 | else | |
2617 | mcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); | |
2618 | } | |
2619 | ||
2620 | for (i = 0; i < NUM_NL80211_IFTYPES; i++) { | |
2621 | struct ieee80211_sta_he_cap *he_cap; | |
2622 | u8 *mac_cap_info; | |
2623 | u8 *phy_cap_info; | |
2624 | ||
2625 | switch (i) { | |
2626 | case NL80211_IFTYPE_STATION: | |
2627 | case NL80211_IFTYPE_AP: | |
2628 | break; | |
2629 | default: | |
2630 | continue; | |
2631 | } | |
2632 | ||
2633 | if (idx >= RTW89_SBAND_IFTYPES_NR) { | |
2634 | rtw89_warn(rtwdev, "run out of iftype_data\n"); | |
2635 | break; | |
2636 | } | |
2637 | ||
2638 | iftype_data[idx].types_mask = BIT(i); | |
2639 | he_cap = &iftype_data[idx].he_cap; | |
2640 | mac_cap_info = he_cap->he_cap_elem.mac_cap_info; | |
2641 | phy_cap_info = he_cap->he_cap_elem.phy_cap_info; | |
2642 | ||
2643 | he_cap->has_he = true; | |
2644 | if (i == NL80211_IFTYPE_AP) | |
2645 | mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE; | |
2646 | if (i == NL80211_IFTYPE_STATION) | |
2647 | mac_cap_info[1] = IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US; | |
2648 | mac_cap_info[2] = IEEE80211_HE_MAC_CAP2_ALL_ACK | | |
2649 | IEEE80211_HE_MAC_CAP2_BSR; | |
2650 | mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_2; | |
2651 | if (i == NL80211_IFTYPE_AP) | |
2652 | mac_cap_info[3] |= IEEE80211_HE_MAC_CAP3_OMI_CONTROL; | |
2653 | mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_OPS | | |
2654 | IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU; | |
2655 | if (i == NL80211_IFTYPE_STATION) | |
2656 | mac_cap_info[5] = IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX; | |
517eed92 JB |
2657 | if (band == NL80211_BAND_2GHZ) { |
2658 | phy_cap_info[0] = | |
2659 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; | |
2660 | } else { | |
2661 | phy_cap_info[0] = | |
2662 | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; | |
2663 | if (chip->support_bw160) | |
2664 | phy_cap_info[0] |= IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; | |
2665 | } | |
e3ec7017 PKS |
2666 | phy_cap_info[1] = IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | |
2667 | IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | | |
2668 | IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; | |
2669 | phy_cap_info[2] = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | | |
2670 | IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | | |
2671 | IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | | |
2672 | IEEE80211_HE_PHY_CAP2_DOPPLER_TX; | |
2673 | phy_cap_info[3] = IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM; | |
2674 | if (i == NL80211_IFTYPE_STATION) | |
2675 | phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_16_QAM | | |
2676 | IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2; | |
2677 | if (i == NL80211_IFTYPE_AP) | |
2678 | phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; | |
2679 | phy_cap_info[4] = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE | | |
2680 | IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; | |
2681 | phy_cap_info[5] = no_ng16 ? 0 : | |
2682 | IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | | |
2683 | IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; | |
2684 | phy_cap_info[6] = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | | |
2685 | IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | | |
2686 | IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | | |
2687 | IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE; | |
2688 | phy_cap_info[7] = IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP | | |
2689 | IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI | | |
2690 | IEEE80211_HE_PHY_CAP7_MAX_NC_1; | |
2691 | phy_cap_info[8] = IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI | | |
2692 | IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI | | |
2693 | IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996; | |
d221270a PKS |
2694 | if (chip->support_bw160) |
2695 | phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | | |
2696 | IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU; | |
e3ec7017 PKS |
2697 | phy_cap_info[9] = IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM | |
2698 | IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU | | |
2699 | IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | | |
2700 | IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB | | |
75c5bd68 MK |
2701 | u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, |
2702 | IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK); | |
e3ec7017 PKS |
2703 | if (i == NL80211_IFTYPE_STATION) |
2704 | phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU; | |
2705 | he_cap->he_mcs_nss_supp.rx_mcs_80 = cpu_to_le16(mcs_map); | |
2706 | he_cap->he_mcs_nss_supp.tx_mcs_80 = cpu_to_le16(mcs_map); | |
d221270a PKS |
2707 | if (chip->support_bw160) { |
2708 | he_cap->he_mcs_nss_supp.rx_mcs_160 = cpu_to_le16(mcs_map); | |
2709 | he_cap->he_mcs_nss_supp.tx_mcs_160 = cpu_to_le16(mcs_map); | |
2710 | } | |
e3ec7017 | 2711 | |
12b604d4 PKS |
2712 | if (band == NL80211_BAND_6GHZ) { |
2713 | __le16 capa; | |
2714 | ||
2715 | capa = le16_encode_bits(IEEE80211_HT_MPDU_DENSITY_NONE, | |
2716 | IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | | |
2717 | le16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, | |
2718 | IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | | |
2719 | le16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, | |
2720 | IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN); | |
2721 | iftype_data[idx].he_6ghz_capa.capa = capa; | |
2722 | } | |
2723 | ||
e3ec7017 PKS |
2724 | idx++; |
2725 | } | |
2726 | ||
2727 | sband->iftype_data = iftype_data; | |
2728 | sband->n_iftype_data = idx; | |
2729 | } | |
2730 | ||
2731 | static int rtw89_core_set_supported_band(struct rtw89_dev *rtwdev) | |
2732 | { | |
2733 | struct ieee80211_hw *hw = rtwdev->hw; | |
2734 | struct ieee80211_supported_band *sband_2ghz = NULL, *sband_5ghz = NULL; | |
0237f65a | 2735 | struct ieee80211_supported_band *sband_6ghz = NULL; |
e3ec7017 | 2736 | u32 size = sizeof(struct ieee80211_supported_band); |
0237f65a ZZY |
2737 | u8 support_bands = rtwdev->chip->support_bands; |
2738 | ||
2739 | if (support_bands & BIT(NL80211_BAND_2GHZ)) { | |
2740 | sband_2ghz = kmemdup(&rtw89_sband_2ghz, size, GFP_KERNEL); | |
2741 | if (!sband_2ghz) | |
2742 | goto err; | |
2743 | rtw89_init_ht_cap(rtwdev, &sband_2ghz->ht_cap); | |
2744 | rtw89_init_he_cap(rtwdev, NL80211_BAND_2GHZ, sband_2ghz); | |
2745 | hw->wiphy->bands[NL80211_BAND_2GHZ] = sband_2ghz; | |
2746 | } | |
2747 | ||
2748 | if (support_bands & BIT(NL80211_BAND_5GHZ)) { | |
2749 | sband_5ghz = kmemdup(&rtw89_sband_5ghz, size, GFP_KERNEL); | |
2750 | if (!sband_5ghz) | |
2751 | goto err; | |
2752 | rtw89_init_ht_cap(rtwdev, &sband_5ghz->ht_cap); | |
2753 | rtw89_init_vht_cap(rtwdev, &sband_5ghz->vht_cap); | |
2754 | rtw89_init_he_cap(rtwdev, NL80211_BAND_5GHZ, sband_5ghz); | |
2755 | hw->wiphy->bands[NL80211_BAND_5GHZ] = sband_5ghz; | |
2756 | } | |
e3ec7017 | 2757 | |
0237f65a ZZY |
2758 | if (support_bands & BIT(NL80211_BAND_6GHZ)) { |
2759 | sband_6ghz = kmemdup(&rtw89_sband_6ghz, size, GFP_KERNEL); | |
2760 | if (!sband_6ghz) | |
2761 | goto err; | |
2762 | rtw89_init_he_cap(rtwdev, NL80211_BAND_6GHZ, sband_6ghz); | |
2763 | hw->wiphy->bands[NL80211_BAND_6GHZ] = sband_6ghz; | |
2764 | } | |
e3ec7017 PKS |
2765 | |
2766 | return 0; | |
2767 | ||
2768 | err: | |
2769 | hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; | |
2770 | hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL; | |
0237f65a | 2771 | hw->wiphy->bands[NL80211_BAND_6GHZ] = NULL; |
e3ec7017 PKS |
2772 | if (sband_2ghz) |
2773 | kfree(sband_2ghz->iftype_data); | |
2774 | if (sband_5ghz) | |
2775 | kfree(sband_5ghz->iftype_data); | |
0237f65a ZZY |
2776 | if (sband_6ghz) |
2777 | kfree(sband_6ghz->iftype_data); | |
e3ec7017 PKS |
2778 | kfree(sband_2ghz); |
2779 | kfree(sband_5ghz); | |
0237f65a | 2780 | kfree(sband_6ghz); |
e3ec7017 PKS |
2781 | return -ENOMEM; |
2782 | } | |
2783 | ||
2784 | static void rtw89_core_clr_supported_band(struct rtw89_dev *rtwdev) | |
2785 | { | |
2786 | struct ieee80211_hw *hw = rtwdev->hw; | |
2787 | ||
2788 | kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data); | |
2789 | kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data); | |
0237f65a ZZY |
2790 | if (hw->wiphy->bands[NL80211_BAND_6GHZ]) |
2791 | kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data); | |
e3ec7017 PKS |
2792 | kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]); |
2793 | kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]); | |
0237f65a | 2794 | kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]); |
e3ec7017 PKS |
2795 | hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; |
2796 | hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL; | |
0237f65a | 2797 | hw->wiphy->bands[NL80211_BAND_6GHZ] = NULL; |
e3ec7017 PKS |
2798 | } |
2799 | ||
2800 | static void rtw89_core_ppdu_sts_init(struct rtw89_dev *rtwdev) | |
2801 | { | |
2802 | int i; | |
2803 | ||
2804 | for (i = 0; i < RTW89_PHY_MAX; i++) | |
2805 | skb_queue_head_init(&rtwdev->ppdu_sts.rx_queue[i]); | |
2806 | for (i = 0; i < RTW89_PHY_MAX; i++) | |
2807 | rtwdev->ppdu_sts.curr_rx_ppdu_cnt[i] = U8_MAX; | |
2808 | } | |
2809 | ||
d62816b4 PKS |
2810 | void rtw89_core_update_beacon_work(struct work_struct *work) |
2811 | { | |
2812 | struct rtw89_dev *rtwdev; | |
2813 | struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif, | |
2814 | update_beacon_work); | |
2815 | ||
2816 | if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE) | |
2817 | return; | |
2818 | ||
2819 | rtwdev = rtwvif->rtwdev; | |
2820 | mutex_lock(&rtwdev->mutex); | |
2821 | rtw89_fw_h2c_update_beacon(rtwdev, rtwvif); | |
2822 | mutex_unlock(&rtwdev->mutex); | |
2823 | } | |
2824 | ||
e3ec7017 PKS |
2825 | int rtw89_core_start(struct rtw89_dev *rtwdev) |
2826 | { | |
2827 | int ret; | |
2828 | ||
2829 | rtwdev->mac.qta_mode = RTW89_QTA_SCC; | |
2830 | ret = rtw89_mac_init(rtwdev); | |
2831 | if (ret) { | |
2832 | rtw89_err(rtwdev, "mac init fail, ret:%d\n", ret); | |
2833 | return ret; | |
2834 | } | |
2835 | ||
2836 | rtw89_btc_ntfy_poweron(rtwdev); | |
2837 | ||
2838 | /* efuse process */ | |
2839 | ||
2840 | /* pre-config BB/RF, BB reset/RFC reset */ | |
61ebeecb PKS |
2841 | rtw89_chip_disable_bb_rf(rtwdev); |
2842 | ret = rtw89_chip_enable_bb_rf(rtwdev); | |
2843 | if (ret) | |
2844 | return ret; | |
2845 | ||
e3ec7017 PKS |
2846 | rtw89_phy_init_bb_reg(rtwdev); |
2847 | rtw89_phy_init_rf_reg(rtwdev); | |
2848 | ||
2849 | rtw89_btc_ntfy_init(rtwdev, BTC_MODE_NORMAL); | |
2850 | ||
2851 | rtw89_phy_dm_init(rtwdev); | |
2852 | ||
2853 | rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); | |
2854 | rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0); | |
2855 | ||
2856 | ret = rtw89_hci_start(rtwdev); | |
2857 | if (ret) { | |
2858 | rtw89_err(rtwdev, "failed to start hci\n"); | |
2859 | return ret; | |
2860 | } | |
2861 | ||
2862 | ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->track_work, | |
2863 | RTW89_TRACK_WORK_PERIOD); | |
2864 | ||
2865 | set_bit(RTW89_FLAG_RUNNING, rtwdev->flags); | |
2866 | ||
2867 | rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON); | |
2868 | rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.fw_log_enable); | |
2869 | ||
2870 | return 0; | |
2871 | } | |
2872 | ||
2873 | void rtw89_core_stop(struct rtw89_dev *rtwdev) | |
2874 | { | |
2875 | struct rtw89_btc *btc = &rtwdev->btc; | |
2876 | ||
2877 | /* Prvent to stop twice; enter_ips and ops_stop */ | |
2878 | if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags)) | |
2879 | return; | |
2880 | ||
2881 | rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_OFF); | |
2882 | ||
2883 | clear_bit(RTW89_FLAG_RUNNING, rtwdev->flags); | |
2884 | ||
2885 | mutex_unlock(&rtwdev->mutex); | |
2886 | ||
2887 | cancel_work_sync(&rtwdev->c2h_work); | |
2888 | cancel_work_sync(&btc->eapol_notify_work); | |
2889 | cancel_work_sync(&btc->arp_notify_work); | |
2890 | cancel_work_sync(&btc->dhcp_notify_work); | |
2891 | cancel_work_sync(&btc->icmp_notify_work); | |
2892 | cancel_delayed_work_sync(&rtwdev->txq_reinvoke_work); | |
2893 | cancel_delayed_work_sync(&rtwdev->track_work); | |
2894 | cancel_delayed_work_sync(&rtwdev->coex_act1_work); | |
2895 | cancel_delayed_work_sync(&rtwdev->coex_bt_devinfo_work); | |
2896 | cancel_delayed_work_sync(&rtwdev->coex_rfk_chk_work); | |
2897 | cancel_delayed_work_sync(&rtwdev->cfo_track_work); | |
679955d5 | 2898 | cancel_delayed_work_sync(&rtwdev->forbid_ba_work); |
e3ec7017 PKS |
2899 | |
2900 | mutex_lock(&rtwdev->mutex); | |
2901 | ||
2902 | rtw89_btc_ntfy_poweroff(rtwdev); | |
2903 | rtw89_hci_flush_queues(rtwdev, BIT(rtwdev->hw->queues) - 1, true); | |
2904 | rtw89_mac_flush_txq(rtwdev, BIT(rtwdev->hw->queues) - 1, true); | |
2905 | rtw89_hci_stop(rtwdev); | |
2906 | rtw89_hci_deinit(rtwdev); | |
2907 | rtw89_mac_pwr_off(rtwdev); | |
2908 | rtw89_hci_reset(rtwdev); | |
2909 | } | |
2910 | ||
2911 | int rtw89_core_init(struct rtw89_dev *rtwdev) | |
2912 | { | |
2913 | struct rtw89_btc *btc = &rtwdev->btc; | |
2914 | int ret; | |
89590777 | 2915 | u8 band; |
e3ec7017 PKS |
2916 | |
2917 | INIT_LIST_HEAD(&rtwdev->ba_list); | |
679955d5 | 2918 | INIT_LIST_HEAD(&rtwdev->forbid_ba_list); |
e3ec7017 PKS |
2919 | INIT_LIST_HEAD(&rtwdev->rtwvifs_list); |
2920 | INIT_LIST_HEAD(&rtwdev->early_h2c_list); | |
89590777 PHH |
2921 | for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { |
2922 | if (!(rtwdev->chip->support_bands & BIT(band))) | |
2923 | continue; | |
2924 | INIT_LIST_HEAD(&rtwdev->scan_info.pkt_list[band]); | |
2925 | } | |
e3ec7017 PKS |
2926 | INIT_WORK(&rtwdev->ba_work, rtw89_core_ba_work); |
2927 | INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work); | |
2928 | INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work); | |
2929 | INIT_DELAYED_WORK(&rtwdev->track_work, rtw89_track_work); | |
2930 | INIT_DELAYED_WORK(&rtwdev->coex_act1_work, rtw89_coex_act1_work); | |
2931 | INIT_DELAYED_WORK(&rtwdev->coex_bt_devinfo_work, rtw89_coex_bt_devinfo_work); | |
2932 | INIT_DELAYED_WORK(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work); | |
2933 | INIT_DELAYED_WORK(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work); | |
679955d5 | 2934 | INIT_DELAYED_WORK(&rtwdev->forbid_ba_work, rtw89_forbid_ba_work); |
e3ec7017 PKS |
2935 | rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0); |
2936 | spin_lock_init(&rtwdev->ba_lock); | |
7bfd05ff | 2937 | spin_lock_init(&rtwdev->rpwm_lock); |
e3ec7017 PKS |
2938 | mutex_init(&rtwdev->mutex); |
2939 | mutex_init(&rtwdev->rf_mutex); | |
2940 | rtwdev->total_sta_assoc = 0; | |
2941 | ||
2942 | INIT_WORK(&rtwdev->c2h_work, rtw89_fw_c2h_work); | |
89590777 | 2943 | INIT_WORK(&rtwdev->ips_work, rtw89_ips_work); |
e3ec7017 PKS |
2944 | skb_queue_head_init(&rtwdev->c2h_queue); |
2945 | rtw89_core_ppdu_sts_init(rtwdev); | |
2946 | rtw89_traffic_stats_init(rtwdev, &rtwdev->stats); | |
2947 | ||
2948 | rtwdev->ps_mode = rtw89_update_ps_mode(rtwdev); | |
2949 | rtwdev->hal.rx_fltr = DEFAULT_AX_RX_FLTR; | |
2950 | ||
2951 | INIT_WORK(&btc->eapol_notify_work, rtw89_btc_ntfy_eapol_packet_work); | |
2952 | INIT_WORK(&btc->arp_notify_work, rtw89_btc_ntfy_arp_packet_work); | |
2953 | INIT_WORK(&btc->dhcp_notify_work, rtw89_btc_ntfy_dhcp_packet_work); | |
2954 | INIT_WORK(&btc->icmp_notify_work, rtw89_btc_ntfy_icmp_packet_work); | |
2955 | ||
2956 | ret = rtw89_load_firmware(rtwdev); | |
2957 | if (ret) { | |
2958 | rtw89_warn(rtwdev, "no firmware loaded\n"); | |
2959 | return ret; | |
2960 | } | |
2961 | rtw89_ser_init(rtwdev); | |
a88b6cc4 | 2962 | rtw89_entity_init(rtwdev); |
e3ec7017 PKS |
2963 | |
2964 | return 0; | |
2965 | } | |
2966 | EXPORT_SYMBOL(rtw89_core_init); | |
2967 | ||
2968 | void rtw89_core_deinit(struct rtw89_dev *rtwdev) | |
2969 | { | |
2970 | rtw89_ser_deinit(rtwdev); | |
2971 | rtw89_unload_firmware(rtwdev); | |
2972 | rtw89_fw_free_all_early_h2c(rtwdev); | |
2973 | ||
2974 | destroy_workqueue(rtwdev->txq_wq); | |
2975 | mutex_destroy(&rtwdev->rf_mutex); | |
2976 | mutex_destroy(&rtwdev->mutex); | |
2977 | } | |
2978 | EXPORT_SYMBOL(rtw89_core_deinit); | |
2979 | ||
89590777 PHH |
2980 | void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, |
2981 | const u8 *mac_addr, bool hw_scan) | |
2982 | { | |
cbb145b9 | 2983 | const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); |
89590777 PHH |
2984 | |
2985 | rtwdev->scanning = true; | |
2986 | rtw89_leave_lps(rtwdev); | |
ee20d538 | 2987 | if (hw_scan && (rtwdev->hw->conf.flags & IEEE80211_CONF_IDLE)) |
89590777 PHH |
2988 | rtw89_leave_ips(rtwdev); |
2989 | ||
2990 | ether_addr_copy(rtwvif->mac_addr, mac_addr); | |
cbb145b9 | 2991 | rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, chan->band_type); |
89590777 PHH |
2992 | rtw89_chip_rfk_scan(rtwdev, true); |
2993 | rtw89_hci_recalc_int_mit(rtwdev); | |
2994 | ||
2995 | rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, mac_addr); | |
2996 | } | |
2997 | ||
2998 | void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, | |
2999 | struct ieee80211_vif *vif, bool hw_scan) | |
3000 | { | |
6d7d1fef PHH |
3001 | struct rtw89_vif *rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL; |
3002 | ||
3003 | if (!rtwvif) | |
3004 | return; | |
89590777 PHH |
3005 | |
3006 | ether_addr_copy(rtwvif->mac_addr, vif->addr); | |
3007 | rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); | |
3008 | ||
3009 | rtw89_chip_rfk_scan(rtwdev, false); | |
3010 | rtw89_btc_ntfy_scan_finish(rtwdev, RTW89_PHY_0); | |
3011 | ||
3012 | rtwdev->scanning = false; | |
3013 | rtwdev->dig.bypass_dig = true; | |
ee20d538 | 3014 | if (hw_scan && (rtwdev->hw->conf.flags & IEEE80211_CONF_IDLE)) |
89590777 PHH |
3015 | ieee80211_queue_work(rtwdev->hw, &rtwdev->ips_work); |
3016 | } | |
3017 | ||
e3ec7017 PKS |
3018 | static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev) |
3019 | { | |
a8bdac12 | 3020 | const struct rtw89_chip_info *chip = rtwdev->chip; |
e3ec7017 PKS |
3021 | u8 cv; |
3022 | ||
3023 | cv = rtw89_read32_mask(rtwdev, R_AX_SYS_CFG1, B_AX_CHIP_VER_MASK); | |
a8bdac12 | 3024 | if (chip->chip_id == RTL8852A && cv <= CHIP_CBV) { |
e3ec7017 PKS |
3025 | if (rtw89_read32(rtwdev, R_AX_GPIO0_7_FUNC_SEL) == RTW89_R32_DEAD) |
3026 | cv = CHIP_CAV; | |
3027 | else | |
3028 | cv = CHIP_CBV; | |
3029 | } | |
3030 | ||
3031 | rtwdev->hal.cv = cv; | |
3032 | } | |
3033 | ||
1c2423de JL |
3034 | static void rtw89_core_setup_phycap(struct rtw89_dev *rtwdev) |
3035 | { | |
3036 | rtwdev->hal.support_cckpd = | |
3037 | !(rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv <= CHIP_CBV) && | |
3038 | !(rtwdev->chip->chip_id == RTL8852B && rtwdev->hal.cv <= CHIP_CAV); | |
1e6f0d2a JL |
3039 | rtwdev->hal.support_igi = |
3040 | rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv <= CHIP_CBV; | |
1c2423de JL |
3041 | } |
3042 | ||
e3ec7017 PKS |
3043 | static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev) |
3044 | { | |
3045 | int ret; | |
3046 | ||
3047 | ret = rtw89_mac_partial_init(rtwdev); | |
3048 | if (ret) | |
3049 | return ret; | |
3050 | ||
3051 | ret = rtw89_parse_efuse_map(rtwdev); | |
3052 | if (ret) | |
3053 | return ret; | |
3054 | ||
3055 | ret = rtw89_parse_phycap_map(rtwdev); | |
3056 | if (ret) | |
3057 | return ret; | |
3058 | ||
3059 | ret = rtw89_mac_setup_phycap(rtwdev); | |
3060 | if (ret) | |
3061 | return ret; | |
3062 | ||
1c2423de JL |
3063 | rtw89_core_setup_phycap(rtwdev); |
3064 | ||
e3ec7017 PKS |
3065 | rtw89_mac_pwr_off(rtwdev); |
3066 | ||
3067 | return 0; | |
3068 | } | |
3069 | ||
3070 | static int rtw89_chip_board_info_setup(struct rtw89_dev *rtwdev) | |
3071 | { | |
3072 | rtw89_chip_fem_setup(rtwdev); | |
3073 | ||
3074 | return 0; | |
3075 | } | |
3076 | ||
3077 | int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) | |
3078 | { | |
3079 | int ret; | |
3080 | ||
3081 | rtw89_read_chip_ver(rtwdev); | |
3082 | ||
3083 | ret = rtw89_wait_firmware_completion(rtwdev); | |
3084 | if (ret) { | |
3085 | rtw89_err(rtwdev, "failed to wait firmware completion\n"); | |
3086 | return ret; | |
3087 | } | |
3088 | ||
3089 | ret = rtw89_fw_recognize(rtwdev); | |
3090 | if (ret) { | |
3091 | rtw89_err(rtwdev, "failed to recognize firmware\n"); | |
3092 | return ret; | |
3093 | } | |
3094 | ||
3095 | ret = rtw89_chip_efuse_info_setup(rtwdev); | |
3096 | if (ret) | |
3097 | return ret; | |
3098 | ||
3099 | ret = rtw89_chip_board_info_setup(rtwdev); | |
3100 | if (ret) | |
3101 | return ret; | |
3102 | ||
3103 | return 0; | |
3104 | } | |
3105 | EXPORT_SYMBOL(rtw89_chip_info_setup); | |
3106 | ||
3107 | static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) | |
3108 | { | |
3109 | struct ieee80211_hw *hw = rtwdev->hw; | |
3110 | struct rtw89_efuse *efuse = &rtwdev->efuse; | |
3111 | int ret; | |
3112 | int tx_headroom = IEEE80211_HT_CTL_LEN; | |
3113 | ||
3114 | hw->vif_data_size = sizeof(struct rtw89_vif); | |
3115 | hw->sta_data_size = sizeof(struct rtw89_sta); | |
3116 | hw->txq_data_size = sizeof(struct rtw89_txq); | |
3117 | ||
3118 | SET_IEEE80211_PERM_ADDR(hw, efuse->addr); | |
3119 | ||
3120 | hw->extra_tx_headroom = tx_headroom; | |
3121 | hw->queues = IEEE80211_NUM_ACS; | |
3122 | hw->max_rx_aggregation_subframes = RTW89_MAX_RX_AGG_NUM; | |
3123 | hw->max_tx_aggregation_subframes = RTW89_MAX_TX_AGG_NUM; | |
3124 | ||
3125 | ieee80211_hw_set(hw, SIGNAL_DBM); | |
3126 | ieee80211_hw_set(hw, HAS_RATE_CONTROL); | |
3127 | ieee80211_hw_set(hw, MFP_CAPABLE); | |
3128 | ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); | |
3129 | ieee80211_hw_set(hw, AMPDU_AGGREGATION); | |
3130 | ieee80211_hw_set(hw, RX_INCLUDES_FCS); | |
3131 | ieee80211_hw_set(hw, TX_AMSDU); | |
3132 | ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); | |
3133 | ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); | |
3134 | ieee80211_hw_set(hw, SUPPORTS_PS); | |
3135 | ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); | |
89590777 | 3136 | ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); |
85393ca6 | 3137 | ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); |
e3ec7017 | 3138 | |
b478ff6b PKS |
3139 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
3140 | BIT(NL80211_IFTYPE_AP); | |
e3ec7017 PKS |
3141 | hw->wiphy->available_antennas_tx = BIT(rtwdev->chip->rf_path_num) - 1; |
3142 | hw->wiphy->available_antennas_rx = BIT(rtwdev->chip->rf_path_num) - 1; | |
3143 | ||
6a5a783a PKS |
3144 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
3145 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP; | |
e3ec7017 PKS |
3146 | hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; |
3147 | ||
89590777 PHH |
3148 | hw->wiphy->max_scan_ssids = RTW89_SCANOFLD_MAX_SSID; |
3149 | hw->wiphy->max_scan_ie_len = RTW89_SCANOFLD_MAX_IE_LEN; | |
3150 | ||
e3ec7017 PKS |
3151 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); |
3152 | ||
3153 | ret = rtw89_core_set_supported_band(rtwdev); | |
3154 | if (ret) { | |
3155 | rtw89_err(rtwdev, "failed to set supported band\n"); | |
3156 | return ret; | |
3157 | } | |
3158 | ||
3159 | hw->wiphy->reg_notifier = rtw89_regd_notifier; | |
3160 | hw->wiphy->sar_capa = &rtw89_sar_capa; | |
3161 | ||
3162 | ret = ieee80211_register_hw(hw); | |
3163 | if (ret) { | |
3164 | rtw89_err(rtwdev, "failed to register hw\n"); | |
3165 | goto err; | |
3166 | } | |
3167 | ||
3168 | ret = rtw89_regd_init(rtwdev, rtw89_regd_notifier); | |
3169 | if (ret) { | |
3170 | rtw89_err(rtwdev, "failed to init regd\n"); | |
3171 | goto err; | |
3172 | } | |
3173 | ||
3174 | return 0; | |
3175 | ||
3176 | err: | |
3177 | return ret; | |
3178 | } | |
3179 | ||
3180 | static void rtw89_core_unregister_hw(struct rtw89_dev *rtwdev) | |
3181 | { | |
3182 | struct ieee80211_hw *hw = rtwdev->hw; | |
3183 | ||
3184 | ieee80211_unregister_hw(hw); | |
3185 | rtw89_core_clr_supported_band(rtwdev); | |
3186 | } | |
3187 | ||
3188 | int rtw89_core_register(struct rtw89_dev *rtwdev) | |
3189 | { | |
3190 | int ret; | |
3191 | ||
3192 | ret = rtw89_core_register_hw(rtwdev); | |
3193 | if (ret) { | |
3194 | rtw89_err(rtwdev, "failed to register core hw\n"); | |
3195 | return ret; | |
3196 | } | |
3197 | ||
3198 | rtw89_debugfs_init(rtwdev); | |
3199 | ||
3200 | return 0; | |
3201 | } | |
3202 | EXPORT_SYMBOL(rtw89_core_register); | |
3203 | ||
3204 | void rtw89_core_unregister(struct rtw89_dev *rtwdev) | |
3205 | { | |
3206 | rtw89_core_unregister_hw(rtwdev); | |
3207 | } | |
3208 | EXPORT_SYMBOL(rtw89_core_unregister); | |
3209 | ||
3210 | MODULE_AUTHOR("Realtek Corporation"); | |
3211 | MODULE_DESCRIPTION("Realtek 802.11ax wireless core module"); | |
3212 | MODULE_LICENSE("Dual BSD/GPL"); |