xref: /linux/drivers/net/wireless/realtek/rtw89/chan.c (revision 34dc1baba215b826e454b8d19e4f24adbeb7d00d)
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 "debug.h"
7 #include "fw.h"
8 #include "ps.h"
9 #include "util.h"
10 
11 static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
12 						 u8 center_chan)
13 {
14 	switch (band) {
15 	default:
16 	case RTW89_BAND_2G:
17 		switch (center_chan) {
18 		default:
19 		case 1 ... 14:
20 			return RTW89_CH_2G;
21 		}
22 	case RTW89_BAND_5G:
23 		switch (center_chan) {
24 		default:
25 		case 36 ... 64:
26 			return RTW89_CH_5G_BAND_1;
27 		case 100 ... 144:
28 			return RTW89_CH_5G_BAND_3;
29 		case 149 ... 177:
30 			return RTW89_CH_5G_BAND_4;
31 		}
32 	case RTW89_BAND_6G:
33 		switch (center_chan) {
34 		default:
35 		case 1 ... 29:
36 			return RTW89_CH_6G_BAND_IDX0;
37 		case 33 ... 61:
38 			return RTW89_CH_6G_BAND_IDX1;
39 		case 65 ... 93:
40 			return RTW89_CH_6G_BAND_IDX2;
41 		case 97 ... 125:
42 			return RTW89_CH_6G_BAND_IDX3;
43 		case 129 ... 157:
44 			return RTW89_CH_6G_BAND_IDX4;
45 		case 161 ... 189:
46 			return RTW89_CH_6G_BAND_IDX5;
47 		case 193 ... 221:
48 			return RTW89_CH_6G_BAND_IDX6;
49 		case 225 ... 253:
50 			return RTW89_CH_6G_BAND_IDX7;
51 		}
52 	}
53 }
54 
55 static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
56 						       u32 center_freq,
57 						       u32 primary_freq)
58 {
59 	u8 primary_chan_idx;
60 	u32 offset;
61 
62 	switch (bw) {
63 	default:
64 	case RTW89_CHANNEL_WIDTH_20:
65 		primary_chan_idx = RTW89_SC_DONT_CARE;
66 		break;
67 	case RTW89_CHANNEL_WIDTH_40:
68 		if (primary_freq > center_freq)
69 			primary_chan_idx = RTW89_SC_20_UPPER;
70 		else
71 			primary_chan_idx = RTW89_SC_20_LOWER;
72 		break;
73 	case RTW89_CHANNEL_WIDTH_80:
74 	case RTW89_CHANNEL_WIDTH_160:
75 		if (primary_freq > center_freq) {
76 			offset = (primary_freq - center_freq - 10) / 20;
77 			primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
78 		} else {
79 			offset = (center_freq - primary_freq - 10) / 20;
80 			primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
81 		}
82 		break;
83 	}
84 
85 	return primary_chan_idx;
86 }
87 
88 void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
89 		       enum rtw89_band band, enum rtw89_bandwidth bandwidth)
90 {
91 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
92 	u32 center_freq, primary_freq;
93 
94 	memset(chan, 0, sizeof(*chan));
95 	chan->channel = center_chan;
96 	chan->primary_channel = primary_chan;
97 	chan->band_type = band;
98 	chan->band_width = bandwidth;
99 
100 	center_freq = ieee80211_channel_to_frequency(center_chan, nl_band);
101 	primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band);
102 
103 	chan->freq = center_freq;
104 	chan->subband_type = rtw89_get_subband_type(band, center_chan);
105 	chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
106 						      primary_freq);
107 }
108 
109 bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
110 			      enum rtw89_sub_entity_idx idx,
111 			      const struct rtw89_chan *new)
112 {
113 	struct rtw89_hal *hal = &rtwdev->hal;
114 	struct rtw89_chan *chan = &hal->sub[idx].chan;
115 	struct rtw89_chan_rcd *rcd = &hal->sub[idx].rcd;
116 	bool band_changed;
117 
118 	rcd->prev_primary_channel = chan->primary_channel;
119 	rcd->prev_band_type = chan->band_type;
120 	band_changed = new->band_type != chan->band_type;
121 	rcd->band_changed = band_changed;
122 
123 	*chan = *new;
124 	return band_changed;
125 }
126 
127 static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
128 					  enum rtw89_sub_entity_idx idx,
129 					  const struct cfg80211_chan_def *chandef,
130 					  bool from_stack)
131 {
132 	struct rtw89_hal *hal = &rtwdev->hal;
133 
134 	hal->sub[idx].chandef = *chandef;
135 
136 	if (from_stack)
137 		set_bit(idx, hal->entity_map);
138 }
139 
140 void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
141 				 enum rtw89_sub_entity_idx idx,
142 				 const struct cfg80211_chan_def *chandef)
143 {
144 	__rtw89_config_entity_chandef(rtwdev, idx, chandef, true);
145 }
146 
147 void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
148 			      enum rtw89_sub_entity_idx idx,
149 			      const struct cfg80211_chan_def *chandef)
150 {
151 	struct rtw89_hal *hal = &rtwdev->hal;
152 	enum rtw89_sub_entity_idx cur;
153 
154 	if (chandef) {
155 		cur = atomic_cmpxchg(&hal->roc_entity_idx,
156 				     RTW89_SUB_ENTITY_IDLE, idx);
157 		if (cur != RTW89_SUB_ENTITY_IDLE) {
158 			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
159 				    "ROC still processing on entity %d\n", idx);
160 			return;
161 		}
162 
163 		hal->roc_chandef = *chandef;
164 	} else {
165 		cur = atomic_cmpxchg(&hal->roc_entity_idx, idx,
166 				     RTW89_SUB_ENTITY_IDLE);
167 		if (cur == idx)
168 			return;
169 
170 		if (cur == RTW89_SUB_ENTITY_IDLE)
171 			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
172 				    "ROC already finished on entity %d\n", idx);
173 		else
174 			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
175 				    "ROC is processing on entity %d\n", cur);
176 	}
177 }
178 
179 static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
180 {
181 	struct cfg80211_chan_def chandef = {0};
182 
183 	rtw89_get_default_chandef(&chandef);
184 	__rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0, &chandef, false);
185 }
186 
187 void rtw89_entity_init(struct rtw89_dev *rtwdev)
188 {
189 	struct rtw89_hal *hal = &rtwdev->hal;
190 
191 	bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
192 	atomic_set(&hal->roc_entity_idx, RTW89_SUB_ENTITY_IDLE);
193 	rtw89_config_default_chandef(rtwdev);
194 }
195 
196 enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
197 {
198 	struct rtw89_hal *hal = &rtwdev->hal;
199 	const struct cfg80211_chan_def *chandef;
200 	enum rtw89_entity_mode mode;
201 	struct rtw89_chan chan;
202 	u8 weight;
203 	u8 last;
204 	u8 idx;
205 
206 	weight = bitmap_weight(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
207 	switch (weight) {
208 	default:
209 		rtw89_warn(rtwdev, "unknown ent chan weight: %d\n", weight);
210 		bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
211 		fallthrough;
212 	case 0:
213 		rtw89_config_default_chandef(rtwdev);
214 		fallthrough;
215 	case 1:
216 		last = RTW89_SUB_ENTITY_0;
217 		mode = RTW89_ENTITY_MODE_SCC;
218 		break;
219 	case 2:
220 		last = RTW89_SUB_ENTITY_1;
221 		mode = rtw89_get_entity_mode(rtwdev);
222 		if (mode == RTW89_ENTITY_MODE_MCC)
223 			break;
224 
225 		mode = RTW89_ENTITY_MODE_MCC_PREPARE;
226 		break;
227 	}
228 
229 	for (idx = 0; idx <= last; idx++) {
230 		chandef = rtw89_chandef_get(rtwdev, idx);
231 		rtw89_get_channel_params(chandef, &chan);
232 		if (chan.channel == 0) {
233 			WARN(1, "Invalid channel on chanctx %d\n", idx);
234 			return RTW89_ENTITY_MODE_INVALID;
235 		}
236 
237 		rtw89_assign_entity_chan(rtwdev, idx, &chan);
238 	}
239 
240 	rtw89_set_entity_mode(rtwdev, mode);
241 	return mode;
242 }
243 
244 static void rtw89_chanctx_notify(struct rtw89_dev *rtwdev,
245 				 enum rtw89_chanctx_state state)
246 {
247 	const struct rtw89_chip_info *chip = rtwdev->chip;
248 	const struct rtw89_chanctx_listener *listener = chip->chanctx_listener;
249 	int i;
250 
251 	if (!listener)
252 		return;
253 
254 	for (i = 0; i < NUM_OF_RTW89_CHANCTX_CALLBACKS; i++) {
255 		if (!listener->callbacks[i])
256 			continue;
257 
258 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
259 			    "chanctx notify listener: cb %d, state %d\n",
260 			    i, state);
261 
262 		listener->callbacks[i](rtwdev, state);
263 	}
264 }
265 
266 static int rtw89_mcc_start(struct rtw89_dev *rtwdev)
267 {
268 	if (rtwdev->scanning)
269 		rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
270 
271 	rtw89_leave_lps(rtwdev);
272 
273 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC start\n");
274 	rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START);
275 	return 0;
276 }
277 
278 static void rtw89_mcc_stop(struct rtw89_dev *rtwdev)
279 {
280 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC stop\n");
281 	rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP);
282 }
283 
284 void rtw89_chanctx_work(struct work_struct *work)
285 {
286 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
287 						chanctx_work.work);
288 	enum rtw89_entity_mode mode;
289 	int ret;
290 
291 	mutex_lock(&rtwdev->mutex);
292 
293 	mode = rtw89_get_entity_mode(rtwdev);
294 	switch (mode) {
295 	case RTW89_ENTITY_MODE_MCC_PREPARE:
296 		rtw89_set_entity_mode(rtwdev, RTW89_ENTITY_MODE_MCC);
297 		rtw89_set_channel(rtwdev);
298 
299 		ret = rtw89_mcc_start(rtwdev);
300 		if (ret)
301 			rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
302 		break;
303 	default:
304 		break;
305 	}
306 
307 	mutex_unlock(&rtwdev->mutex);
308 }
309 
310 void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev)
311 {
312 	enum rtw89_entity_mode mode;
313 	u32 delay;
314 
315 	mode = rtw89_get_entity_mode(rtwdev);
316 	switch (mode) {
317 	default:
318 		return;
319 	case RTW89_ENTITY_MODE_MCC_PREPARE:
320 		delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE);
321 		break;
322 	}
323 
324 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
325 		    "queue chanctx work for mode %d with delay %d us\n",
326 		    mode, delay);
327 	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->chanctx_work,
328 				     usecs_to_jiffies(delay));
329 }
330 
331 int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
332 			  struct ieee80211_chanctx_conf *ctx)
333 {
334 	struct rtw89_hal *hal = &rtwdev->hal;
335 	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
336 	const struct rtw89_chip_info *chip = rtwdev->chip;
337 	u8 idx;
338 
339 	idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
340 	if (idx >= chip->support_chanctx_num)
341 		return -ENOENT;
342 
343 	rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
344 	rtw89_set_channel(rtwdev);
345 	cfg->idx = idx;
346 	hal->sub[idx].cfg = cfg;
347 	return 0;
348 }
349 
350 void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
351 			      struct ieee80211_chanctx_conf *ctx)
352 {
353 	struct rtw89_hal *hal = &rtwdev->hal;
354 	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
355 	enum rtw89_entity_mode mode;
356 	struct rtw89_vif *rtwvif;
357 	u8 drop, roll;
358 
359 	drop = cfg->idx;
360 	if (drop != RTW89_SUB_ENTITY_0)
361 		goto out;
362 
363 	roll = find_next_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY, drop + 1);
364 
365 	/* Follow rtw89_config_default_chandef() when rtw89_entity_recalc(). */
366 	if (roll == NUM_OF_RTW89_SUB_ENTITY)
367 		goto out;
368 
369 	/* RTW89_SUB_ENTITY_0 is going to release, and another exists.
370 	 * Make another roll down to RTW89_SUB_ENTITY_0 to replace.
371 	 */
372 	hal->sub[roll].cfg->idx = RTW89_SUB_ENTITY_0;
373 	hal->sub[RTW89_SUB_ENTITY_0] = hal->sub[roll];
374 
375 	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
376 		if (rtwvif->sub_entity_idx == roll)
377 			rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
378 	}
379 
380 	atomic_cmpxchg(&hal->roc_entity_idx, roll, RTW89_SUB_ENTITY_0);
381 
382 	drop = roll;
383 
384 out:
385 	mode = rtw89_get_entity_mode(rtwdev);
386 	switch (mode) {
387 	case RTW89_ENTITY_MODE_MCC:
388 		rtw89_mcc_stop(rtwdev);
389 		break;
390 	default:
391 		break;
392 	}
393 
394 	clear_bit(drop, hal->entity_map);
395 	rtw89_set_channel(rtwdev);
396 }
397 
398 void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
399 			      struct ieee80211_chanctx_conf *ctx,
400 			      u32 changed)
401 {
402 	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
403 	u8 idx = cfg->idx;
404 
405 	if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
406 		rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
407 		rtw89_set_channel(rtwdev);
408 	}
409 }
410 
411 int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
412 				 struct rtw89_vif *rtwvif,
413 				 struct ieee80211_chanctx_conf *ctx)
414 {
415 	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
416 
417 	rtwvif->sub_entity_idx = cfg->idx;
418 	return 0;
419 }
420 
421 void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
422 				    struct rtw89_vif *rtwvif,
423 				    struct ieee80211_chanctx_conf *ctx)
424 {
425 	rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
426 }
427