1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2020-2022 Realtek Corporation
3 */
4
5 #include "chan.h"
6 #include "coex.h"
7 #include "debug.h"
8 #include "fw.h"
9 #include "mac.h"
10 #include "phy.h"
11 #include "ps.h"
12 #include "sar.h"
13 #include "util.h"
14
15 static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
16 enum rtw89_chanctx_idx idx1,
17 enum rtw89_chanctx_idx idx2);
18
rtw89_get_subband_type(enum rtw89_band band,u8 center_chan)19 static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
20 u8 center_chan)
21 {
22 switch (band) {
23 default:
24 case RTW89_BAND_2G:
25 switch (center_chan) {
26 default:
27 case 1 ... 14:
28 return RTW89_CH_2G;
29 }
30 case RTW89_BAND_5G:
31 switch (center_chan) {
32 default:
33 case 36 ... 64:
34 return RTW89_CH_5G_BAND_1;
35 case 100 ... 144:
36 return RTW89_CH_5G_BAND_3;
37 case 149 ... 177:
38 return RTW89_CH_5G_BAND_4;
39 }
40 case RTW89_BAND_6G:
41 switch (center_chan) {
42 default:
43 case 1 ... 29:
44 return RTW89_CH_6G_BAND_IDX0;
45 case 33 ... 61:
46 return RTW89_CH_6G_BAND_IDX1;
47 case 65 ... 93:
48 return RTW89_CH_6G_BAND_IDX2;
49 case 97 ... 125:
50 return RTW89_CH_6G_BAND_IDX3;
51 case 129 ... 157:
52 return RTW89_CH_6G_BAND_IDX4;
53 case 161 ... 189:
54 return RTW89_CH_6G_BAND_IDX5;
55 case 193 ... 221:
56 return RTW89_CH_6G_BAND_IDX6;
57 case 225 ... 253:
58 return RTW89_CH_6G_BAND_IDX7;
59 }
60 }
61 }
62
rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,u32 center_freq,u32 primary_freq)63 static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
64 u32 center_freq,
65 u32 primary_freq)
66 {
67 u8 primary_chan_idx;
68 u32 offset;
69
70 switch (bw) {
71 default:
72 case RTW89_CHANNEL_WIDTH_20:
73 primary_chan_idx = RTW89_SC_DONT_CARE;
74 break;
75 case RTW89_CHANNEL_WIDTH_40:
76 if (primary_freq > center_freq)
77 primary_chan_idx = RTW89_SC_20_UPPER;
78 else
79 primary_chan_idx = RTW89_SC_20_LOWER;
80 break;
81 case RTW89_CHANNEL_WIDTH_80:
82 case RTW89_CHANNEL_WIDTH_160:
83 if (primary_freq > center_freq) {
84 offset = (primary_freq - center_freq - 10) / 20;
85 primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
86 } else {
87 offset = (center_freq - primary_freq - 10) / 20;
88 primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
89 }
90 break;
91 }
92
93 return primary_chan_idx;
94 }
95
rtw89_get_primary_sb_idx(u8 central_ch,u8 pri_ch,enum rtw89_bandwidth bw)96 static u8 rtw89_get_primary_sb_idx(u8 central_ch, u8 pri_ch,
97 enum rtw89_bandwidth bw)
98 {
99 static const u8 prisb_cal_ofst[RTW89_CHANNEL_WIDTH_ORDINARY_NUM] = {
100 0, 2, 6, 14, 30
101 };
102
103 if (bw >= RTW89_CHANNEL_WIDTH_ORDINARY_NUM)
104 return 0;
105
106 return (prisb_cal_ofst[bw] + pri_ch - central_ch) / 4;
107 }
108
rtw89_chan_create(struct rtw89_chan * chan,u8 center_chan,u8 primary_chan,enum rtw89_band band,enum rtw89_bandwidth bandwidth)109 void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
110 enum rtw89_band band, enum rtw89_bandwidth bandwidth)
111 {
112 enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
113 u32 center_freq, primary_freq;
114
115 memset(chan, 0, sizeof(*chan));
116 chan->channel = center_chan;
117 chan->primary_channel = primary_chan;
118 chan->band_type = band;
119 chan->band_width = bandwidth;
120
121 center_freq = ieee80211_channel_to_frequency(center_chan, nl_band);
122 primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band);
123
124 chan->freq = center_freq;
125 chan->subband_type = rtw89_get_subband_type(band, center_chan);
126 chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
127 primary_freq);
128 chan->pri_sb_idx = rtw89_get_primary_sb_idx(center_chan, primary_chan,
129 bandwidth);
130 }
131
_rtw89_chan_update_punctured(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,const struct cfg80211_chan_def * chandef)132 static void _rtw89_chan_update_punctured(struct rtw89_dev *rtwdev,
133 struct rtw89_vif_link *rtwvif_link,
134 const struct cfg80211_chan_def *chandef)
135 {
136 struct ieee80211_bss_conf *bss_conf;
137
138 if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION &&
139 rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT)
140 return;
141
142 rcu_read_lock();
143
144 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
145 if (!bss_conf->eht_support) {
146 rcu_read_unlock();
147 return;
148 }
149
150 rcu_read_unlock();
151
152 rtw89_chip_h2c_punctured_cmac_tbl(rtwdev, rtwvif_link, chandef->punctured);
153 }
154
rtw89_chan_update_punctured(struct rtw89_dev * rtwdev,enum rtw89_chanctx_idx idx,const struct cfg80211_chan_def * chandef)155 static void rtw89_chan_update_punctured(struct rtw89_dev *rtwdev,
156 enum rtw89_chanctx_idx idx,
157 const struct cfg80211_chan_def *chandef)
158 {
159 struct rtw89_vif_link *rtwvif_link;
160 struct rtw89_vif *rtwvif;
161 unsigned int link_id;
162
163 rtw89_for_each_rtwvif(rtwdev, rtwvif) {
164 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
165 if (!rtwvif_link->chanctx_assigned ||
166 rtwvif_link->chanctx_idx != idx)
167 continue;
168
169 _rtw89_chan_update_punctured(rtwdev, rtwvif_link, chandef);
170 }
171 }
172 }
173
rtw89_assign_entity_chan(struct rtw89_dev * rtwdev,enum rtw89_chanctx_idx idx,const struct rtw89_chan * new)174 bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
175 enum rtw89_chanctx_idx idx,
176 const struct rtw89_chan *new)
177 {
178 struct rtw89_hal *hal = &rtwdev->hal;
179 struct rtw89_chan *chan = &hal->chanctx[idx].chan;
180 struct rtw89_chan_rcd *rcd = &hal->chanctx[idx].rcd;
181 bool band_changed;
182
183 rcd->prev_primary_channel = chan->primary_channel;
184 rcd->prev_band_type = chan->band_type;
185 band_changed = new->band_type != chan->band_type;
186 rcd->band_changed = band_changed;
187
188 *chan = *new;
189 return band_changed;
190 }
191
rtw89_iterate_entity_chan(struct rtw89_dev * rtwdev,int (* iterator)(const struct rtw89_chan * chan,void * data),void * data)192 int rtw89_iterate_entity_chan(struct rtw89_dev *rtwdev,
193 int (*iterator)(const struct rtw89_chan *chan,
194 void *data),
195 void *data)
196 {
197 struct rtw89_hal *hal = &rtwdev->hal;
198 const struct rtw89_chan *chan;
199 int ret;
200 u8 idx;
201
202 lockdep_assert_wiphy(rtwdev->hw->wiphy);
203
204 for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) {
205 chan = rtw89_chan_get(rtwdev, idx);
206 ret = iterator(chan, data);
207 if (ret)
208 return ret;
209 }
210
211 return 0;
212 }
213
__rtw89_config_entity_chandef(struct rtw89_dev * rtwdev,enum rtw89_chanctx_idx idx,const struct cfg80211_chan_def * chandef)214 static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
215 enum rtw89_chanctx_idx idx,
216 const struct cfg80211_chan_def *chandef)
217 {
218 struct rtw89_hal *hal = &rtwdev->hal;
219
220 hal->chanctx[idx].chandef = *chandef;
221 }
222
rtw89_config_entity_chandef(struct rtw89_dev * rtwdev,enum rtw89_chanctx_idx idx,const struct cfg80211_chan_def * chandef)223 void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
224 enum rtw89_chanctx_idx idx,
225 const struct cfg80211_chan_def *chandef)
226 {
227 struct rtw89_hal *hal = &rtwdev->hal;
228
229 if (!chandef) {
230 clear_bit(idx, hal->entity_map);
231 return;
232 }
233
234 __rtw89_config_entity_chandef(rtwdev, idx, chandef);
235 set_bit(idx, hal->entity_map);
236 }
237
rtw89_config_roc_chandef(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,const struct cfg80211_chan_def * chandef)238 void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
239 struct rtw89_vif_link *rtwvif_link,
240 const struct cfg80211_chan_def *chandef)
241 {
242 enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx;
243 struct rtw89_hal *hal = &rtwdev->hal;
244 enum rtw89_chanctx_idx cur;
245
246 if (chandef) {
247 cur = atomic_cmpxchg(&hal->roc_chanctx_idx,
248 RTW89_CHANCTX_IDLE, idx);
249 if (cur != RTW89_CHANCTX_IDLE) {
250 rtw89_debug(rtwdev, RTW89_DBG_TXRX,
251 "ROC still processing on entity %d\n", idx);
252 return;
253 }
254
255 hal->roc_chandef = *chandef;
256 hal->roc_link_index = rtw89_vif_link_inst_get_index(rtwvif_link);
257 } else {
258 cur = atomic_cmpxchg(&hal->roc_chanctx_idx, idx,
259 RTW89_CHANCTX_IDLE);
260 if (cur == idx)
261 return;
262
263 if (cur == RTW89_CHANCTX_IDLE)
264 rtw89_debug(rtwdev, RTW89_DBG_TXRX,
265 "ROC already finished on entity %d\n", idx);
266 else
267 rtw89_debug(rtwdev, RTW89_DBG_TXRX,
268 "ROC is processing on entity %d\n", cur);
269 }
270 }
271
rtw89_config_default_chandef(struct rtw89_dev * rtwdev)272 static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
273 {
274 struct cfg80211_chan_def chandef = {0};
275
276 rtw89_get_default_chandef(&chandef);
277 __rtw89_config_entity_chandef(rtwdev, RTW89_CHANCTX_0, &chandef);
278 }
279
rtw89_entity_init(struct rtw89_dev * rtwdev)280 void rtw89_entity_init(struct rtw89_dev *rtwdev)
281 {
282 struct rtw89_hal *hal = &rtwdev->hal;
283 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
284
285 hal->entity_pause = false;
286 bitmap_zero(hal->entity_map, NUM_OF_RTW89_CHANCTX);
287 bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES);
288 atomic_set(&hal->roc_chanctx_idx, RTW89_CHANCTX_IDLE);
289
290 INIT_LIST_HEAD(&mgnt->active_list);
291
292 rtw89_config_default_chandef(rtwdev);
293 }
294
rtw89_vif_is_active_role(struct rtw89_vif * rtwvif)295 static bool rtw89_vif_is_active_role(struct rtw89_vif *rtwvif)
296 {
297 struct rtw89_vif_link *rtwvif_link;
298 unsigned int link_id;
299
300 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
301 if (rtwvif_link->chanctx_assigned)
302 return true;
303
304 return false;
305 }
306
rtw89_entity_calculate_weight(struct rtw89_dev * rtwdev,struct rtw89_entity_weight * w)307 static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev,
308 struct rtw89_entity_weight *w)
309 {
310 struct rtw89_hal *hal = &rtwdev->hal;
311 const struct rtw89_chanctx_cfg *cfg;
312 struct rtw89_vif *rtwvif;
313 int idx;
314
315 w->registered_chanctxs = bitmap_weight(hal->entity_map, NUM_OF_RTW89_CHANCTX);
316
317 for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) {
318 cfg = hal->chanctx[idx].cfg;
319 if (!cfg) {
320 /* doesn't run with chanctx ops; one channel at most */
321 w->active_chanctxs = 1;
322 break;
323 }
324
325 if (cfg->ref_count > 0)
326 w->active_chanctxs++;
327 }
328
329 rtw89_for_each_rtwvif(rtwdev, rtwvif) {
330 if (rtw89_vif_is_active_role(rtwvif))
331 w->active_roles++;
332 }
333 }
334
rtw89_normalize_link_chanctx(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link)335 static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev,
336 struct rtw89_vif_link *rtwvif_link)
337 {
338 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
339 struct rtw89_vif_link *cur;
340
341 if (unlikely(!rtwvif_link->chanctx_assigned))
342 return;
343
344 cur = rtw89_vif_get_link_inst(rtwvif, 0);
345 if (!cur || !cur->chanctx_assigned)
346 return;
347
348 if (cur == rtwvif_link)
349 return;
350
351 rtw89_swap_chanctx(rtwdev, rtwvif_link->chanctx_idx, cur->chanctx_idx);
352 }
353
__rtw89_mgnt_chan_get(struct rtw89_dev * rtwdev,const char * caller_message,u8 link_index)354 const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
355 const char *caller_message,
356 u8 link_index)
357 {
358 struct rtw89_hal *hal = &rtwdev->hal;
359 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
360 enum rtw89_chanctx_idx chanctx_idx;
361 enum rtw89_chanctx_idx roc_idx;
362 enum rtw89_entity_mode mode;
363 u8 role_index;
364
365 lockdep_assert_wiphy(rtwdev->hw->wiphy);
366
367 if (unlikely(link_index >= __RTW89_MLD_MAX_LINK_NUM)) {
368 WARN(1, "link index %u is invalid (max link inst num: %d)\n",
369 link_index, __RTW89_MLD_MAX_LINK_NUM);
370 goto dflt;
371 }
372
373 mode = rtw89_get_entity_mode(rtwdev);
374 switch (mode) {
375 case RTW89_ENTITY_MODE_SCC_OR_SMLD:
376 case RTW89_ENTITY_MODE_MCC:
377 role_index = 0;
378 break;
379 case RTW89_ENTITY_MODE_MCC_PREPARE:
380 role_index = 1;
381 break;
382 default:
383 WARN(1, "Invalid ent mode: %d\n", mode);
384 goto dflt;
385 }
386
387 chanctx_idx = mgnt->chanctx_tbl[role_index][link_index];
388 if (chanctx_idx == RTW89_CHANCTX_IDLE)
389 goto dflt;
390
391 roc_idx = atomic_read(&hal->roc_chanctx_idx);
392 if (roc_idx != RTW89_CHANCTX_IDLE) {
393 /* ROC is ongoing (given ROC runs on @hal->roc_link_index).
394 * If @link_index is the same, get the ongoing ROC chanctx.
395 */
396 if (link_index == hal->roc_link_index)
397 chanctx_idx = roc_idx;
398 }
399
400 return rtw89_chan_get(rtwdev, chanctx_idx);
401
402 dflt:
403 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
404 "%s (%s): prefetch NULL on link index %u\n",
405 __func__, caller_message ?: "", link_index);
406
407 return rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
408 }
409 EXPORT_SYMBOL(__rtw89_mgnt_chan_get);
410
411 static enum rtw89_mlo_dbcc_mode
rtw89_entity_sel_mlo_dbcc_mode(struct rtw89_dev * rtwdev,u8 active_hws)412 rtw89_entity_sel_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws)
413 {
414 if (rtwdev->chip->chip_gen != RTW89_CHIP_BE)
415 return MLO_DBCC_NOT_SUPPORT;
416
417 switch (active_hws) {
418 case BIT(0):
419 return MLO_2_PLUS_0_1RF;
420 case BIT(1):
421 return MLO_0_PLUS_2_1RF;
422 case BIT(0) | BIT(1):
423 default:
424 return MLO_1_PLUS_1_1RF;
425 }
426 }
427
428 static
rtw89_entity_recalc_mlo_dbcc_mode(struct rtw89_dev * rtwdev,u8 active_hws)429 void rtw89_entity_recalc_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws)
430 {
431 enum rtw89_mlo_dbcc_mode mode;
432
433 mode = rtw89_entity_sel_mlo_dbcc_mode(rtwdev, active_hws);
434 rtwdev->mlo_dbcc_mode = mode;
435
436 rtw89_debug(rtwdev, RTW89_DBG_STATE, "recalc mlo dbcc mode to %d\n", mode);
437 }
438
rtw89_entity_recalc_mgnt_roles(struct rtw89_dev * rtwdev)439 static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
440 {
441 struct rtw89_hal *hal = &rtwdev->hal;
442 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
443 struct rtw89_vif_link *link;
444 struct rtw89_vif *role;
445 u8 active_hws = 0;
446 u8 pos = 0;
447 int i, j;
448
449 lockdep_assert_wiphy(rtwdev->hw->wiphy);
450
451 for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++)
452 mgnt->active_roles[i] = NULL;
453
454 for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++) {
455 for (j = 0; j < __RTW89_MLD_MAX_LINK_NUM; j++)
456 mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE;
457 }
458
459 /* To be consistent with legacy behavior, expect the first active role
460 * which uses RTW89_CHANCTX_0 to put at position 0, and make its first
461 * link instance take RTW89_CHANCTX_0. (normalizing)
462 */
463 list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
464 for (i = 0; i < role->links_inst_valid_num; i++) {
465 link = rtw89_vif_get_link_inst(role, i);
466 if (!link || !link->chanctx_assigned)
467 continue;
468
469 if (link->chanctx_idx == RTW89_CHANCTX_0) {
470 rtw89_normalize_link_chanctx(rtwdev, link);
471
472 list_del(&role->mgnt_entry);
473 list_add(&role->mgnt_entry, &mgnt->active_list);
474 goto fill;
475 }
476 }
477 }
478
479 fill:
480 list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
481 if (unlikely(pos >= RTW89_MAX_INTERFACE_NUM)) {
482 rtw89_warn(rtwdev,
483 "%s: active roles are over max iface num\n",
484 __func__);
485 break;
486 }
487
488 for (i = 0; i < role->links_inst_valid_num; i++) {
489 link = rtw89_vif_get_link_inst(role, i);
490 if (!link || !link->chanctx_assigned)
491 continue;
492
493 mgnt->chanctx_tbl[pos][i] = link->chanctx_idx;
494 active_hws |= BIT(i);
495 }
496
497 mgnt->active_roles[pos++] = role;
498 }
499
500 rtw89_entity_recalc_mlo_dbcc_mode(rtwdev, active_hws);
501 }
502
rtw89_entity_recalc(struct rtw89_dev * rtwdev)503 enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
504 {
505 DECLARE_BITMAP(recalc_map, NUM_OF_RTW89_CHANCTX) = {};
506 struct rtw89_hal *hal = &rtwdev->hal;
507 const struct cfg80211_chan_def *chandef;
508 struct rtw89_entity_weight w = {};
509 enum rtw89_entity_mode mode;
510 struct rtw89_chan chan;
511 u8 idx;
512
513 lockdep_assert_wiphy(rtwdev->hw->wiphy);
514
515 bitmap_copy(recalc_map, hal->entity_map, NUM_OF_RTW89_CHANCTX);
516
517 rtw89_entity_calculate_weight(rtwdev, &w);
518 switch (w.active_chanctxs) {
519 default:
520 rtw89_warn(rtwdev, "unknown ent chanctxs weight: %d\n",
521 w.active_chanctxs);
522 bitmap_zero(recalc_map, NUM_OF_RTW89_CHANCTX);
523 fallthrough;
524 case 0:
525 if (!w.registered_chanctxs)
526 rtw89_config_default_chandef(rtwdev);
527 set_bit(RTW89_CHANCTX_0, recalc_map);
528 fallthrough;
529 case 1:
530 mode = RTW89_ENTITY_MODE_SCC_OR_SMLD;
531 break;
532 case 2 ... NUM_OF_RTW89_CHANCTX:
533 if (w.active_roles == 1) {
534 mode = RTW89_ENTITY_MODE_SCC_OR_SMLD;
535 break;
536 }
537
538 if (w.active_roles != NUM_OF_RTW89_MCC_ROLES) {
539 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
540 "unhandled ent: %d chanctxs %d roles\n",
541 w.active_chanctxs, w.active_roles);
542 return RTW89_ENTITY_MODE_UNHANDLED;
543 }
544
545 mode = rtw89_get_entity_mode(rtwdev);
546 if (mode == RTW89_ENTITY_MODE_MCC)
547 break;
548
549 mode = RTW89_ENTITY_MODE_MCC_PREPARE;
550 break;
551 }
552
553 for_each_set_bit(idx, recalc_map, NUM_OF_RTW89_CHANCTX) {
554 chandef = rtw89_chandef_get(rtwdev, idx);
555 rtw89_get_channel_params(chandef, &chan);
556 if (chan.channel == 0) {
557 WARN(1, "Invalid channel on chanctx %d\n", idx);
558 return RTW89_ENTITY_MODE_INVALID;
559 }
560
561 rtw89_assign_entity_chan(rtwdev, idx, &chan);
562 }
563
564 rtw89_entity_recalc_mgnt_roles(rtwdev);
565
566 if (hal->entity_pause)
567 return rtw89_get_entity_mode(rtwdev);
568
569 rtw89_set_entity_mode(rtwdev, mode);
570 return mode;
571 }
572
rtw89_chanctx_notify(struct rtw89_dev * rtwdev,enum rtw89_chanctx_state state)573 static void rtw89_chanctx_notify(struct rtw89_dev *rtwdev,
574 enum rtw89_chanctx_state state)
575 {
576 const struct rtw89_chip_info *chip = rtwdev->chip;
577 const struct rtw89_chanctx_listener *listener = chip->chanctx_listener;
578 int i;
579
580 if (!listener)
581 return;
582
583 for (i = 0; i < NUM_OF_RTW89_CHANCTX_CALLBACKS; i++) {
584 if (!listener->callbacks[i])
585 continue;
586
587 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
588 "chanctx notify listener: cb %d, state %d\n",
589 i, state);
590
591 listener->callbacks[i](rtwdev, state);
592 }
593 }
594
rtw89_concurrent_via_mrc(struct rtw89_dev * rtwdev)595 static bool rtw89_concurrent_via_mrc(struct rtw89_dev *rtwdev)
596 {
597 enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
598
599 return chip_gen == RTW89_CHIP_BE;
600 }
601
602 /* This function centrally manages how MCC roles are sorted and iterated.
603 * And, it guarantees that ordered_idx is less than NUM_OF_RTW89_MCC_ROLES.
604 * So, if data needs to pass an array for ordered_idx, the array can declare
605 * with NUM_OF_RTW89_MCC_ROLES. Besides, the entire iteration will stop
606 * immediately as long as iterator returns a non-zero value.
607 */
608 static
rtw89_iterate_mcc_roles(struct rtw89_dev * rtwdev,int (* iterator)(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role,unsigned int ordered_idx,void * data),void * data)609 int rtw89_iterate_mcc_roles(struct rtw89_dev *rtwdev,
610 int (*iterator)(struct rtw89_dev *rtwdev,
611 struct rtw89_mcc_role *mcc_role,
612 unsigned int ordered_idx,
613 void *data),
614 void *data)
615 {
616 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
617 struct rtw89_mcc_role * const roles[] = {
618 &mcc->role_ref,
619 &mcc->role_aux,
620 };
621 unsigned int idx;
622 int ret;
623
624 BUILD_BUG_ON(ARRAY_SIZE(roles) != NUM_OF_RTW89_MCC_ROLES);
625
626 for (idx = 0; idx < NUM_OF_RTW89_MCC_ROLES; idx++) {
627 ret = iterator(rtwdev, roles[idx], idx, data);
628 if (ret)
629 return ret;
630 }
631
632 return 0;
633 }
634
rtw89_mcc_get_tbtt_ofst(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * role,u64 tsf)635 static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev,
636 struct rtw89_mcc_role *role, u64 tsf)
637 {
638 struct rtw89_vif_link *rtwvif_link = role->rtwvif_link;
639 u32 bcn_intvl_us = ieee80211_tu_to_usec(role->beacon_interval);
640 u64 sync_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf);
641 u32 remainder;
642
643 if (role->is_go) {
644 sync_tsf = 0;
645 } else if (tsf < sync_tsf) {
646 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
647 "MCC get tbtt ofst: tsf might not update yet\n");
648 sync_tsf = 0;
649 }
650
651 div_u64_rem(tsf - sync_tsf, bcn_intvl_us, &remainder);
652
653 return remainder;
654 }
655
__mcc_fw_req_tsf(struct rtw89_dev * rtwdev,u64 * tsf_ref,u64 * tsf_aux)656 static int __mcc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux)
657 {
658 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
659 struct rtw89_mcc_role *ref = &mcc->role_ref;
660 struct rtw89_mcc_role *aux = &mcc->role_aux;
661 struct rtw89_mac_mcc_tsf_rpt rpt = {};
662 struct rtw89_fw_mcc_tsf_req req = {};
663 int ret;
664
665 req.group = mcc->group;
666 req.macid_x = ref->rtwvif_link->mac_id;
667 req.macid_y = aux->rtwvif_link->mac_id;
668 ret = rtw89_fw_h2c_mcc_req_tsf(rtwdev, &req, &rpt);
669 if (ret) {
670 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
671 "MCC h2c failed to request tsf: %d\n", ret);
672 return ret;
673 }
674
675 *tsf_ref = (u64)rpt.tsf_x_high << 32 | rpt.tsf_x_low;
676 *tsf_aux = (u64)rpt.tsf_y_high << 32 | rpt.tsf_y_low;
677
678 return 0;
679 }
680
__mrc_fw_req_tsf(struct rtw89_dev * rtwdev,u64 * tsf_ref,u64 * tsf_aux)681 static int __mrc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux)
682 {
683 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
684 struct rtw89_mcc_role *ref = &mcc->role_ref;
685 struct rtw89_mcc_role *aux = &mcc->role_aux;
686 struct rtw89_fw_mrc_req_tsf_arg arg = {};
687 struct rtw89_mac_mrc_tsf_rpt rpt = {};
688 int ret;
689
690 BUILD_BUG_ON(RTW89_MAC_MRC_MAX_REQ_TSF_NUM < NUM_OF_RTW89_MCC_ROLES);
691
692 arg.num = 2;
693 arg.infos[0].band = ref->rtwvif_link->mac_idx;
694 arg.infos[0].port = ref->rtwvif_link->port;
695 arg.infos[1].band = aux->rtwvif_link->mac_idx;
696 arg.infos[1].port = aux->rtwvif_link->port;
697
698 ret = rtw89_fw_h2c_mrc_req_tsf(rtwdev, &arg, &rpt);
699 if (ret) {
700 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
701 "MRC h2c failed to request tsf: %d\n", ret);
702 return ret;
703 }
704
705 *tsf_ref = rpt.tsfs[0];
706 *tsf_aux = rpt.tsfs[1];
707
708 return 0;
709 }
710
rtw89_mcc_get_bcn_ofst(struct rtw89_dev * rtwdev)711 static u16 rtw89_mcc_get_bcn_ofst(struct rtw89_dev *rtwdev)
712 {
713 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
714 struct rtw89_mcc_role *ref = &mcc->role_ref;
715 struct rtw89_mcc_role *aux = &mcc->role_aux;
716 u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval);
717 u32 tbtt_ofst_ref, tbtt_ofst_aux;
718 u64 tsf_ref, tsf_aux;
719 int ret;
720
721 if (rtw89_concurrent_via_mrc(rtwdev))
722 ret = __mrc_fw_req_tsf(rtwdev, &tsf_ref, &tsf_aux);
723 else
724 ret = __mcc_fw_req_tsf(rtwdev, &tsf_ref, &tsf_aux);
725
726 if (ret)
727 return RTW89_MCC_DFLT_BCN_OFST_TIME;
728
729 tbtt_ofst_ref = rtw89_mcc_get_tbtt_ofst(rtwdev, ref, tsf_ref);
730 tbtt_ofst_aux = rtw89_mcc_get_tbtt_ofst(rtwdev, aux, tsf_aux);
731
732 while (tbtt_ofst_ref < tbtt_ofst_aux)
733 tbtt_ofst_ref += bcn_intvl_ref_us;
734
735 return (tbtt_ofst_ref - tbtt_ofst_aux) / 1024;
736 }
737
738 static
rtw89_mcc_role_fw_macid_bitmap_set_bit(struct rtw89_mcc_role * mcc_role,unsigned int bit)739 void rtw89_mcc_role_fw_macid_bitmap_set_bit(struct rtw89_mcc_role *mcc_role,
740 unsigned int bit)
741 {
742 unsigned int idx = bit / 8;
743 unsigned int pos = bit % 8;
744
745 if (idx >= ARRAY_SIZE(mcc_role->macid_bitmap))
746 return;
747
748 mcc_role->macid_bitmap[idx] |= BIT(pos);
749 }
750
751 static
rtw89_mcc_role_fw_macid_bitmap_to_u32(struct rtw89_mcc_role * mcc_role)752 u32 rtw89_mcc_role_fw_macid_bitmap_to_u32(struct rtw89_mcc_role *mcc_role)
753 {
754 unsigned int macid;
755 unsigned int i, j;
756 u32 bitmap = 0;
757
758 for (i = 0; i < ARRAY_SIZE(mcc_role->macid_bitmap); i++) {
759 for (j = 0; j < 8; j++) {
760 macid = i * 8 + j;
761 if (macid >= 32)
762 goto out;
763
764 if (mcc_role->macid_bitmap[i] & BIT(j))
765 bitmap |= BIT(macid);
766 }
767 }
768
769 out:
770 return bitmap;
771 }
772
rtw89_mcc_role_macid_sta_iter(void * data,struct ieee80211_sta * sta)773 static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta)
774 {
775 struct rtw89_mcc_role *mcc_role = data;
776 struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif;
777 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
778 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
779 u8 macid;
780
781 if (rtwvif != target)
782 return;
783
784 macid = rtw89_sta_get_main_macid(rtwsta);
785 rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, macid);
786 }
787
rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role)788 static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev,
789 struct rtw89_mcc_role *mcc_role)
790 {
791 struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link;
792
793 rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif_link->mac_id);
794 ieee80211_iterate_stations_atomic(rtwdev->hw,
795 rtw89_mcc_role_macid_sta_iter,
796 mcc_role);
797 }
798
rtw89_mcc_fill_role_policy(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role)799 static void rtw89_mcc_fill_role_policy(struct rtw89_dev *rtwdev,
800 struct rtw89_mcc_role *mcc_role)
801 {
802 struct rtw89_mcc_policy *policy = &mcc_role->policy;
803
804 policy->c2h_rpt = RTW89_FW_MCC_C2H_RPT_ALL;
805 policy->tx_null_early = RTW89_MCC_DFLT_TX_NULL_EARLY;
806 policy->in_curr_ch = false;
807 policy->dis_sw_retry = true;
808 policy->sw_retry_count = false;
809
810 if (mcc_role->is_go)
811 policy->dis_tx_null = true;
812 else
813 policy->dis_tx_null = false;
814 }
815
rtw89_mcc_fill_role_limit(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role)816 static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev,
817 struct rtw89_mcc_role *mcc_role)
818 {
819 struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link;
820 struct ieee80211_p2p_noa_desc *noa_desc;
821 struct ieee80211_bss_conf *bss_conf;
822 u32 bcn_intvl_us = ieee80211_tu_to_usec(mcc_role->beacon_interval);
823 u32 max_toa_us, max_tob_us, max_dur_us;
824 u32 start_time, interval, duration;
825 u64 tsf, tsf_lmt;
826 int ret;
827 int i;
828
829 if (!mcc_role->is_gc)
830 return;
831
832 rtw89_p2p_noa_once_recalc(rtwvif_link);
833
834 rcu_read_lock();
835
836 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
837
838 /* find the first periodic NoA */
839 for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) {
840 noa_desc = &bss_conf->p2p_noa_attr.desc[i];
841 if (noa_desc->count == 255)
842 goto fill;
843 }
844
845 rcu_read_unlock();
846 return;
847
848 fill:
849 start_time = le32_to_cpu(noa_desc->start_time);
850 interval = le32_to_cpu(noa_desc->interval);
851 duration = le32_to_cpu(noa_desc->duration);
852
853 rcu_read_unlock();
854
855 if (interval != bcn_intvl_us) {
856 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
857 "MCC role limit: mismatch interval: %d vs. %d\n",
858 interval, bcn_intvl_us);
859 return;
860 }
861
862 ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
863 if (ret) {
864 rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
865 return;
866 }
867
868 tsf_lmt = (tsf & GENMASK_ULL(63, 32)) | start_time;
869 if (tsf_lmt < tsf)
870 tsf_lmt += roundup_u64(tsf - tsf_lmt, interval);
871
872 max_toa_us = rtw89_mcc_get_tbtt_ofst(rtwdev, mcc_role, tsf_lmt);
873 max_dur_us = interval - duration;
874 max_tob_us = max_dur_us - max_toa_us;
875
876 if (!max_toa_us || !max_tob_us) {
877 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
878 "MCC role limit: hit boundary\n");
879 return;
880 }
881
882 if (max_dur_us < max_toa_us) {
883 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
884 "MCC role limit: insufficient duration\n");
885 return;
886 }
887
888 mcc_role->limit.max_toa = max_toa_us / 1024;
889 mcc_role->limit.max_tob = max_tob_us / 1024;
890 mcc_role->limit.max_dur = mcc_role->limit.max_toa + mcc_role->limit.max_tob;
891 mcc_role->limit.enable = true;
892
893 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
894 "MCC role limit: max_toa %d, max_tob %d, max_dur %d\n",
895 mcc_role->limit.max_toa, mcc_role->limit.max_tob,
896 mcc_role->limit.max_dur);
897 }
898
rtw89_mcc_fill_role(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,struct rtw89_mcc_role * role)899 static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev,
900 struct rtw89_vif_link *rtwvif_link,
901 struct rtw89_mcc_role *role)
902 {
903 struct ieee80211_bss_conf *bss_conf;
904 const struct rtw89_chan *chan;
905
906 memset(role, 0, sizeof(*role));
907 role->rtwvif_link = rtwvif_link;
908
909 rcu_read_lock();
910
911 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
912 role->beacon_interval = bss_conf->beacon_int;
913
914 rcu_read_unlock();
915
916 if (!role->beacon_interval) {
917 rtw89_warn(rtwdev,
918 "cannot handle MCC role without beacon interval\n");
919 return -EINVAL;
920 }
921
922 role->duration = role->beacon_interval / 2;
923
924 chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
925 role->is_2ghz = chan->band_type == RTW89_BAND_2G;
926 role->is_go = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_GO;
927 role->is_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT;
928
929 rtw89_mcc_fill_role_macid_bitmap(rtwdev, role);
930 rtw89_mcc_fill_role_policy(rtwdev, role);
931 rtw89_mcc_fill_role_limit(rtwdev, role);
932
933 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
934 "MCC role: bcn_intvl %d, is_2ghz %d, is_go %d, is_gc %d\n",
935 role->beacon_interval, role->is_2ghz, role->is_go, role->is_gc);
936 return 0;
937 }
938
rtw89_mcc_fill_bt_role(struct rtw89_dev * rtwdev)939 static void rtw89_mcc_fill_bt_role(struct rtw89_dev *rtwdev)
940 {
941 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
942 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
943
944 memset(bt_role, 0, sizeof(*bt_role));
945 bt_role->duration = rtw89_coex_query_bt_req_len(rtwdev, RTW89_PHY_0);
946
947 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC bt role: dur %d\n",
948 bt_role->duration);
949 }
950
951 struct rtw89_mcc_fill_role_selector {
952 struct rtw89_vif_link *bind_vif[NUM_OF_RTW89_CHANCTX];
953 };
954
955 static_assert((u8)NUM_OF_RTW89_CHANCTX >= NUM_OF_RTW89_MCC_ROLES);
956 static_assert(RTW89_MAX_INTERFACE_NUM >= NUM_OF_RTW89_MCC_ROLES);
957
rtw89_mcc_fill_role_iterator(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role,unsigned int ordered_idx,void * data)958 static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev,
959 struct rtw89_mcc_role *mcc_role,
960 unsigned int ordered_idx,
961 void *data)
962 {
963 struct rtw89_mcc_fill_role_selector *sel = data;
964 struct rtw89_vif_link *role_vif = sel->bind_vif[ordered_idx];
965 int ret;
966
967 if (!role_vif) {
968 rtw89_warn(rtwdev, "cannot handle MCC without role[%d]\n",
969 ordered_idx);
970 return -EINVAL;
971 }
972
973 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
974 "MCC fill role[%d] with vif <macid %d>\n",
975 ordered_idx, role_vif->mac_id);
976
977 ret = rtw89_mcc_fill_role(rtwdev, role_vif, mcc_role);
978 if (ret)
979 return ret;
980
981 return 0;
982 }
983
rtw89_mcc_fill_all_roles(struct rtw89_dev * rtwdev)984 static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev)
985 {
986 struct rtw89_hal *hal = &rtwdev->hal;
987 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
988 struct rtw89_mcc_fill_role_selector sel = {};
989 struct rtw89_vif_link *rtwvif_link;
990 struct rtw89_vif *rtwvif;
991 int ret;
992 int i;
993
994 for (i = 0; i < NUM_OF_RTW89_MCC_ROLES; i++) {
995 rtwvif = mgnt->active_roles[i];
996 if (!rtwvif)
997 break;
998
999 rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
1000 if (unlikely(!rtwvif_link)) {
1001 rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n");
1002 continue;
1003 }
1004
1005 sel.bind_vif[i] = rtwvif_link;
1006 rtw89_p2p_disable_all_noa(rtwdev, rtwvif_link, NULL);
1007 }
1008
1009 ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel);
1010 if (ret)
1011 return ret;
1012
1013 rtw89_mcc_fill_bt_role(rtwdev);
1014 return 0;
1015 }
1016
rtw89_mcc_can_courtesy(const struct rtw89_mcc_role * provider,const struct rtw89_mcc_role * receiver)1017 static bool rtw89_mcc_can_courtesy(const struct rtw89_mcc_role *provider,
1018 const struct rtw89_mcc_role *receiver)
1019 {
1020 if (provider->is_go || receiver->is_gc)
1021 return false;
1022
1023 return true;
1024 }
1025
rtw89_mcc_assign_pattern(struct rtw89_dev * rtwdev,const struct rtw89_mcc_pattern * new)1026 static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev,
1027 const struct rtw89_mcc_pattern *new)
1028 {
1029 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1030 struct rtw89_mcc_role *ref = &mcc->role_ref;
1031 struct rtw89_mcc_role *aux = &mcc->role_aux;
1032 struct rtw89_mcc_config *config = &mcc->config;
1033 struct rtw89_mcc_pattern *pattern = &config->pattern;
1034 struct rtw89_mcc_courtesy_cfg *crtz;
1035
1036 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1037 "MCC assign pattern: ref {%d | %d}, aux {%d | %d}\n",
1038 new->tob_ref, new->toa_ref, new->tob_aux, new->toa_aux);
1039
1040 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC pattern plan: %d\n", new->plan);
1041
1042 *pattern = *new;
1043 memset(&pattern->courtesy, 0, sizeof(pattern->courtesy));
1044
1045 if (RTW89_MCC_REQ_COURTESY(pattern, aux) && aux->is_gc)
1046 aux->ignore_bcn = true;
1047 else
1048 aux->ignore_bcn = false;
1049
1050 if (RTW89_MCC_REQ_COURTESY(pattern, aux) && rtw89_mcc_can_courtesy(ref, aux)) {
1051 crtz = &pattern->courtesy.ref;
1052 ref->crtz = crtz;
1053
1054 crtz->macid_tgt = aux->rtwvif_link->mac_id;
1055 crtz->slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
1056
1057 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1058 "MCC courtesy ref: tgt %d, slot %d\n",
1059 crtz->macid_tgt, crtz->slot_num);
1060 } else {
1061 ref->crtz = NULL;
1062 }
1063
1064 if (RTW89_MCC_REQ_COURTESY(pattern, ref) && ref->is_gc)
1065 ref->ignore_bcn = true;
1066 else
1067 ref->ignore_bcn = false;
1068
1069 if (RTW89_MCC_REQ_COURTESY(pattern, ref) && rtw89_mcc_can_courtesy(aux, ref)) {
1070 crtz = &pattern->courtesy.aux;
1071 aux->crtz = crtz;
1072
1073 crtz->macid_tgt = ref->rtwvif_link->mac_id;
1074 crtz->slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
1075
1076 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1077 "MCC courtesy aux: tgt %d, slot %d\n",
1078 crtz->macid_tgt, crtz->slot_num);
1079 } else {
1080 aux->crtz = NULL;
1081 }
1082 }
1083
1084 /* The follow-up roughly shows the relationship between the parameters
1085 * for pattern calculation.
1086 *
1087 * |< duration ref >| (if mid bt) |< duration aux >|
1088 * |< tob ref >|< toa ref >| ... |< tob aux >|< toa aux >|
1089 * V V
1090 * tbtt ref tbtt aux
1091 * |< beacon offset >|
1092 *
1093 * In loose pattern calculation, we only ensure at least tob_ref and
1094 * toa_ref have positive results. If tob_aux or toa_aux is negative
1095 * unfortunately, FW will be notified to handle it with courtesy
1096 * mechanism.
1097 */
__rtw89_mcc_calc_pattern_loose(struct rtw89_dev * rtwdev,struct rtw89_mcc_pattern * ptrn,bool hdl_bt)1098 static void __rtw89_mcc_calc_pattern_loose(struct rtw89_dev *rtwdev,
1099 struct rtw89_mcc_pattern *ptrn,
1100 bool hdl_bt)
1101 {
1102 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1103 struct rtw89_mcc_role *ref = &mcc->role_ref;
1104 struct rtw89_mcc_role *aux = &mcc->role_aux;
1105 struct rtw89_mcc_config *config = &mcc->config;
1106 u16 mcc_intvl = config->mcc_interval;
1107 u16 bcn_ofst = config->beacon_offset;
1108 u16 bt_dur_in_mid = 0;
1109 u16 max_bcn_ofst;
1110 s16 upper, lower;
1111 u16 res;
1112
1113 *ptrn = (typeof(*ptrn)){
1114 .plan = hdl_bt ? RTW89_MCC_PLAN_TAIL_BT : RTW89_MCC_PLAN_NO_BT,
1115 };
1116
1117 if (!hdl_bt)
1118 goto calc;
1119
1120 max_bcn_ofst = ref->duration + aux->duration;
1121 if (ref->limit.enable)
1122 max_bcn_ofst = min_t(u16, max_bcn_ofst,
1123 ref->limit.max_toa + aux->duration);
1124 else if (aux->limit.enable)
1125 max_bcn_ofst = min_t(u16, max_bcn_ofst,
1126 ref->duration + aux->limit.max_tob);
1127
1128 if (bcn_ofst > max_bcn_ofst && bcn_ofst >= mcc->bt_role.duration) {
1129 bt_dur_in_mid = mcc->bt_role.duration;
1130 ptrn->plan = RTW89_MCC_PLAN_MID_BT;
1131 }
1132
1133 calc:
1134 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1135 "MCC calc ptrn_ls: plan %d, bcn_ofst %d\n",
1136 ptrn->plan, bcn_ofst);
1137
1138 res = bcn_ofst - bt_dur_in_mid;
1139 upper = min_t(s16, ref->duration, res);
1140 lower = max_t(s16, 0, ref->duration - (mcc_intvl - bcn_ofst));
1141
1142 if (ref->limit.enable) {
1143 upper = min_t(s16, upper, ref->limit.max_toa);
1144 lower = max_t(s16, lower, ref->duration - ref->limit.max_tob);
1145 } else if (aux->limit.enable) {
1146 upper = min_t(s16, upper,
1147 res - (aux->duration - aux->limit.max_toa));
1148 lower = max_t(s16, lower, res - aux->limit.max_tob);
1149 }
1150
1151 if (lower < upper)
1152 ptrn->toa_ref = (upper + lower) / 2;
1153 else
1154 ptrn->toa_ref = lower;
1155
1156 ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1157 ptrn->tob_aux = res - ptrn->toa_ref;
1158 ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1159 }
1160
1161 /* In strict pattern calculation, we consider timing that might need
1162 * for HW stuffs, i.e. min_tob and min_toa.
1163 */
__rtw89_mcc_calc_pattern_strict(struct rtw89_dev * rtwdev,struct rtw89_mcc_pattern * ptrn)1164 static int __rtw89_mcc_calc_pattern_strict(struct rtw89_dev *rtwdev,
1165 struct rtw89_mcc_pattern *ptrn)
1166 {
1167 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1168 struct rtw89_mcc_role *ref = &mcc->role_ref;
1169 struct rtw89_mcc_role *aux = &mcc->role_aux;
1170 struct rtw89_mcc_config *config = &mcc->config;
1171 u16 min_tob = RTW89_MCC_EARLY_RX_BCN_TIME + RTW89_MCC_SWITCH_CH_TIME;
1172 u16 min_toa = RTW89_MCC_MIN_RX_BCN_TIME;
1173 u16 bcn_ofst = config->beacon_offset;
1174 s16 upper_toa_ref, lower_toa_ref;
1175 s16 upper_tob_aux, lower_tob_aux;
1176 u16 bt_dur_in_mid;
1177 s16 res;
1178
1179 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1180 "MCC calc ptrn_st: plan %d, bcn_ofst %d\n",
1181 ptrn->plan, bcn_ofst);
1182
1183 if (ptrn->plan == RTW89_MCC_PLAN_MID_BT)
1184 bt_dur_in_mid = mcc->bt_role.duration;
1185 else
1186 bt_dur_in_mid = 0;
1187
1188 if (ref->duration < min_tob + min_toa) {
1189 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1190 "MCC calc ptrn_st: not meet ref dur cond\n");
1191 return -EINVAL;
1192 }
1193
1194 if (aux->duration < min_tob + min_toa) {
1195 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1196 "MCC calc ptrn_st: not meet aux dur cond\n");
1197 return -EINVAL;
1198 }
1199
1200 res = bcn_ofst - min_toa - min_tob - bt_dur_in_mid;
1201 if (res < 0) {
1202 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1203 "MCC calc ptrn_st: not meet bcn_ofst cond\n");
1204 return -EINVAL;
1205 }
1206
1207 upper_toa_ref = min_t(s16, min_toa + res, ref->duration - min_tob);
1208 lower_toa_ref = min_toa;
1209 upper_tob_aux = min_t(s16, min_tob + res, aux->duration - min_toa);
1210 lower_tob_aux = min_tob;
1211
1212 if (ref->limit.enable) {
1213 if (min_tob > ref->limit.max_tob || min_toa > ref->limit.max_toa) {
1214 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1215 "MCC calc ptrn_st: conflict ref limit\n");
1216 return -EINVAL;
1217 }
1218
1219 upper_toa_ref = min_t(s16, upper_toa_ref, ref->limit.max_toa);
1220 lower_toa_ref = max_t(s16, lower_toa_ref,
1221 ref->duration - ref->limit.max_tob);
1222 } else if (aux->limit.enable) {
1223 if (min_tob > aux->limit.max_tob || min_toa > aux->limit.max_toa) {
1224 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1225 "MCC calc ptrn_st: conflict aux limit\n");
1226 return -EINVAL;
1227 }
1228
1229 upper_tob_aux = min_t(s16, upper_tob_aux, aux->limit.max_tob);
1230 lower_tob_aux = max_t(s16, lower_tob_aux,
1231 aux->duration - aux->limit.max_toa);
1232 }
1233
1234 upper_toa_ref = min_t(s16, upper_toa_ref,
1235 bcn_ofst - bt_dur_in_mid - lower_tob_aux);
1236 lower_toa_ref = max_t(s16, lower_toa_ref,
1237 bcn_ofst - bt_dur_in_mid - upper_tob_aux);
1238 if (lower_toa_ref > upper_toa_ref) {
1239 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1240 "MCC calc ptrn_st: conflict boundary\n");
1241 return -EINVAL;
1242 }
1243
1244 ptrn->toa_ref = (upper_toa_ref + lower_toa_ref) / 2;
1245 ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1246 ptrn->tob_aux = bcn_ofst - ptrn->toa_ref - bt_dur_in_mid;
1247 ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1248 return 0;
1249 }
1250
__rtw89_mcc_fill_ptrn_anchor_ref(struct rtw89_dev * rtwdev,struct rtw89_mcc_pattern * ptrn,bool small_bcn_ofst)1251 static void __rtw89_mcc_fill_ptrn_anchor_ref(struct rtw89_dev *rtwdev,
1252 struct rtw89_mcc_pattern *ptrn,
1253 bool small_bcn_ofst)
1254 {
1255 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1256 struct rtw89_mcc_role *ref = &mcc->role_ref;
1257 struct rtw89_mcc_role *aux = &mcc->role_aux;
1258 struct rtw89_mcc_config *config = &mcc->config;
1259 u16 bcn_ofst = config->beacon_offset;
1260 u16 ref_tob;
1261 u16 ref_toa;
1262
1263 if (ref->limit.enable) {
1264 ref_tob = ref->limit.max_tob;
1265 ref_toa = ref->limit.max_toa;
1266 } else {
1267 ref_tob = ref->duration / 2;
1268 ref_toa = ref->duration / 2;
1269 }
1270
1271 if (small_bcn_ofst) {
1272 ptrn->toa_ref = ref_toa;
1273 ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1274 } else {
1275 ptrn->tob_ref = ref_tob;
1276 ptrn->toa_ref = ref->duration - ptrn->tob_ref;
1277 }
1278
1279 ptrn->tob_aux = bcn_ofst - ptrn->toa_ref;
1280 ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1281 }
1282
__rtw89_mcc_fill_ptrn_anchor_aux(struct rtw89_dev * rtwdev,struct rtw89_mcc_pattern * ptrn,bool small_bcn_ofst)1283 static void __rtw89_mcc_fill_ptrn_anchor_aux(struct rtw89_dev *rtwdev,
1284 struct rtw89_mcc_pattern *ptrn,
1285 bool small_bcn_ofst)
1286 {
1287 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1288 struct rtw89_mcc_role *ref = &mcc->role_ref;
1289 struct rtw89_mcc_role *aux = &mcc->role_aux;
1290 struct rtw89_mcc_config *config = &mcc->config;
1291 u16 bcn_ofst = config->beacon_offset;
1292 u16 aux_tob;
1293 u16 aux_toa;
1294
1295 if (aux->limit.enable) {
1296 aux_tob = aux->limit.max_tob;
1297 aux_toa = aux->limit.max_toa;
1298 } else {
1299 aux_tob = aux->duration / 2;
1300 aux_toa = aux->duration / 2;
1301 }
1302
1303 if (small_bcn_ofst) {
1304 ptrn->tob_aux = aux_tob;
1305 ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1306 } else {
1307 ptrn->toa_aux = aux_toa;
1308 ptrn->tob_aux = aux->duration - ptrn->toa_aux;
1309 }
1310
1311 ptrn->toa_ref = bcn_ofst - ptrn->tob_aux;
1312 ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1313 }
1314
__rtw89_mcc_calc_pattern_anchor(struct rtw89_dev * rtwdev,struct rtw89_mcc_pattern * ptrn,bool hdl_bt)1315 static int __rtw89_mcc_calc_pattern_anchor(struct rtw89_dev *rtwdev,
1316 struct rtw89_mcc_pattern *ptrn,
1317 bool hdl_bt)
1318 {
1319 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1320 struct rtw89_mcc_role *ref = &mcc->role_ref;
1321 struct rtw89_mcc_role *aux = &mcc->role_aux;
1322 struct rtw89_mcc_config *config = &mcc->config;
1323 u16 mcc_intvl = config->mcc_interval;
1324 u16 bcn_ofst = config->beacon_offset;
1325 bool small_bcn_ofst;
1326
1327 if (bcn_ofst < RTW89_MCC_MIN_RX_BCN_WITH_SWITCH_CH_TIME)
1328 small_bcn_ofst = true;
1329 else if (bcn_ofst < aux->duration - aux->limit.max_toa)
1330 small_bcn_ofst = true;
1331 else if (mcc_intvl - bcn_ofst < RTW89_MCC_MIN_RX_BCN_WITH_SWITCH_CH_TIME)
1332 small_bcn_ofst = false;
1333 else
1334 return -EPERM;
1335
1336 *ptrn = (typeof(*ptrn)){
1337 .plan = hdl_bt ? RTW89_MCC_PLAN_TAIL_BT : RTW89_MCC_PLAN_NO_BT,
1338 };
1339
1340 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1341 "MCC calc ptrn_ac: plan %d, bcn_ofst %d\n",
1342 ptrn->plan, bcn_ofst);
1343
1344 if (ref->is_go || ref->is_gc)
1345 __rtw89_mcc_fill_ptrn_anchor_ref(rtwdev, ptrn, small_bcn_ofst);
1346 else if (aux->is_go || aux->is_gc)
1347 __rtw89_mcc_fill_ptrn_anchor_aux(rtwdev, ptrn, small_bcn_ofst);
1348 else
1349 __rtw89_mcc_fill_ptrn_anchor_ref(rtwdev, ptrn, small_bcn_ofst);
1350
1351 return 0;
1352 }
1353
rtw89_mcc_calc_pattern(struct rtw89_dev * rtwdev,bool hdl_bt)1354 static int rtw89_mcc_calc_pattern(struct rtw89_dev *rtwdev, bool hdl_bt)
1355 {
1356 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1357 struct rtw89_mcc_role *ref = &mcc->role_ref;
1358 struct rtw89_mcc_role *aux = &mcc->role_aux;
1359 bool sel_plan[NUM_OF_RTW89_MCC_PLAN] = {};
1360 struct rtw89_mcc_pattern ptrn;
1361 int ret;
1362 int i;
1363
1364 if (ref->limit.enable && aux->limit.enable) {
1365 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1366 "MCC calc ptrn: not support dual limited roles\n");
1367 return -EINVAL;
1368 }
1369
1370 if (ref->limit.enable &&
1371 ref->duration > ref->limit.max_tob + ref->limit.max_toa) {
1372 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1373 "MCC calc ptrn: not fit ref limit\n");
1374 return -EINVAL;
1375 }
1376
1377 if (aux->limit.enable &&
1378 aux->duration > aux->limit.max_tob + aux->limit.max_toa) {
1379 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1380 "MCC calc ptrn: not fit aux limit\n");
1381 return -EINVAL;
1382 }
1383
1384 if (hdl_bt) {
1385 sel_plan[RTW89_MCC_PLAN_TAIL_BT] = true;
1386 sel_plan[RTW89_MCC_PLAN_MID_BT] = true;
1387 } else {
1388 sel_plan[RTW89_MCC_PLAN_NO_BT] = true;
1389 }
1390
1391 for (i = 0; i < NUM_OF_RTW89_MCC_PLAN; i++) {
1392 if (!sel_plan[i])
1393 continue;
1394
1395 ptrn = (typeof(ptrn)){
1396 .plan = i,
1397 };
1398
1399 ret = __rtw89_mcc_calc_pattern_strict(rtwdev, &ptrn);
1400 if (ret)
1401 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1402 "MCC calc ptrn_st with plan %d: fail\n", i);
1403 else
1404 goto done;
1405 }
1406
1407 ret = __rtw89_mcc_calc_pattern_anchor(rtwdev, &ptrn, hdl_bt);
1408 if (!ret)
1409 goto done;
1410
1411 __rtw89_mcc_calc_pattern_loose(rtwdev, &ptrn, hdl_bt);
1412
1413 done:
1414 rtw89_mcc_assign_pattern(rtwdev, &ptrn);
1415 return 0;
1416 }
1417
rtw89_mcc_set_default_pattern(struct rtw89_dev * rtwdev)1418 static void rtw89_mcc_set_default_pattern(struct rtw89_dev *rtwdev)
1419 {
1420 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1421 struct rtw89_mcc_role *ref = &mcc->role_ref;
1422 struct rtw89_mcc_role *aux = &mcc->role_aux;
1423 struct rtw89_mcc_pattern tmp = {};
1424
1425 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1426 "MCC use default pattern unexpectedly\n");
1427
1428 tmp.plan = RTW89_MCC_PLAN_NO_BT;
1429 tmp.tob_ref = ref->duration / 2;
1430 tmp.toa_ref = ref->duration - tmp.tob_ref;
1431 tmp.tob_aux = aux->duration / 2;
1432 tmp.toa_aux = aux->duration - tmp.tob_aux;
1433
1434 rtw89_mcc_assign_pattern(rtwdev, &tmp);
1435 }
1436
rtw89_mcc_set_duration_go_sta(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * role_go,struct rtw89_mcc_role * role_sta)1437 static void rtw89_mcc_set_duration_go_sta(struct rtw89_dev *rtwdev,
1438 struct rtw89_mcc_role *role_go,
1439 struct rtw89_mcc_role *role_sta)
1440 {
1441 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1442 struct rtw89_mcc_config *config = &mcc->config;
1443 u16 mcc_intvl = config->mcc_interval;
1444 u16 dur_go, dur_sta;
1445
1446 dur_go = clamp_t(u16, role_go->duration, RTW89_MCC_MIN_GO_DURATION,
1447 mcc_intvl - RTW89_MCC_MIN_STA_DURATION);
1448 if (role_go->limit.enable)
1449 dur_go = min(dur_go, role_go->limit.max_dur);
1450 dur_sta = mcc_intvl - dur_go;
1451
1452 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1453 "MCC set dur: (go, sta) {%d, %d} -> {%d, %d}\n",
1454 role_go->duration, role_sta->duration, dur_go, dur_sta);
1455
1456 role_go->duration = dur_go;
1457 role_sta->duration = dur_sta;
1458 }
1459
rtw89_mcc_set_duration_gc_sta(struct rtw89_dev * rtwdev)1460 static void rtw89_mcc_set_duration_gc_sta(struct rtw89_dev *rtwdev)
1461 {
1462 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1463 struct rtw89_mcc_role *ref = &mcc->role_ref;
1464 struct rtw89_mcc_role *aux = &mcc->role_aux;
1465 struct rtw89_mcc_config *config = &mcc->config;
1466 u16 mcc_intvl = config->mcc_interval;
1467 u16 dur_ref, dur_aux;
1468
1469 if (ref->duration < RTW89_MCC_MIN_STA_DURATION) {
1470 dur_ref = RTW89_MCC_MIN_STA_DURATION;
1471 dur_aux = mcc_intvl - dur_ref;
1472 } else if (aux->duration < RTW89_MCC_MIN_STA_DURATION) {
1473 dur_aux = RTW89_MCC_MIN_STA_DURATION;
1474 dur_ref = mcc_intvl - dur_aux;
1475 } else {
1476 dur_ref = ref->duration;
1477 dur_aux = mcc_intvl - dur_ref;
1478 }
1479
1480 if (ref->limit.enable) {
1481 dur_ref = min(dur_ref, ref->limit.max_dur);
1482 dur_aux = mcc_intvl - dur_ref;
1483 } else if (aux->limit.enable) {
1484 dur_aux = min(dur_aux, aux->limit.max_dur);
1485 dur_ref = mcc_intvl - dur_aux;
1486 }
1487
1488 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1489 "MCC set dur: (ref, aux) {%d ~ %d} -> {%d ~ %d}\n",
1490 ref->duration, aux->duration, dur_ref, dur_aux);
1491
1492 ref->duration = dur_ref;
1493 aux->duration = dur_aux;
1494 }
1495
1496 struct rtw89_mcc_mod_dur_data {
1497 u16 available;
1498 struct {
1499 u16 dur;
1500 u16 room;
1501 } parm[NUM_OF_RTW89_MCC_ROLES];
1502 };
1503
rtw89_mcc_mod_dur_get_iterator(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role,unsigned int ordered_idx,void * data)1504 static int rtw89_mcc_mod_dur_get_iterator(struct rtw89_dev *rtwdev,
1505 struct rtw89_mcc_role *mcc_role,
1506 unsigned int ordered_idx,
1507 void *data)
1508 {
1509 struct rtw89_mcc_mod_dur_data *p = data;
1510 u16 min;
1511
1512 p->parm[ordered_idx].dur = mcc_role->duration;
1513
1514 if (mcc_role->is_go)
1515 min = RTW89_MCC_MIN_GO_DURATION;
1516 else
1517 min = RTW89_MCC_MIN_STA_DURATION;
1518
1519 p->parm[ordered_idx].room = max_t(s32, p->parm[ordered_idx].dur - min, 0);
1520
1521 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1522 "MCC mod dur: chk role[%u]: dur %u, min %u, room %u\n",
1523 ordered_idx, p->parm[ordered_idx].dur, min,
1524 p->parm[ordered_idx].room);
1525
1526 p->available += p->parm[ordered_idx].room;
1527 return 0;
1528 }
1529
rtw89_mcc_mod_dur_put_iterator(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role,unsigned int ordered_idx,void * data)1530 static int rtw89_mcc_mod_dur_put_iterator(struct rtw89_dev *rtwdev,
1531 struct rtw89_mcc_role *mcc_role,
1532 unsigned int ordered_idx,
1533 void *data)
1534 {
1535 struct rtw89_mcc_mod_dur_data *p = data;
1536
1537 mcc_role->duration = p->parm[ordered_idx].dur;
1538
1539 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1540 "MCC mod dur: set role[%u]: dur %u\n",
1541 ordered_idx, p->parm[ordered_idx].dur);
1542 return 0;
1543 }
1544
rtw89_mcc_mod_duration_dual_2ghz_with_bt(struct rtw89_dev * rtwdev)1545 static void rtw89_mcc_mod_duration_dual_2ghz_with_bt(struct rtw89_dev *rtwdev)
1546 {
1547 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1548 struct rtw89_mcc_config *config = &mcc->config;
1549 struct rtw89_mcc_mod_dur_data data = {};
1550 u16 mcc_intvl = config->mcc_interval;
1551 u16 bt_dur = mcc->bt_role.duration;
1552 u16 wifi_dur;
1553
1554 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1555 "MCC mod dur (dual 2ghz): mcc_intvl %u, raw bt_dur %u\n",
1556 mcc_intvl, bt_dur);
1557
1558 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_get_iterator, &data);
1559
1560 bt_dur = clamp_t(u16, bt_dur, 1, data.available / 3);
1561 wifi_dur = mcc_intvl - bt_dur;
1562
1563 if (data.parm[0].room <= data.parm[1].room) {
1564 data.parm[0].dur -= min_t(u16, bt_dur / 2, data.parm[0].room);
1565 data.parm[1].dur = wifi_dur - data.parm[0].dur;
1566 } else {
1567 data.parm[1].dur -= min_t(u16, bt_dur / 2, data.parm[1].room);
1568 data.parm[0].dur = wifi_dur - data.parm[1].dur;
1569 }
1570
1571 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_put_iterator, &data);
1572
1573 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC mod dur: set bt: dur %u\n", bt_dur);
1574 mcc->bt_role.duration = bt_dur;
1575 }
1576
1577 static
rtw89_mcc_mod_duration_diff_band_with_bt(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * role_2ghz,struct rtw89_mcc_role * role_non_2ghz)1578 void rtw89_mcc_mod_duration_diff_band_with_bt(struct rtw89_dev *rtwdev,
1579 struct rtw89_mcc_role *role_2ghz,
1580 struct rtw89_mcc_role *role_non_2ghz)
1581 {
1582 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1583 struct rtw89_mcc_config *config = &mcc->config;
1584 u16 dur_2ghz, dur_non_2ghz;
1585 u16 bt_dur, mcc_intvl;
1586
1587 dur_2ghz = role_2ghz->duration;
1588 dur_non_2ghz = role_non_2ghz->duration;
1589 mcc_intvl = config->mcc_interval;
1590 bt_dur = mcc->bt_role.duration;
1591
1592 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1593 "MCC mod dur (diff band): mcc_intvl %u, bt_dur %u\n",
1594 mcc_intvl, bt_dur);
1595
1596 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1597 "MCC mod dur: check dur_2ghz %u, dur_non_2ghz %u\n",
1598 dur_2ghz, dur_non_2ghz);
1599
1600 if (dur_non_2ghz >= bt_dur) {
1601 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1602 "MCC mod dur: dur_non_2ghz is enough for bt\n");
1603 return;
1604 }
1605
1606 dur_non_2ghz = bt_dur;
1607 dur_2ghz = mcc_intvl - dur_non_2ghz;
1608
1609 if (role_non_2ghz->limit.enable) {
1610 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1611 "MCC mod dur: dur_non_2ghz is limited with max %u\n",
1612 role_non_2ghz->limit.max_dur);
1613
1614 dur_non_2ghz = min(dur_non_2ghz, role_non_2ghz->limit.max_dur);
1615 dur_2ghz = mcc_intvl - dur_non_2ghz;
1616 }
1617
1618 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1619 "MCC mod dur: set dur_2ghz %u, dur_non_2ghz %u\n",
1620 dur_2ghz, dur_non_2ghz);
1621
1622 role_2ghz->duration = dur_2ghz;
1623 role_non_2ghz->duration = dur_non_2ghz;
1624 }
1625
rtw89_mcc_duration_decision_on_bt(struct rtw89_dev * rtwdev)1626 static bool rtw89_mcc_duration_decision_on_bt(struct rtw89_dev *rtwdev)
1627 {
1628 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1629 struct rtw89_mcc_role *ref = &mcc->role_ref;
1630 struct rtw89_mcc_role *aux = &mcc->role_aux;
1631 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1632
1633 if (!bt_role->duration)
1634 return false;
1635
1636 if (ref->is_2ghz && aux->is_2ghz) {
1637 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1638 "MCC dual roles are on 2GHz; consider BT duration\n");
1639
1640 rtw89_mcc_mod_duration_dual_2ghz_with_bt(rtwdev);
1641 return true;
1642 }
1643
1644 if (!ref->is_2ghz && !aux->is_2ghz) {
1645 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1646 "MCC dual roles are not on 2GHz; ignore BT duration\n");
1647 return false;
1648 }
1649
1650 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1651 "MCC one role is on 2GHz; modify another for BT duration\n");
1652
1653 if (ref->is_2ghz)
1654 rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, ref, aux);
1655 else
1656 rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, aux, ref);
1657
1658 return false;
1659 }
1660
rtw89_mcc_prepare_done_work(struct wiphy * wiphy,struct wiphy_work * work)1661 void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work)
1662 {
1663 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
1664 mcc_prepare_done_work.work);
1665
1666 lockdep_assert_wiphy(wiphy);
1667
1668 ieee80211_wake_queues(rtwdev->hw);
1669 }
1670
rtw89_mcc_prepare(struct rtw89_dev * rtwdev,bool start)1671 static void rtw89_mcc_prepare(struct rtw89_dev *rtwdev, bool start)
1672 {
1673 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1674 struct rtw89_mcc_config *config = &mcc->config;
1675
1676 if (start) {
1677 ieee80211_stop_queues(rtwdev->hw);
1678
1679 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
1680 &rtwdev->mcc_prepare_done_work,
1681 usecs_to_jiffies(config->prepare_delay));
1682 } else {
1683 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
1684 &rtwdev->mcc_prepare_done_work, 0);
1685 wiphy_delayed_work_flush(rtwdev->hw->wiphy,
1686 &rtwdev->mcc_prepare_done_work);
1687 }
1688 }
1689
rtw89_mcc_fill_start_tsf(struct rtw89_dev * rtwdev)1690 static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev)
1691 {
1692 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1693 struct rtw89_mcc_role *ref = &mcc->role_ref;
1694 struct rtw89_mcc_role *aux = &mcc->role_aux;
1695 struct rtw89_mcc_config *config = &mcc->config;
1696 u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval);
1697 s32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref);
1698 u64 tsf, start_tsf;
1699 u32 cur_tbtt_ofst;
1700 u64 min_time;
1701 u64 tsf_aux;
1702 int ret;
1703
1704 if (rtw89_concurrent_via_mrc(rtwdev))
1705 ret = __mrc_fw_req_tsf(rtwdev, &tsf, &tsf_aux);
1706 else
1707 ret = __mcc_fw_req_tsf(rtwdev, &tsf, &tsf_aux);
1708
1709 if (ret)
1710 return ret;
1711
1712 min_time = tsf;
1713 if (ref->is_go || aux->is_go)
1714 min_time += ieee80211_tu_to_usec(RTW89_MCC_SHORT_TRIGGER_TIME);
1715 else
1716 min_time += ieee80211_tu_to_usec(RTW89_MCC_LONG_TRIGGER_TIME);
1717
1718 cur_tbtt_ofst = rtw89_mcc_get_tbtt_ofst(rtwdev, ref, tsf);
1719 start_tsf = tsf - cur_tbtt_ofst + bcn_intvl_ref_us - tob_ref_us;
1720 if (start_tsf < min_time)
1721 start_tsf += roundup_u64(min_time - start_tsf, bcn_intvl_ref_us);
1722
1723 config->start_tsf = start_tsf;
1724 config->start_tsf_in_aux_domain = tsf_aux + start_tsf - tsf;
1725 config->prepare_delay = start_tsf - tsf;
1726
1727 return 0;
1728 }
1729
rtw89_mcc_fill_config(struct rtw89_dev * rtwdev)1730 static int rtw89_mcc_fill_config(struct rtw89_dev *rtwdev)
1731 {
1732 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1733 struct rtw89_mcc_role *ref = &mcc->role_ref;
1734 struct rtw89_mcc_role *aux = &mcc->role_aux;
1735 struct rtw89_mcc_config *config = &mcc->config;
1736 bool hdl_bt;
1737 int ret;
1738
1739 memset(config, 0, sizeof(*config));
1740
1741 switch (mcc->mode) {
1742 case RTW89_MCC_MODE_GO_STA:
1743 config->beacon_offset = rtw89_mcc_get_bcn_ofst(rtwdev);
1744 if (ref->is_go) {
1745 config->mcc_interval = ref->beacon_interval;
1746 rtw89_mcc_set_duration_go_sta(rtwdev, ref, aux);
1747 } else {
1748 config->mcc_interval = aux->beacon_interval;
1749 rtw89_mcc_set_duration_go_sta(rtwdev, aux, ref);
1750 }
1751 break;
1752 case RTW89_MCC_MODE_GC_STA:
1753 config->beacon_offset = rtw89_mcc_get_bcn_ofst(rtwdev);
1754 config->mcc_interval = ref->beacon_interval;
1755 rtw89_mcc_set_duration_gc_sta(rtwdev);
1756 break;
1757 default:
1758 rtw89_warn(rtwdev, "MCC unknown mode: %d\n", mcc->mode);
1759 return -EFAULT;
1760 }
1761
1762 hdl_bt = rtw89_mcc_duration_decision_on_bt(rtwdev);
1763 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC handle bt: %d\n", hdl_bt);
1764
1765 ret = rtw89_mcc_calc_pattern(rtwdev, hdl_bt);
1766 if (!ret)
1767 goto bottom;
1768
1769 rtw89_mcc_set_default_pattern(rtwdev);
1770
1771 bottom:
1772 return rtw89_mcc_fill_start_tsf(rtwdev);
1773 }
1774
__mcc_fw_add_role(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * role)1775 static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role)
1776 {
1777 const struct rtw89_mcc_courtesy_cfg *crtz = role->crtz;
1778 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1779 struct rtw89_mcc_policy *policy = &role->policy;
1780 struct rtw89_fw_mcc_add_req req = {};
1781 const struct rtw89_chan *chan;
1782 int ret;
1783
1784 chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx);
1785 req.central_ch_seg0 = chan->channel;
1786 req.primary_ch = chan->primary_channel;
1787 req.bandwidth = chan->band_width;
1788 req.ch_band_type = chan->band_type;
1789
1790 req.macid = role->rtwvif_link->mac_id;
1791 req.group = mcc->group;
1792 req.c2h_rpt = policy->c2h_rpt;
1793 req.tx_null_early = policy->tx_null_early;
1794 req.dis_tx_null = policy->dis_tx_null;
1795 req.in_curr_ch = policy->in_curr_ch;
1796 req.sw_retry_count = policy->sw_retry_count;
1797 req.dis_sw_retry = policy->dis_sw_retry;
1798 req.duration = role->duration;
1799 req.btc_in_2g = false;
1800
1801 if (crtz) {
1802 req.courtesy_target = crtz->macid_tgt;
1803 req.courtesy_num = crtz->slot_num;
1804 req.courtesy_en = true;
1805 }
1806
1807 ret = rtw89_fw_h2c_add_mcc(rtwdev, &req);
1808 if (ret) {
1809 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1810 "MCC h2c failed to add wifi role: %d\n", ret);
1811 return ret;
1812 }
1813
1814 ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group,
1815 role->rtwvif_link->mac_id,
1816 role->macid_bitmap);
1817 if (ret) {
1818 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1819 "MCC h2c failed to set macid bitmap: %d\n", ret);
1820 return ret;
1821 }
1822
1823 return 0;
1824 }
1825
1826 static
__mrc_fw_add_role(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * role,struct rtw89_fw_mrc_add_arg * arg,u8 slot_idx)1827 void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role,
1828 struct rtw89_fw_mrc_add_arg *arg, u8 slot_idx)
1829 {
1830 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1831 struct rtw89_mcc_role *ref = &mcc->role_ref;
1832 struct rtw89_mcc_policy *policy = &role->policy;
1833 struct rtw89_fw_mrc_add_slot_arg *slot_arg;
1834 const struct rtw89_chan *chan;
1835
1836 slot_arg = &arg->slots[slot_idx];
1837 role->slot_idx = slot_idx;
1838
1839 slot_arg->duration = role->duration;
1840 slot_arg->role_num = 1;
1841
1842 chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx);
1843
1844 slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_WIFI;
1845 slot_arg->roles[0].is_master = role == ref;
1846 slot_arg->roles[0].band = chan->band_type;
1847 slot_arg->roles[0].bw = chan->band_width;
1848 slot_arg->roles[0].central_ch = chan->channel;
1849 slot_arg->roles[0].primary_ch = chan->primary_channel;
1850 slot_arg->roles[0].en_tx_null = !policy->dis_tx_null;
1851 slot_arg->roles[0].null_early = policy->tx_null_early;
1852 slot_arg->roles[0].macid = role->rtwvif_link->mac_id;
1853 slot_arg->roles[0].macid_main_bitmap =
1854 rtw89_mcc_role_fw_macid_bitmap_to_u32(role);
1855 }
1856
__mcc_fw_add_bt_role(struct rtw89_dev * rtwdev)1857 static int __mcc_fw_add_bt_role(struct rtw89_dev *rtwdev)
1858 {
1859 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1860 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1861 struct rtw89_fw_mcc_add_req req = {};
1862 int ret;
1863
1864 req.group = mcc->group;
1865 req.duration = bt_role->duration;
1866 req.btc_in_2g = true;
1867
1868 ret = rtw89_fw_h2c_add_mcc(rtwdev, &req);
1869 if (ret) {
1870 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1871 "MCC h2c failed to add bt role: %d\n", ret);
1872 return ret;
1873 }
1874
1875 return 0;
1876 }
1877
1878 static
__mrc_fw_add_bt_role(struct rtw89_dev * rtwdev,struct rtw89_fw_mrc_add_arg * arg,u8 slot_idx)1879 void __mrc_fw_add_bt_role(struct rtw89_dev *rtwdev,
1880 struct rtw89_fw_mrc_add_arg *arg, u8 slot_idx)
1881 {
1882 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1883 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1884 struct rtw89_fw_mrc_add_slot_arg *slot_arg = &arg->slots[slot_idx];
1885
1886 slot_arg->duration = bt_role->duration;
1887 slot_arg->role_num = 1;
1888
1889 slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_BT;
1890 }
1891
__mcc_fw_start(struct rtw89_dev * rtwdev,bool replace)1892 static int __mcc_fw_start(struct rtw89_dev *rtwdev, bool replace)
1893 {
1894 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1895 struct rtw89_mcc_role *ref = &mcc->role_ref;
1896 struct rtw89_mcc_role *aux = &mcc->role_aux;
1897 struct rtw89_mcc_config *config = &mcc->config;
1898 struct rtw89_mcc_pattern *pattern = &config->pattern;
1899 struct rtw89_mcc_sync *sync = &config->sync;
1900 struct rtw89_fw_mcc_start_req req = {};
1901 int ret;
1902
1903 if (replace) {
1904 req.old_group = mcc->group;
1905 req.old_group_action = RTW89_FW_MCC_OLD_GROUP_ACT_REPLACE;
1906 mcc->group = RTW89_MCC_NEXT_GROUP(mcc->group);
1907 }
1908
1909 req.group = mcc->group;
1910
1911 switch (pattern->plan) {
1912 case RTW89_MCC_PLAN_TAIL_BT:
1913 ret = __mcc_fw_add_role(rtwdev, ref);
1914 if (ret)
1915 return ret;
1916 ret = __mcc_fw_add_role(rtwdev, aux);
1917 if (ret)
1918 return ret;
1919 ret = __mcc_fw_add_bt_role(rtwdev);
1920 if (ret)
1921 return ret;
1922
1923 req.btc_in_group = true;
1924 break;
1925 case RTW89_MCC_PLAN_MID_BT:
1926 ret = __mcc_fw_add_role(rtwdev, ref);
1927 if (ret)
1928 return ret;
1929 ret = __mcc_fw_add_bt_role(rtwdev);
1930 if (ret)
1931 return ret;
1932 ret = __mcc_fw_add_role(rtwdev, aux);
1933 if (ret)
1934 return ret;
1935
1936 req.btc_in_group = true;
1937 break;
1938 case RTW89_MCC_PLAN_NO_BT:
1939 ret = __mcc_fw_add_role(rtwdev, ref);
1940 if (ret)
1941 return ret;
1942 ret = __mcc_fw_add_role(rtwdev, aux);
1943 if (ret)
1944 return ret;
1945
1946 req.btc_in_group = false;
1947 break;
1948 default:
1949 rtw89_warn(rtwdev, "MCC unknown plan: %d\n", pattern->plan);
1950 return -EFAULT;
1951 }
1952
1953 if (sync->enable) {
1954 ret = rtw89_fw_h2c_mcc_sync(rtwdev, req.group, sync->macid_src,
1955 sync->macid_tgt, sync->offset);
1956 if (ret) {
1957 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1958 "MCC h2c failed to trigger sync: %d\n", ret);
1959 return ret;
1960 }
1961 }
1962
1963 req.macid = ref->rtwvif_link->mac_id;
1964 req.tsf_high = config->start_tsf >> 32;
1965 req.tsf_low = config->start_tsf;
1966
1967 ret = rtw89_fw_h2c_start_mcc(rtwdev, &req);
1968 if (ret) {
1969 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1970 "MCC h2c failed to trigger start: %d\n", ret);
1971 return ret;
1972 }
1973
1974 return 0;
1975 }
1976
__mrc_fw_add_courtesy(struct rtw89_dev * rtwdev,struct rtw89_fw_mrc_add_arg * arg)1977 static void __mrc_fw_add_courtesy(struct rtw89_dev *rtwdev,
1978 struct rtw89_fw_mrc_add_arg *arg)
1979 {
1980 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1981 struct rtw89_mcc_role *ref = &mcc->role_ref;
1982 struct rtw89_mcc_role *aux = &mcc->role_aux;
1983 struct rtw89_fw_mrc_add_slot_arg *slot_arg_src;
1984
1985 if (ref->crtz) {
1986 slot_arg_src = &arg->slots[ref->slot_idx];
1987
1988 slot_arg_src->courtesy_target = aux->slot_idx;
1989 slot_arg_src->courtesy_period = ref->crtz->slot_num;
1990 slot_arg_src->courtesy_en = true;
1991 }
1992
1993 if (aux->crtz) {
1994 slot_arg_src = &arg->slots[aux->slot_idx];
1995
1996 slot_arg_src->courtesy_target = ref->slot_idx;
1997 slot_arg_src->courtesy_period = aux->crtz->slot_num;
1998 slot_arg_src->courtesy_en = true;
1999 }
2000 }
2001
__mrc_fw_start(struct rtw89_dev * rtwdev,bool replace)2002 static int __mrc_fw_start(struct rtw89_dev *rtwdev, bool replace)
2003 {
2004 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2005 struct rtw89_mcc_role *ref = &mcc->role_ref;
2006 struct rtw89_mcc_role *aux = &mcc->role_aux;
2007 struct rtw89_mcc_config *config = &mcc->config;
2008 struct rtw89_mcc_pattern *pattern = &config->pattern;
2009 struct rtw89_mcc_sync *sync = &config->sync;
2010 struct rtw89_fw_mrc_start_arg start_arg = {};
2011 struct rtw89_fw_mrc_add_arg add_arg = {};
2012 int ret;
2013
2014 BUILD_BUG_ON(RTW89_MAC_MRC_MAX_ADD_SLOT_NUM <
2015 NUM_OF_RTW89_MCC_ROLES + 1 /* bt role */);
2016
2017 if (replace) {
2018 start_arg.old_sch_idx = mcc->group;
2019 start_arg.action = RTW89_H2C_MRC_START_ACTION_REPLACE_OLD;
2020 mcc->group = RTW89_MCC_NEXT_GROUP(mcc->group);
2021 }
2022
2023 add_arg.sch_idx = mcc->group;
2024 add_arg.sch_type = RTW89_H2C_MRC_SCH_BAND0_ONLY;
2025
2026 switch (pattern->plan) {
2027 case RTW89_MCC_PLAN_TAIL_BT:
2028 __mrc_fw_add_role(rtwdev, ref, &add_arg, 0);
2029 __mrc_fw_add_role(rtwdev, aux, &add_arg, 1);
2030 __mrc_fw_add_bt_role(rtwdev, &add_arg, 2);
2031
2032 add_arg.slot_num = 3;
2033 add_arg.btc_in_sch = true;
2034 break;
2035 case RTW89_MCC_PLAN_MID_BT:
2036 __mrc_fw_add_role(rtwdev, ref, &add_arg, 0);
2037 __mrc_fw_add_bt_role(rtwdev, &add_arg, 1);
2038 __mrc_fw_add_role(rtwdev, aux, &add_arg, 2);
2039
2040 add_arg.slot_num = 3;
2041 add_arg.btc_in_sch = true;
2042 break;
2043 case RTW89_MCC_PLAN_NO_BT:
2044 __mrc_fw_add_role(rtwdev, ref, &add_arg, 0);
2045 __mrc_fw_add_role(rtwdev, aux, &add_arg, 1);
2046
2047 add_arg.slot_num = 2;
2048 add_arg.btc_in_sch = false;
2049 break;
2050 default:
2051 rtw89_warn(rtwdev, "MCC unknown plan: %d\n", pattern->plan);
2052 return -EFAULT;
2053 }
2054
2055 __mrc_fw_add_courtesy(rtwdev, &add_arg);
2056
2057 ret = rtw89_fw_h2c_mrc_add(rtwdev, &add_arg);
2058 if (ret) {
2059 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2060 "MRC h2c failed to trigger add: %d\n", ret);
2061 return ret;
2062 }
2063
2064 if (sync->enable) {
2065 struct rtw89_fw_mrc_sync_arg sync_arg = {
2066 .offset = sync->offset,
2067 .src = {
2068 .band = sync->band_src,
2069 .port = sync->port_src,
2070 },
2071 .dest = {
2072 .band = sync->band_tgt,
2073 .port = sync->port_tgt,
2074 },
2075 };
2076
2077 ret = rtw89_fw_h2c_mrc_sync(rtwdev, &sync_arg);
2078 if (ret) {
2079 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2080 "MRC h2c failed to trigger sync: %d\n", ret);
2081 return ret;
2082 }
2083 }
2084
2085 start_arg.sch_idx = mcc->group;
2086 start_arg.start_tsf = config->start_tsf;
2087
2088 ret = rtw89_fw_h2c_mrc_start(rtwdev, &start_arg);
2089 if (ret) {
2090 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2091 "MRC h2c failed to trigger start: %d\n", ret);
2092 return ret;
2093 }
2094
2095 return 0;
2096 }
2097
__mcc_fw_set_duration_no_bt(struct rtw89_dev * rtwdev,bool sync_changed)2098 static int __mcc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_changed)
2099 {
2100 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2101 struct rtw89_mcc_config *config = &mcc->config;
2102 struct rtw89_mcc_sync *sync = &config->sync;
2103 struct rtw89_mcc_role *ref = &mcc->role_ref;
2104 struct rtw89_mcc_role *aux = &mcc->role_aux;
2105 struct rtw89_fw_mcc_duration req = {
2106 .group = mcc->group,
2107 .btc_in_group = false,
2108 .start_macid = ref->rtwvif_link->mac_id,
2109 .macid_x = ref->rtwvif_link->mac_id,
2110 .macid_y = aux->rtwvif_link->mac_id,
2111 .duration_x = ref->duration,
2112 .duration_y = aux->duration,
2113 .start_tsf_high = config->start_tsf >> 32,
2114 .start_tsf_low = config->start_tsf,
2115 };
2116 int ret;
2117
2118 ret = rtw89_fw_h2c_mcc_set_duration(rtwdev, &req);
2119 if (ret) {
2120 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2121 "MCC h2c failed to set duration: %d\n", ret);
2122 return ret;
2123 }
2124
2125 if (!sync->enable || !sync_changed)
2126 return 0;
2127
2128 ret = rtw89_fw_h2c_mcc_sync(rtwdev, mcc->group, sync->macid_src,
2129 sync->macid_tgt, sync->offset);
2130 if (ret) {
2131 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2132 "MCC h2c failed to trigger sync: %d\n", ret);
2133 return ret;
2134 }
2135
2136 return 0;
2137 }
2138
__mrc_fw_set_duration_no_bt(struct rtw89_dev * rtwdev,bool sync_changed)2139 static int __mrc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_changed)
2140 {
2141 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2142 struct rtw89_mcc_config *config = &mcc->config;
2143 struct rtw89_mcc_sync *sync = &config->sync;
2144 struct rtw89_mcc_role *ref = &mcc->role_ref;
2145 struct rtw89_mcc_role *aux = &mcc->role_aux;
2146 struct rtw89_fw_mrc_upd_duration_arg dur_arg = {
2147 .sch_idx = mcc->group,
2148 .start_tsf = config->start_tsf,
2149 .slot_num = 2,
2150 .slots[0] = {
2151 .slot_idx = ref->slot_idx,
2152 .duration = ref->duration,
2153 },
2154 .slots[1] = {
2155 .slot_idx = aux->slot_idx,
2156 .duration = aux->duration,
2157 },
2158 };
2159 struct rtw89_fw_mrc_sync_arg sync_arg = {
2160 .offset = sync->offset,
2161 .src = {
2162 .band = sync->band_src,
2163 .port = sync->port_src,
2164 },
2165 .dest = {
2166 .band = sync->band_tgt,
2167 .port = sync->port_tgt,
2168 },
2169
2170 };
2171 int ret;
2172
2173 ret = rtw89_fw_h2c_mrc_upd_duration(rtwdev, &dur_arg);
2174 if (ret) {
2175 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2176 "MRC h2c failed to update duration: %d\n", ret);
2177 return ret;
2178 }
2179
2180 if (!sync->enable || !sync_changed)
2181 return 0;
2182
2183 ret = rtw89_fw_h2c_mrc_sync(rtwdev, &sync_arg);
2184 if (ret) {
2185 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2186 "MRC h2c failed to trigger sync: %d\n", ret);
2187 return ret;
2188 }
2189
2190 return 0;
2191 }
2192
rtw89_mcc_handle_beacon_noa(struct rtw89_dev * rtwdev,bool enable)2193 static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable)
2194 {
2195 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2196 struct rtw89_mcc_role *ref = &mcc->role_ref;
2197 struct rtw89_mcc_role *aux = &mcc->role_aux;
2198 struct rtw89_mcc_config *config = &mcc->config;
2199 struct ieee80211_p2p_noa_desc noa_desc = {};
2200 u32 interval = config->mcc_interval;
2201 struct rtw89_vif_link *rtwvif_go;
2202 u64 start_time;
2203 u32 duration;
2204
2205 if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2206 return;
2207
2208 if (ref->is_go) {
2209 start_time = config->start_tsf;
2210 rtwvif_go = ref->rtwvif_link;
2211 start_time += ieee80211_tu_to_usec(ref->duration);
2212 duration = config->mcc_interval - ref->duration;
2213 } else if (aux->is_go) {
2214 start_time = config->start_tsf_in_aux_domain;
2215 rtwvif_go = aux->rtwvif_link;
2216 duration = config->mcc_interval - aux->duration;
2217 } else {
2218 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2219 "MCC find no GO: skip updating beacon NoA\n");
2220 return;
2221 }
2222
2223 rtw89_p2p_noa_renew(rtwvif_go);
2224
2225 if (enable) {
2226 duration += RTW89_MCC_SWITCH_CH_TIME;
2227 noa_desc.start_time = cpu_to_le32(start_time);
2228 noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(interval));
2229 noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(duration));
2230 noa_desc.count = 255;
2231 rtw89_p2p_noa_append(rtwvif_go, &noa_desc);
2232 }
2233
2234 /* without chanctx, we cannot get beacon from mac80211 stack */
2235 if (!rtwvif_go->chanctx_assigned)
2236 return;
2237
2238 rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_go);
2239 }
2240
rtw89_mcc_start_beacon_noa(struct rtw89_dev * rtwdev)2241 static void rtw89_mcc_start_beacon_noa(struct rtw89_dev *rtwdev)
2242 {
2243 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2244 struct rtw89_mcc_role *ref = &mcc->role_ref;
2245 struct rtw89_mcc_role *aux = &mcc->role_aux;
2246
2247 if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2248 return;
2249
2250 if (ref->is_go)
2251 rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, true);
2252 else if (aux->is_go)
2253 rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, true);
2254
2255 rtw89_mcc_handle_beacon_noa(rtwdev, true);
2256 }
2257
rtw89_mcc_stop_beacon_noa(struct rtw89_dev * rtwdev)2258 static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev)
2259 {
2260 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2261 struct rtw89_mcc_role *ref = &mcc->role_ref;
2262 struct rtw89_mcc_role *aux = &mcc->role_aux;
2263
2264 if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2265 return;
2266
2267 if (ref->is_go)
2268 rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, false);
2269 else if (aux->is_go)
2270 rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, false);
2271
2272 rtw89_mcc_handle_beacon_noa(rtwdev, false);
2273 }
2274
rtw89_mcc_ignore_bcn(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * role)2275 static bool rtw89_mcc_ignore_bcn(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role)
2276 {
2277 enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
2278
2279 if (role->is_go)
2280 return true;
2281 else if (chip_gen == RTW89_CHIP_BE && role->is_gc)
2282 return true;
2283 else
2284 return false;
2285 }
2286
rtw89_mcc_start(struct rtw89_dev * rtwdev)2287 static int rtw89_mcc_start(struct rtw89_dev *rtwdev)
2288 {
2289 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2290 struct rtw89_mcc_role *ref = &mcc->role_ref;
2291 struct rtw89_mcc_role *aux = &mcc->role_aux;
2292 int ret;
2293
2294 if (rtwdev->scanning)
2295 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
2296
2297 rtw89_leave_lps(rtwdev);
2298
2299 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC start\n");
2300
2301 ret = rtw89_mcc_fill_all_roles(rtwdev);
2302 if (ret)
2303 return ret;
2304
2305 if (ref->is_go || aux->is_go)
2306 mcc->mode = RTW89_MCC_MODE_GO_STA;
2307 else
2308 mcc->mode = RTW89_MCC_MODE_GC_STA;
2309
2310 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC sel mode: %d\n", mcc->mode);
2311
2312 mcc->group = RTW89_MCC_DFLT_GROUP;
2313
2314 ret = rtw89_mcc_fill_config(rtwdev);
2315 if (ret)
2316 return ret;
2317
2318 if (rtw89_mcc_ignore_bcn(rtwdev, ref) || aux->ignore_bcn) {
2319 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, false);
2320 } else if (rtw89_mcc_ignore_bcn(rtwdev, aux) || ref->ignore_bcn) {
2321 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, false);
2322 } else {
2323 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, true);
2324 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, true);
2325 }
2326
2327 if (rtw89_concurrent_via_mrc(rtwdev))
2328 ret = __mrc_fw_start(rtwdev, false);
2329 else
2330 ret = __mcc_fw_start(rtwdev, false);
2331
2332 if (ret)
2333 return ret;
2334
2335 rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START);
2336
2337 rtw89_mcc_start_beacon_noa(rtwdev);
2338 rtw89_phy_dig_suspend(rtwdev);
2339
2340 rtw89_mcc_prepare(rtwdev, true);
2341 return 0;
2342 }
2343
2344 struct rtw89_mcc_stop_sel {
2345 struct {
2346 const struct rtw89_vif_link *target;
2347 } hint;
2348
2349 /* selection content */
2350 bool filled;
2351 u8 mac_id;
2352 u8 slot_idx;
2353 };
2354
rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel * sel,const struct rtw89_mcc_role * mcc_role)2355 static void rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel *sel,
2356 const struct rtw89_mcc_role *mcc_role)
2357 {
2358 sel->mac_id = mcc_role->rtwvif_link->mac_id;
2359 sel->slot_idx = mcc_role->slot_idx;
2360 sel->filled = true;
2361 }
2362
rtw89_mcc_stop_sel_iterator(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role,unsigned int ordered_idx,void * data)2363 static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev,
2364 struct rtw89_mcc_role *mcc_role,
2365 unsigned int ordered_idx,
2366 void *data)
2367 {
2368 struct rtw89_mcc_stop_sel *sel = data;
2369
2370 if (mcc_role->rtwvif_link == sel->hint.target) {
2371 rtw89_mcc_stop_sel_fill(sel, mcc_role);
2372 return 1; /* break iteration */
2373 }
2374
2375 if (sel->filled)
2376 return 0;
2377
2378 if (!mcc_role->rtwvif_link->chanctx_assigned)
2379 return 0;
2380
2381 rtw89_mcc_stop_sel_fill(sel, mcc_role);
2382 return 0;
2383 }
2384
rtw89_mcc_stop(struct rtw89_dev * rtwdev,const struct rtw89_chanctx_pause_parm * pause)2385 static void rtw89_mcc_stop(struct rtw89_dev *rtwdev,
2386 const struct rtw89_chanctx_pause_parm *pause)
2387 {
2388 struct rtw89_hal *hal = &rtwdev->hal;
2389 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2390 struct rtw89_mcc_role *ref = &mcc->role_ref;
2391 struct rtw89_mcc_role *aux = &mcc->role_aux;
2392 struct rtw89_mcc_stop_sel sel = {
2393 .hint.target = pause ? pause->trigger : NULL,
2394 };
2395 bool rsn_scan;
2396 int ret;
2397
2398 if (!pause) {
2399 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->chanctx_work);
2400 bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES);
2401 }
2402
2403 rsn_scan = pause && pause->rsn == RTW89_CHANCTX_PAUSE_REASON_HW_SCAN;
2404 if (rsn_scan && ref->is_go)
2405 sel.hint.target = ref->rtwvif_link;
2406 else if (rsn_scan && aux->is_go)
2407 sel.hint.target = aux->rtwvif_link;
2408
2409 /* by default, stop at ref */
2410 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_stop_sel_iterator, &sel);
2411 if (!sel.filled)
2412 rtw89_mcc_stop_sel_fill(&sel, ref);
2413
2414 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC stop at <macid %d>\n", sel.mac_id);
2415
2416 if (rtw89_concurrent_via_mrc(rtwdev)) {
2417 ret = rtw89_fw_h2c_mrc_del(rtwdev, mcc->group, sel.slot_idx);
2418 if (ret)
2419 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2420 "MRC h2c failed to trigger del: %d\n", ret);
2421 } else {
2422 ret = rtw89_fw_h2c_stop_mcc(rtwdev, mcc->group,
2423 sel.mac_id, true);
2424 if (ret)
2425 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2426 "MCC h2c failed to trigger stop: %d\n", ret);
2427
2428 ret = rtw89_fw_h2c_del_mcc_group(rtwdev, mcc->group, true);
2429 if (ret)
2430 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2431 "MCC h2c failed to delete group: %d\n", ret);
2432 }
2433
2434 rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP);
2435
2436 rtw89_mcc_stop_beacon_noa(rtwdev);
2437 rtw89_fw_h2c_mcc_dig(rtwdev, RTW89_CHANCTX_0, 0, 0, false);
2438 rtw89_phy_dig_resume(rtwdev, true);
2439
2440 rtw89_mcc_prepare(rtwdev, false);
2441 }
2442
rtw89_mcc_update(struct rtw89_dev * rtwdev)2443 static int rtw89_mcc_update(struct rtw89_dev *rtwdev)
2444 {
2445 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2446 bool old_ref_ignore_bcn = mcc->role_ref.ignore_bcn;
2447 bool old_aux_ignore_bcn = mcc->role_aux.ignore_bcn;
2448 struct rtw89_mcc_config *config = &mcc->config;
2449 struct rtw89_mcc_role *ref = &mcc->role_ref;
2450 struct rtw89_mcc_role *aux = &mcc->role_aux;
2451 struct rtw89_mcc_config old_cfg = *config;
2452 bool courtesy_changed;
2453 bool sync_changed;
2454 int ret;
2455
2456 if (rtwdev->scanning)
2457 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
2458
2459 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC update\n");
2460
2461 ret = rtw89_mcc_fill_config(rtwdev);
2462 if (ret)
2463 return ret;
2464
2465 if (old_ref_ignore_bcn != ref->ignore_bcn)
2466 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, !ref->ignore_bcn);
2467 else if (old_aux_ignore_bcn != aux->ignore_bcn)
2468 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, !aux->ignore_bcn);
2469
2470 if (memcmp(&old_cfg.pattern.courtesy, &config->pattern.courtesy,
2471 sizeof(old_cfg.pattern.courtesy)) == 0)
2472 courtesy_changed = false;
2473 else
2474 courtesy_changed = true;
2475
2476 if (old_cfg.pattern.plan != RTW89_MCC_PLAN_NO_BT ||
2477 config->pattern.plan != RTW89_MCC_PLAN_NO_BT ||
2478 courtesy_changed) {
2479 if (rtw89_concurrent_via_mrc(rtwdev))
2480 ret = __mrc_fw_start(rtwdev, true);
2481 else
2482 ret = __mcc_fw_start(rtwdev, true);
2483
2484 if (ret)
2485 return ret;
2486 } else {
2487 if (memcmp(&old_cfg.sync, &config->sync, sizeof(old_cfg.sync)) == 0)
2488 sync_changed = false;
2489 else
2490 sync_changed = true;
2491
2492 if (rtw89_concurrent_via_mrc(rtwdev))
2493 ret = __mrc_fw_set_duration_no_bt(rtwdev, sync_changed);
2494 else
2495 ret = __mcc_fw_set_duration_no_bt(rtwdev, sync_changed);
2496
2497 if (ret)
2498 return ret;
2499 }
2500
2501 rtw89_mcc_handle_beacon_noa(rtwdev, true);
2502 return 0;
2503 }
2504
rtw89_mcc_search_gc_iterator(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role,unsigned int ordered_idx,void * data)2505 static int rtw89_mcc_search_gc_iterator(struct rtw89_dev *rtwdev,
2506 struct rtw89_mcc_role *mcc_role,
2507 unsigned int ordered_idx,
2508 void *data)
2509 {
2510 struct rtw89_mcc_role **role = data;
2511
2512 if (mcc_role->is_gc)
2513 *role = mcc_role;
2514
2515 return 0;
2516 }
2517
rtw89_mcc_get_gc_role(struct rtw89_dev * rtwdev)2518 static struct rtw89_mcc_role *rtw89_mcc_get_gc_role(struct rtw89_dev *rtwdev)
2519 {
2520 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2521 struct rtw89_mcc_role *role = NULL;
2522
2523 if (mcc->mode != RTW89_MCC_MODE_GC_STA)
2524 return NULL;
2525
2526 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_search_gc_iterator, &role);
2527
2528 return role;
2529 }
2530
rtw89_mcc_gc_detect_beacon_work(struct wiphy * wiphy,struct wiphy_work * work)2531 void rtw89_mcc_gc_detect_beacon_work(struct wiphy *wiphy, struct wiphy_work *work)
2532 {
2533 struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link,
2534 mcc_gc_detect_beacon_work.work);
2535 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
2536 enum rtw89_entity_mode mode;
2537 struct rtw89_dev *rtwdev;
2538
2539 lockdep_assert_wiphy(wiphy);
2540
2541 rtwdev = rtwvif_link->rtwvif->rtwdev;
2542
2543 mode = rtw89_get_entity_mode(rtwdev);
2544 if (mode != RTW89_ENTITY_MODE_MCC)
2545 return;
2546
2547 if (READ_ONCE(rtwvif_link->sync_bcn_tsf) > rtwvif_link->last_sync_bcn_tsf)
2548 rtwvif_link->detect_bcn_count = 0;
2549 else
2550 rtwvif_link->detect_bcn_count++;
2551
2552 if (rtwvif_link->detect_bcn_count < RTW89_MCC_DETECT_BCN_MAX_TRIES)
2553 rtw89_chanctx_proceed(rtwdev, NULL);
2554 else
2555 ieee80211_connection_loss(vif);
2556 }
2557
rtw89_mcc_detect_go_bcn(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link)2558 bool rtw89_mcc_detect_go_bcn(struct rtw89_dev *rtwdev,
2559 struct rtw89_vif_link *rtwvif_link)
2560 {
2561 enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev);
2562 struct rtw89_chanctx_pause_parm pause_parm = {
2563 .rsn = RTW89_CHANCTX_PAUSE_REASON_GC_BCN_LOSS,
2564 .trigger = rtwvif_link,
2565 };
2566 struct ieee80211_bss_conf *bss_conf;
2567 struct rtw89_mcc_role *role;
2568 u16 bcn_int;
2569
2570 if (mode != RTW89_ENTITY_MODE_MCC)
2571 return false;
2572
2573 role = rtw89_mcc_get_gc_role(rtwdev);
2574 if (!role)
2575 return false;
2576
2577 if (role->rtwvif_link != rtwvif_link)
2578 return false;
2579
2580 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2581 "MCC GC beacon loss, pause MCC to detect GO beacon\n");
2582
2583 rcu_read_lock();
2584
2585 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
2586 bcn_int = bss_conf->beacon_int;
2587
2588 rcu_read_unlock();
2589
2590 rtw89_chanctx_pause(rtwdev, &pause_parm);
2591 rtwvif_link->last_sync_bcn_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf);
2592 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
2593 &rtwvif_link->mcc_gc_detect_beacon_work,
2594 usecs_to_jiffies(ieee80211_tu_to_usec(bcn_int)));
2595
2596 return true;
2597 }
2598
rtw89_mcc_detect_connection(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * role)2599 static void rtw89_mcc_detect_connection(struct rtw89_dev *rtwdev,
2600 struct rtw89_mcc_role *role)
2601 {
2602 struct ieee80211_vif *vif;
2603 bool start_detect;
2604 int ret;
2605
2606 ret = rtw89_core_send_nullfunc(rtwdev, role->rtwvif_link, true, false,
2607 RTW89_MCC_PROBE_TIMEOUT);
2608 if (ret)
2609 role->probe_count++;
2610 else
2611 role->probe_count = 0;
2612
2613 if (role->probe_count < RTW89_MCC_PROBE_MAX_TRIES)
2614 return;
2615
2616 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2617 "MCC <macid %d> can not detect AP/GO\n", role->rtwvif_link->mac_id);
2618
2619 start_detect = rtw89_mcc_detect_go_bcn(rtwdev, role->rtwvif_link);
2620 if (start_detect)
2621 return;
2622
2623 vif = rtwvif_link_to_vif(role->rtwvif_link);
2624 ieee80211_connection_loss(vif);
2625 }
2626
rtw89_mcc_track(struct rtw89_dev * rtwdev)2627 static void rtw89_mcc_track(struct rtw89_dev *rtwdev)
2628 {
2629 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2630 struct rtw89_mcc_config *config = &mcc->config;
2631 struct rtw89_mcc_pattern *pattern = &config->pattern;
2632 struct rtw89_mcc_role *ref = &mcc->role_ref;
2633 struct rtw89_mcc_role *aux = &mcc->role_aux;
2634 u16 tolerance;
2635 u16 bcn_ofst;
2636 u16 diff;
2637
2638 if (rtw89_mcc_ignore_bcn(rtwdev, ref) || aux->ignore_bcn)
2639 rtw89_mcc_detect_connection(rtwdev, aux);
2640 else if (rtw89_mcc_ignore_bcn(rtwdev, aux) || ref->ignore_bcn)
2641 rtw89_mcc_detect_connection(rtwdev, ref);
2642
2643 if (mcc->mode != RTW89_MCC_MODE_GC_STA)
2644 return;
2645
2646 bcn_ofst = rtw89_mcc_get_bcn_ofst(rtwdev);
2647 if (bcn_ofst == config->beacon_offset)
2648 return;
2649
2650 if (bcn_ofst > config->beacon_offset) {
2651 diff = bcn_ofst - config->beacon_offset;
2652 if (pattern->tob_aux < 0)
2653 tolerance = -pattern->tob_aux;
2654 else if (pattern->toa_aux > 0)
2655 tolerance = pattern->toa_aux;
2656 else
2657 return; /* no chance to improve */
2658 } else {
2659 diff = config->beacon_offset - bcn_ofst;
2660 if (pattern->toa_aux < 0)
2661 tolerance = -pattern->toa_aux;
2662 else if (pattern->tob_aux > 0)
2663 tolerance = pattern->tob_aux;
2664 else
2665 return; /* no chance to improve */
2666 }
2667
2668 if (diff <= tolerance)
2669 return;
2670
2671 rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_BCN_OFFSET_CHANGE);
2672 }
2673
__mcc_fw_upd_macid_bitmap(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * upd)2674 static int __mcc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev,
2675 struct rtw89_mcc_role *upd)
2676 {
2677 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2678 int ret;
2679
2680 ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group,
2681 upd->rtwvif_link->mac_id,
2682 upd->macid_bitmap);
2683 if (ret) {
2684 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2685 "MCC h2c failed to update macid bitmap: %d\n", ret);
2686 return ret;
2687 }
2688
2689 return 0;
2690 }
2691
__mrc_fw_upd_macid_bitmap(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * cur,struct rtw89_mcc_role * upd)2692 static int __mrc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev,
2693 struct rtw89_mcc_role *cur,
2694 struct rtw89_mcc_role *upd)
2695 {
2696 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2697 struct rtw89_fw_mrc_upd_bitmap_arg arg = {};
2698 u32 old = rtw89_mcc_role_fw_macid_bitmap_to_u32(cur);
2699 u32 new = rtw89_mcc_role_fw_macid_bitmap_to_u32(upd);
2700 u32 add = new & ~old;
2701 u32 del = old & ~new;
2702 int ret;
2703 int i;
2704
2705 arg.sch_idx = mcc->group;
2706 arg.macid = upd->rtwvif_link->mac_id;
2707
2708 for (i = 0; i < 32; i++) {
2709 if (add & BIT(i)) {
2710 arg.client_macid = i;
2711 arg.action = RTW89_H2C_MRC_UPD_BITMAP_ACTION_ADD;
2712
2713 ret = rtw89_fw_h2c_mrc_upd_bitmap(rtwdev, &arg);
2714 if (ret)
2715 goto err;
2716 }
2717 }
2718
2719 for (i = 0; i < 32; i++) {
2720 if (del & BIT(i)) {
2721 arg.client_macid = i;
2722 arg.action = RTW89_H2C_MRC_UPD_BITMAP_ACTION_DEL;
2723
2724 ret = rtw89_fw_h2c_mrc_upd_bitmap(rtwdev, &arg);
2725 if (ret)
2726 goto err;
2727 }
2728 }
2729
2730 return 0;
2731
2732 err:
2733 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2734 "MRC h2c failed to update bitmap: %d\n", ret);
2735 return ret;
2736 }
2737
rtw89_mcc_upd_map_iterator(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role,unsigned int ordered_idx,void * data)2738 static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev,
2739 struct rtw89_mcc_role *mcc_role,
2740 unsigned int ordered_idx,
2741 void *data)
2742 {
2743 struct rtw89_mcc_role upd = {
2744 .rtwvif_link = mcc_role->rtwvif_link,
2745 };
2746 int ret;
2747
2748 if (!mcc_role->is_go)
2749 return 0;
2750
2751 rtw89_mcc_fill_role_macid_bitmap(rtwdev, &upd);
2752 if (memcmp(mcc_role->macid_bitmap, upd.macid_bitmap,
2753 sizeof(mcc_role->macid_bitmap)) == 0)
2754 return 0;
2755
2756 if (rtw89_concurrent_via_mrc(rtwdev))
2757 ret = __mrc_fw_upd_macid_bitmap(rtwdev, mcc_role, &upd);
2758 else
2759 ret = __mcc_fw_upd_macid_bitmap(rtwdev, &upd);
2760
2761 if (ret)
2762 return ret;
2763
2764 memcpy(mcc_role->macid_bitmap, upd.macid_bitmap,
2765 sizeof(mcc_role->macid_bitmap));
2766 return 0;
2767 }
2768
rtw89_mcc_update_macid_bitmap(struct rtw89_dev * rtwdev)2769 static void rtw89_mcc_update_macid_bitmap(struct rtw89_dev *rtwdev)
2770 {
2771 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2772
2773 if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2774 return;
2775
2776 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_map_iterator, NULL);
2777 }
2778
rtw89_mcc_upd_lmt_iterator(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role,unsigned int ordered_idx,void * data)2779 static int rtw89_mcc_upd_lmt_iterator(struct rtw89_dev *rtwdev,
2780 struct rtw89_mcc_role *mcc_role,
2781 unsigned int ordered_idx,
2782 void *data)
2783 {
2784 memset(&mcc_role->limit, 0, sizeof(mcc_role->limit));
2785 rtw89_mcc_fill_role_limit(rtwdev, mcc_role);
2786 return 0;
2787 }
2788
rtw89_mcc_update_limit(struct rtw89_dev * rtwdev)2789 static void rtw89_mcc_update_limit(struct rtw89_dev *rtwdev)
2790 {
2791 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2792
2793 if (mcc->mode != RTW89_MCC_MODE_GC_STA)
2794 return;
2795
2796 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_lmt_iterator, NULL);
2797 }
2798
rtw89_mcc_get_links_iterator(struct rtw89_dev * rtwdev,struct rtw89_mcc_role * mcc_role,unsigned int ordered_idx,void * data)2799 static int rtw89_mcc_get_links_iterator(struct rtw89_dev *rtwdev,
2800 struct rtw89_mcc_role *mcc_role,
2801 unsigned int ordered_idx,
2802 void *data)
2803 {
2804 struct rtw89_mcc_links_info *info = data;
2805
2806 info->links[ordered_idx] = mcc_role->rtwvif_link;
2807 return 0;
2808 }
2809
rtw89_mcc_get_links(struct rtw89_dev * rtwdev,struct rtw89_mcc_links_info * info)2810 void rtw89_mcc_get_links(struct rtw89_dev *rtwdev, struct rtw89_mcc_links_info *info)
2811 {
2812 enum rtw89_entity_mode mode;
2813
2814 memset(info, 0, sizeof(*info));
2815
2816 mode = rtw89_get_entity_mode(rtwdev);
2817 if (unlikely(mode != RTW89_ENTITY_MODE_MCC))
2818 return;
2819
2820 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_get_links_iterator, info);
2821 }
2822
rtw89_chanctx_work(struct wiphy * wiphy,struct wiphy_work * work)2823 void rtw89_chanctx_work(struct wiphy *wiphy, struct wiphy_work *work)
2824 {
2825 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
2826 chanctx_work.work);
2827 struct rtw89_hal *hal = &rtwdev->hal;
2828 bool update_mcc_pattern = false;
2829 enum rtw89_entity_mode mode;
2830 u32 changed = 0;
2831 int ret;
2832 int i;
2833
2834 lockdep_assert_wiphy(wiphy);
2835
2836 if (hal->entity_pause)
2837 return;
2838
2839 for (i = 0; i < NUM_OF_RTW89_CHANCTX_CHANGES; i++) {
2840 if (test_and_clear_bit(i, hal->changes))
2841 changed |= BIT(i);
2842 }
2843
2844 mode = rtw89_get_entity_mode(rtwdev);
2845 switch (mode) {
2846 case RTW89_ENTITY_MODE_MCC_PREPARE:
2847 rtw89_set_entity_mode(rtwdev, RTW89_ENTITY_MODE_MCC);
2848 rtw89_set_channel(rtwdev);
2849
2850 ret = rtw89_mcc_start(rtwdev);
2851 if (ret)
2852 rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
2853 break;
2854 case RTW89_ENTITY_MODE_MCC:
2855 if (changed & BIT(RTW89_CHANCTX_BCN_OFFSET_CHANGE) ||
2856 changed & BIT(RTW89_CHANCTX_P2P_PS_CHANGE) ||
2857 changed & BIT(RTW89_CHANCTX_BT_SLOT_CHANGE) ||
2858 changed & BIT(RTW89_CHANCTX_TSF32_TOGGLE_CHANGE))
2859 update_mcc_pattern = true;
2860 if (changed & BIT(RTW89_CHANCTX_REMOTE_STA_CHANGE))
2861 rtw89_mcc_update_macid_bitmap(rtwdev);
2862 if (changed & BIT(RTW89_CHANCTX_P2P_PS_CHANGE))
2863 rtw89_mcc_update_limit(rtwdev);
2864 if (changed & BIT(RTW89_CHANCTX_BT_SLOT_CHANGE))
2865 rtw89_mcc_fill_bt_role(rtwdev);
2866 if (update_mcc_pattern) {
2867 ret = rtw89_mcc_update(rtwdev);
2868 if (ret)
2869 rtw89_warn(rtwdev, "failed to update MCC: %d\n",
2870 ret);
2871 }
2872 break;
2873 default:
2874 break;
2875 }
2876 }
2877
rtw89_queue_chanctx_change(struct rtw89_dev * rtwdev,enum rtw89_chanctx_changes change)2878 void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
2879 enum rtw89_chanctx_changes change)
2880 {
2881 struct rtw89_hal *hal = &rtwdev->hal;
2882 enum rtw89_entity_mode mode;
2883 u32 delay;
2884
2885 mode = rtw89_get_entity_mode(rtwdev);
2886 switch (mode) {
2887 default:
2888 return;
2889 case RTW89_ENTITY_MODE_MCC_PREPARE:
2890 delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE);
2891 rtw89_phy_dig_suspend(rtwdev);
2892 break;
2893 case RTW89_ENTITY_MODE_MCC:
2894 delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC);
2895 break;
2896 }
2897
2898 if (change != RTW89_CHANCTX_CHANGE_DFLT) {
2899 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "set chanctx change %d\n",
2900 change);
2901 set_bit(change, hal->changes);
2902 }
2903
2904 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2905 "queue chanctx work for mode %d with delay %d us\n",
2906 mode, delay);
2907 wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->chanctx_work,
2908 usecs_to_jiffies(delay));
2909 }
2910
rtw89_queue_chanctx_work(struct rtw89_dev * rtwdev)2911 void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev)
2912 {
2913 rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_CHANGE_DFLT);
2914 }
2915
__rtw89_query_mr_wtype(struct rtw89_dev * rtwdev)2916 static enum rtw89_mr_wtype __rtw89_query_mr_wtype(struct rtw89_dev *rtwdev)
2917 {
2918 struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
2919 enum rtw89_chanctx_idx chanctx_idx;
2920 struct ieee80211_vif *vif;
2921 struct rtw89_vif *rtwvif;
2922 unsigned int num_mld = 0;
2923 unsigned int num_ml = 0;
2924 unsigned int cnt = 0;
2925 u8 role_idx;
2926 u8 idx;
2927
2928 for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) {
2929 rtwvif = mgnt->active_roles[role_idx];
2930 if (!rtwvif)
2931 continue;
2932
2933 cnt++;
2934
2935 vif = rtwvif_to_vif(rtwvif);
2936 if (!ieee80211_vif_is_mld(vif))
2937 continue;
2938
2939 num_mld++;
2940
2941 for (idx = 0; idx < __RTW89_MLD_MAX_LINK_NUM; idx++) {
2942 chanctx_idx = mgnt->chanctx_tbl[role_idx][idx];
2943 if (chanctx_idx != RTW89_CHANCTX_IDLE)
2944 num_ml++;
2945 }
2946 }
2947
2948 if (num_mld > 1)
2949 goto err;
2950
2951 switch (cnt) {
2952 case 0:
2953 return RTW89_MR_WTYPE_NONE;
2954 case 1:
2955 if (!num_mld)
2956 return RTW89_MR_WTYPE_NONMLD;
2957 switch (num_ml) {
2958 case 1:
2959 return RTW89_MR_WTYPE_MLD1L1R;
2960 case 2:
2961 return RTW89_MR_WTYPE_MLD2L1R;
2962 default:
2963 break;
2964 }
2965 break;
2966 case 2:
2967 if (!num_mld)
2968 return RTW89_MR_WTYPE_NONMLD_NONMLD;
2969 switch (num_ml) {
2970 case 1:
2971 return RTW89_MR_WTYPE_MLD1L1R_NONMLD;
2972 case 2:
2973 return RTW89_MR_WTYPE_MLD2L1R_NONMLD;
2974 default:
2975 break;
2976 }
2977 break;
2978 default:
2979 break;
2980 }
2981
2982 err:
2983 rtw89_warn(rtwdev, "%s: unhandled cnt %u mld %u ml %u\n", __func__,
2984 cnt, num_mld, num_ml);
2985 return RTW89_MR_WTYPE_UNKNOWN;
2986 }
2987
__rtw89_query_mr_wmode(struct rtw89_dev * rtwdev,u8 inst_idx)2988 static enum rtw89_mr_wmode __rtw89_query_mr_wmode(struct rtw89_dev *rtwdev,
2989 u8 inst_idx)
2990 {
2991 struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
2992 unsigned int num[NUM_NL80211_IFTYPES] = {};
2993 enum rtw89_chanctx_idx chanctx_idx;
2994 struct ieee80211_vif *vif;
2995 struct rtw89_vif *rtwvif;
2996 unsigned int cnt = 0;
2997 u8 role_idx;
2998
2999 if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM))
3000 return RTW89_MR_WMODE_UNKNOWN;
3001
3002 for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) {
3003 chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx];
3004 if (chanctx_idx == RTW89_CHANCTX_IDLE)
3005 continue;
3006
3007 rtwvif = mgnt->active_roles[role_idx];
3008 if (unlikely(!rtwvif))
3009 continue;
3010
3011 vif = rtwvif_to_vif(rtwvif);
3012 num[vif->type]++;
3013 cnt++;
3014 }
3015
3016 switch (cnt) {
3017 case 0:
3018 return RTW89_MR_WMODE_NONE;
3019 case 1:
3020 if (num[NL80211_IFTYPE_STATION])
3021 return RTW89_MR_WMODE_1CLIENT;
3022 if (num[NL80211_IFTYPE_AP])
3023 return RTW89_MR_WMODE_1AP;
3024 break;
3025 case 2:
3026 if (num[NL80211_IFTYPE_STATION] == 2)
3027 return RTW89_MR_WMODE_2CLIENTS;
3028 if (num[NL80211_IFTYPE_AP] == 2)
3029 return RTW89_MR_WMODE_2APS;
3030 if (num[NL80211_IFTYPE_STATION] && num[NL80211_IFTYPE_AP])
3031 return RTW89_MR_WMODE_1AP_1CLIENT;
3032 break;
3033 default:
3034 break;
3035 }
3036
3037 rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt);
3038 return RTW89_MR_WMODE_UNKNOWN;
3039 }
3040
__rtw89_query_mr_ctxtype(struct rtw89_dev * rtwdev,u8 inst_idx)3041 static enum rtw89_mr_ctxtype __rtw89_query_mr_ctxtype(struct rtw89_dev *rtwdev,
3042 u8 inst_idx)
3043 {
3044 struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
3045 DECLARE_BITMAP(map, NUM_OF_RTW89_CHANCTX) = {};
3046 unsigned int num[RTW89_BAND_NUM] = {};
3047 enum rtw89_chanctx_idx chanctx_idx;
3048 const struct rtw89_chan *chan;
3049 unsigned int cnt = 0;
3050 u8 role_idx;
3051
3052 if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM))
3053 return RTW89_MR_CTX_UNKNOWN;
3054
3055 for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) {
3056 chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx];
3057 if (chanctx_idx == RTW89_CHANCTX_IDLE)
3058 continue;
3059
3060 if (__test_and_set_bit(chanctx_idx, map))
3061 continue;
3062
3063 chan = rtw89_chan_get(rtwdev, chanctx_idx);
3064 num[chan->band_type]++;
3065 cnt++;
3066 }
3067
3068 switch (cnt) {
3069 case 0:
3070 return RTW89_MR_CTX_NONE;
3071 case 1:
3072 if (num[RTW89_BAND_2G])
3073 return RTW89_MR_CTX1_2GHZ;
3074 if (num[RTW89_BAND_5G])
3075 return RTW89_MR_CTX1_5GHZ;
3076 if (num[RTW89_BAND_6G])
3077 return RTW89_MR_CTX1_6GHZ;
3078 break;
3079 case 2:
3080 if (num[RTW89_BAND_2G] == 2)
3081 return RTW89_MR_CTX2_2GHZ;
3082 if (num[RTW89_BAND_5G] == 2)
3083 return RTW89_MR_CTX2_5GHZ;
3084 if (num[RTW89_BAND_6G] == 2)
3085 return RTW89_MR_CTX2_6GHZ;
3086 if (num[RTW89_BAND_2G] && num[RTW89_BAND_5G])
3087 return RTW89_MR_CTX2_2GHZ_5GHZ;
3088 if (num[RTW89_BAND_2G] && num[RTW89_BAND_6G])
3089 return RTW89_MR_CTX2_2GHZ_6GHZ;
3090 if (num[RTW89_BAND_5G] && num[RTW89_BAND_6G])
3091 return RTW89_MR_CTX2_5GHZ_6GHZ;
3092 break;
3093 default:
3094 break;
3095 }
3096
3097 rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt);
3098 return RTW89_MR_CTX_UNKNOWN;
3099 }
3100
rtw89_query_mr_chanctx_info(struct rtw89_dev * rtwdev,u8 inst_idx,struct rtw89_mr_chanctx_info * info)3101 void rtw89_query_mr_chanctx_info(struct rtw89_dev *rtwdev, u8 inst_idx,
3102 struct rtw89_mr_chanctx_info *info)
3103 {
3104 lockdep_assert_wiphy(rtwdev->hw->wiphy);
3105
3106 info->wtype = __rtw89_query_mr_wtype(rtwdev);
3107 info->wmode = __rtw89_query_mr_wmode(rtwdev, inst_idx);
3108 info->ctxtype = __rtw89_query_mr_ctxtype(rtwdev, inst_idx);
3109 }
3110
rtw89_chanctx_track(struct rtw89_dev * rtwdev)3111 void rtw89_chanctx_track(struct rtw89_dev *rtwdev)
3112 {
3113 struct rtw89_hal *hal = &rtwdev->hal;
3114 enum rtw89_entity_mode mode;
3115
3116 lockdep_assert_wiphy(rtwdev->hw->wiphy);
3117
3118 if (hal->entity_pause)
3119 return;
3120
3121 mode = rtw89_get_entity_mode(rtwdev);
3122 switch (mode) {
3123 case RTW89_ENTITY_MODE_MCC:
3124 rtw89_mcc_track(rtwdev);
3125 break;
3126 default:
3127 break;
3128 }
3129 }
3130
rtw89_chanctx_pause(struct rtw89_dev * rtwdev,const struct rtw89_chanctx_pause_parm * pause_parm)3131 void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
3132 const struct rtw89_chanctx_pause_parm *pause_parm)
3133 {
3134 struct rtw89_hal *hal = &rtwdev->hal;
3135 enum rtw89_entity_mode mode;
3136
3137 lockdep_assert_wiphy(rtwdev->hw->wiphy);
3138
3139 if (hal->entity_pause)
3140 return;
3141
3142 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx pause (rsn: %d)\n", pause_parm->rsn);
3143
3144 mode = rtw89_get_entity_mode(rtwdev);
3145 switch (mode) {
3146 case RTW89_ENTITY_MODE_MCC:
3147 rtw89_mcc_stop(rtwdev, pause_parm);
3148 break;
3149 default:
3150 break;
3151 }
3152
3153 hal->entity_pause = true;
3154 }
3155
rtw89_chanctx_proceed_cb(struct rtw89_dev * rtwdev,const struct rtw89_chanctx_cb_parm * parm)3156 static void rtw89_chanctx_proceed_cb(struct rtw89_dev *rtwdev,
3157 const struct rtw89_chanctx_cb_parm *parm)
3158 {
3159 int ret;
3160
3161 if (!parm || !parm->cb)
3162 return;
3163
3164 ret = parm->cb(rtwdev, parm->data);
3165 if (ret)
3166 rtw89_warn(rtwdev, "%s (%s): cb failed: %d\n", __func__,
3167 parm->caller ?: "unknown", ret);
3168 }
3169
3170 /* pass @cb_parm if there is a @cb_parm->cb which needs to invoke right after
3171 * call rtw89_set_channel() and right before proceed entity according to mode.
3172 */
rtw89_chanctx_proceed(struct rtw89_dev * rtwdev,const struct rtw89_chanctx_cb_parm * cb_parm)3173 void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev,
3174 const struct rtw89_chanctx_cb_parm *cb_parm)
3175 {
3176 struct rtw89_hal *hal = &rtwdev->hal;
3177 enum rtw89_entity_mode mode;
3178 int ret;
3179
3180 lockdep_assert_wiphy(rtwdev->hw->wiphy);
3181
3182 if (unlikely(!hal->entity_pause)) {
3183 rtw89_chanctx_proceed_cb(rtwdev, cb_parm);
3184 return;
3185 }
3186
3187 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx proceed\n");
3188
3189 hal->entity_pause = false;
3190 rtw89_set_channel(rtwdev);
3191
3192 rtw89_chanctx_proceed_cb(rtwdev, cb_parm);
3193
3194 mode = rtw89_get_entity_mode(rtwdev);
3195 switch (mode) {
3196 case RTW89_ENTITY_MODE_MCC:
3197 ret = rtw89_mcc_start(rtwdev);
3198 if (ret)
3199 rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
3200 break;
3201 default:
3202 break;
3203 }
3204
3205 rtw89_queue_chanctx_work(rtwdev);
3206 }
3207
__rtw89_swap_chanctx(struct rtw89_vif * rtwvif,enum rtw89_chanctx_idx idx1,enum rtw89_chanctx_idx idx2)3208 static void __rtw89_swap_chanctx(struct rtw89_vif *rtwvif,
3209 enum rtw89_chanctx_idx idx1,
3210 enum rtw89_chanctx_idx idx2)
3211 {
3212 struct rtw89_vif_link *rtwvif_link;
3213 unsigned int link_id;
3214
3215 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
3216 if (!rtwvif_link->chanctx_assigned)
3217 continue;
3218
3219 if (rtwvif_link->chanctx_idx == idx1)
3220 rtwvif_link->chanctx_idx = idx2;
3221 else if (rtwvif_link->chanctx_idx == idx2)
3222 rtwvif_link->chanctx_idx = idx1;
3223 }
3224 }
3225
rtw89_swap_chanctx(struct rtw89_dev * rtwdev,enum rtw89_chanctx_idx idx1,enum rtw89_chanctx_idx idx2)3226 static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
3227 enum rtw89_chanctx_idx idx1,
3228 enum rtw89_chanctx_idx idx2)
3229 {
3230 struct rtw89_hal *hal = &rtwdev->hal;
3231 struct rtw89_vif *rtwvif;
3232 u8 cur;
3233
3234 if (idx1 == idx2)
3235 return;
3236
3237 hal->chanctx[idx1].cfg->idx = idx2;
3238 hal->chanctx[idx2].cfg->idx = idx1;
3239
3240 swap(hal->chanctx[idx1], hal->chanctx[idx2]);
3241
3242 rtw89_for_each_rtwvif(rtwdev, rtwvif)
3243 __rtw89_swap_chanctx(rtwvif, idx1, idx2);
3244
3245 cur = atomic_read(&hal->roc_chanctx_idx);
3246 if (cur == idx1)
3247 atomic_set(&hal->roc_chanctx_idx, idx2);
3248 else if (cur == idx2)
3249 atomic_set(&hal->roc_chanctx_idx, idx1);
3250 }
3251
rtw89_chanctx_ops_add(struct rtw89_dev * rtwdev,struct ieee80211_chanctx_conf * ctx)3252 int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
3253 struct ieee80211_chanctx_conf *ctx)
3254 {
3255 struct rtw89_hal *hal = &rtwdev->hal;
3256 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3257 const struct rtw89_chip_info *chip = rtwdev->chip;
3258 u8 idx;
3259
3260 idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_CHANCTX);
3261 if (idx >= chip->support_chanctx_num)
3262 return -ENOENT;
3263
3264 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
3265 cfg->idx = idx;
3266 cfg->ref_count = 0;
3267 hal->chanctx[idx].cfg = cfg;
3268 return 0;
3269 }
3270
rtw89_chanctx_ops_remove(struct rtw89_dev * rtwdev,struct ieee80211_chanctx_conf * ctx)3271 void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
3272 struct ieee80211_chanctx_conf *ctx)
3273 {
3274 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3275
3276 rtw89_config_entity_chandef(rtwdev, cfg->idx, NULL);
3277 }
3278
rtw89_chanctx_ops_change(struct rtw89_dev * rtwdev,struct ieee80211_chanctx_conf * ctx,u32 changed)3279 void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
3280 struct ieee80211_chanctx_conf *ctx,
3281 u32 changed)
3282 {
3283 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3284 u8 idx = cfg->idx;
3285
3286 if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
3287 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
3288 rtw89_set_channel(rtwdev);
3289 }
3290
3291 if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)
3292 rtw89_chan_update_punctured(rtwdev, idx, &ctx->def);
3293 }
3294
rtw89_chanctx_ops_assign_vif(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,struct ieee80211_chanctx_conf * ctx)3295 int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
3296 struct rtw89_vif_link *rtwvif_link,
3297 struct ieee80211_chanctx_conf *ctx)
3298 {
3299 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3300 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
3301 struct rtw89_hal *hal = &rtwdev->hal;
3302 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
3303 struct rtw89_entity_weight w = {};
3304 int ret;
3305
3306 rtwvif_link->chanctx_idx = cfg->idx;
3307 rtwvif_link->chanctx_assigned = true;
3308 cfg->ref_count++;
3309
3310 if (rtwdev->scanning)
3311 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
3312
3313 if (list_empty(&rtwvif->mgnt_entry))
3314 list_add_tail(&rtwvif->mgnt_entry, &mgnt->active_list);
3315
3316 if (cfg->idx == RTW89_CHANCTX_0)
3317 goto out;
3318
3319 rtw89_entity_calculate_weight(rtwdev, &w);
3320 if (w.active_chanctxs != 1)
3321 goto out;
3322
3323 /* put the first active chanctx at RTW89_CHANCTX_0 */
3324 rtw89_swap_chanctx(rtwdev, cfg->idx, RTW89_CHANCTX_0);
3325
3326 out:
3327 ret = rtw89_set_channel(rtwdev);
3328 if (ret)
3329 return ret;
3330
3331 rtw89_tas_reset(rtwdev, true);
3332
3333 return 0;
3334 }
3335
rtw89_chanctx_ops_unassign_vif(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,struct ieee80211_chanctx_conf * ctx)3336 void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
3337 struct rtw89_vif_link *rtwvif_link,
3338 struct ieee80211_chanctx_conf *ctx)
3339 {
3340 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3341 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
3342 struct rtw89_hal *hal = &rtwdev->hal;
3343 enum rtw89_chanctx_idx roll;
3344 enum rtw89_entity_mode cur;
3345 enum rtw89_entity_mode new;
3346 int ret;
3347
3348 rtwvif_link->chanctx_idx = RTW89_CHANCTX_0;
3349 rtwvif_link->chanctx_assigned = false;
3350 cfg->ref_count--;
3351
3352 if (rtwdev->scanning)
3353 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
3354
3355 if (!rtw89_vif_is_active_role(rtwvif))
3356 list_del_init(&rtwvif->mgnt_entry);
3357
3358 if (cfg->ref_count != 0)
3359 goto out;
3360
3361 if (cfg->idx != RTW89_CHANCTX_0)
3362 goto out;
3363
3364 roll = find_next_bit(hal->entity_map, NUM_OF_RTW89_CHANCTX,
3365 cfg->idx + 1);
3366 /* Follow rtw89_config_default_chandef() when rtw89_entity_recalc(). */
3367 if (roll == NUM_OF_RTW89_CHANCTX)
3368 goto out;
3369
3370 /* RTW89_CHANCTX_0 is going to release, and another exists.
3371 * Make another roll down to RTW89_CHANCTX_0 to replace.
3372 */
3373 rtw89_swap_chanctx(rtwdev, cfg->idx, roll);
3374
3375 out:
3376 if (!hal->entity_pause) {
3377 cur = rtw89_get_entity_mode(rtwdev);
3378 switch (cur) {
3379 case RTW89_ENTITY_MODE_MCC:
3380 rtw89_mcc_stop(rtwdev, NULL);
3381 break;
3382 default:
3383 break;
3384 }
3385 }
3386
3387 ret = rtw89_set_channel(rtwdev);
3388 if (ret)
3389 return;
3390
3391 if (hal->entity_pause)
3392 return;
3393
3394 new = rtw89_get_entity_mode(rtwdev);
3395 switch (new) {
3396 case RTW89_ENTITY_MODE_MCC:
3397 /* re-plan MCC for chanctx changes. */
3398 ret = rtw89_mcc_start(rtwdev);
3399 if (ret)
3400 rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
3401 break;
3402 default:
3403 break;
3404 }
3405 }
3406
rtw89_chanctx_ops_reassign_vif(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,struct ieee80211_chanctx_conf * old_ctx,struct ieee80211_chanctx_conf * new_ctx,bool replace)3407 int rtw89_chanctx_ops_reassign_vif(struct rtw89_dev *rtwdev,
3408 struct rtw89_vif_link *rtwvif_link,
3409 struct ieee80211_chanctx_conf *old_ctx,
3410 struct ieee80211_chanctx_conf *new_ctx,
3411 bool replace)
3412 {
3413 int ret;
3414
3415 rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, old_ctx);
3416
3417 if (!replace)
3418 goto assign;
3419
3420 rtw89_chanctx_ops_remove(rtwdev, old_ctx);
3421 ret = rtw89_chanctx_ops_add(rtwdev, new_ctx);
3422 if (ret) {
3423 rtw89_err(rtwdev, "%s: failed to add chanctx: %d\n",
3424 __func__, ret);
3425 return ret;
3426 }
3427
3428 assign:
3429 ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, new_ctx);
3430 if (ret) {
3431 rtw89_err(rtwdev, "%s: failed to assign chanctx: %d\n",
3432 __func__, ret);
3433 return ret;
3434 }
3435
3436 _rtw89_chan_update_punctured(rtwdev, rtwvif_link, &new_ctx->def);
3437
3438 return 0;
3439 }
3440