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