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