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