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