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