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