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