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