xref: /openbmc/linux/net/mac80211/chan.c (revision c4ee0af3)
1 /*
2  * mac80211 - channel management
3  */
4 
5 #include <linux/nl80211.h>
6 #include <linux/export.h>
7 #include <linux/rtnetlink.h>
8 #include <net/cfg80211.h>
9 #include "ieee80211_i.h"
10 #include "driver-ops.h"
11 
12 static void ieee80211_change_chanctx(struct ieee80211_local *local,
13 				     struct ieee80211_chanctx *ctx,
14 				     const struct cfg80211_chan_def *chandef)
15 {
16 	if (cfg80211_chandef_identical(&ctx->conf.def, chandef))
17 		return;
18 
19 	WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
20 
21 	ctx->conf.def = *chandef;
22 	drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
23 
24 	if (!local->use_chanctx) {
25 		local->_oper_chandef = *chandef;
26 		ieee80211_hw_config(local, 0);
27 	}
28 }
29 
30 static struct ieee80211_chanctx *
31 ieee80211_find_chanctx(struct ieee80211_local *local,
32 		       const struct cfg80211_chan_def *chandef,
33 		       enum ieee80211_chanctx_mode mode)
34 {
35 	struct ieee80211_chanctx *ctx;
36 
37 	lockdep_assert_held(&local->chanctx_mtx);
38 
39 	if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
40 		return NULL;
41 
42 	list_for_each_entry(ctx, &local->chanctx_list, list) {
43 		const struct cfg80211_chan_def *compat;
44 
45 		if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
46 			continue;
47 
48 		compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
49 		if (!compat)
50 			continue;
51 
52 		ieee80211_change_chanctx(local, ctx, compat);
53 
54 		return ctx;
55 	}
56 
57 	return NULL;
58 }
59 
60 static bool ieee80211_is_radar_required(struct ieee80211_local *local)
61 {
62 	struct ieee80211_sub_if_data *sdata;
63 
64 	rcu_read_lock();
65 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
66 		if (sdata->radar_required) {
67 			rcu_read_unlock();
68 			return true;
69 		}
70 	}
71 	rcu_read_unlock();
72 
73 	return false;
74 }
75 
76 static struct ieee80211_chanctx *
77 ieee80211_new_chanctx(struct ieee80211_local *local,
78 		      const struct cfg80211_chan_def *chandef,
79 		      enum ieee80211_chanctx_mode mode)
80 {
81 	struct ieee80211_chanctx *ctx;
82 	u32 changed;
83 	int err;
84 
85 	lockdep_assert_held(&local->chanctx_mtx);
86 
87 	ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
88 	if (!ctx)
89 		return ERR_PTR(-ENOMEM);
90 
91 	ctx->conf.def = *chandef;
92 	ctx->conf.rx_chains_static = 1;
93 	ctx->conf.rx_chains_dynamic = 1;
94 	ctx->mode = mode;
95 	ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
96 	if (!local->use_chanctx)
97 		local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
98 
99 	/* acquire mutex to prevent idle from changing */
100 	mutex_lock(&local->mtx);
101 	/* turn idle off *before* setting channel -- some drivers need that */
102 	changed = ieee80211_idle_off(local);
103 	if (changed)
104 		ieee80211_hw_config(local, changed);
105 
106 	if (!local->use_chanctx) {
107 		local->_oper_chandef = *chandef;
108 		ieee80211_hw_config(local, 0);
109 	} else {
110 		err = drv_add_chanctx(local, ctx);
111 		if (err) {
112 			kfree(ctx);
113 			ctx = ERR_PTR(err);
114 
115 			ieee80211_recalc_idle(local);
116 			goto out;
117 		}
118 	}
119 
120 	/* and keep the mutex held until the new chanctx is on the list */
121 	list_add_rcu(&ctx->list, &local->chanctx_list);
122 
123  out:
124 	mutex_unlock(&local->mtx);
125 
126 	return ctx;
127 }
128 
129 static void ieee80211_free_chanctx(struct ieee80211_local *local,
130 				   struct ieee80211_chanctx *ctx)
131 {
132 	bool check_single_channel = false;
133 	lockdep_assert_held(&local->chanctx_mtx);
134 
135 	WARN_ON_ONCE(ctx->refcount != 0);
136 
137 	if (!local->use_chanctx) {
138 		struct cfg80211_chan_def *chandef = &local->_oper_chandef;
139 		chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
140 		chandef->center_freq1 = chandef->chan->center_freq;
141 		chandef->center_freq2 = 0;
142 
143 		/* NOTE: Disabling radar is only valid here for
144 		 * single channel context. To be sure, check it ...
145 		 */
146 		if (local->hw.conf.radar_enabled)
147 			check_single_channel = true;
148 		local->hw.conf.radar_enabled = false;
149 
150 		ieee80211_hw_config(local, 0);
151 	} else {
152 		drv_remove_chanctx(local, ctx);
153 	}
154 
155 	list_del_rcu(&ctx->list);
156 	kfree_rcu(ctx, rcu_head);
157 
158 	/* throw a warning if this wasn't the only channel context. */
159 	WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
160 
161 	mutex_lock(&local->mtx);
162 	ieee80211_recalc_idle(local);
163 	mutex_unlock(&local->mtx);
164 }
165 
166 static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
167 					struct ieee80211_chanctx *ctx)
168 {
169 	struct ieee80211_local *local = sdata->local;
170 	int ret;
171 
172 	lockdep_assert_held(&local->chanctx_mtx);
173 
174 	ret = drv_assign_vif_chanctx(local, sdata, ctx);
175 	if (ret)
176 		return ret;
177 
178 	rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
179 	ctx->refcount++;
180 
181 	ieee80211_recalc_txpower(sdata);
182 	sdata->vif.bss_conf.idle = false;
183 
184 	if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
185 	    sdata->vif.type != NL80211_IFTYPE_MONITOR)
186 		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
187 
188 	return 0;
189 }
190 
191 static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
192 					      struct ieee80211_chanctx *ctx)
193 {
194 	struct ieee80211_chanctx_conf *conf = &ctx->conf;
195 	struct ieee80211_sub_if_data *sdata;
196 	const struct cfg80211_chan_def *compat = NULL;
197 
198 	lockdep_assert_held(&local->chanctx_mtx);
199 
200 	rcu_read_lock();
201 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
202 
203 		if (!ieee80211_sdata_running(sdata))
204 			continue;
205 		if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
206 			continue;
207 
208 		if (!compat)
209 			compat = &sdata->vif.bss_conf.chandef;
210 
211 		compat = cfg80211_chandef_compatible(
212 				&sdata->vif.bss_conf.chandef, compat);
213 		if (!compat)
214 			break;
215 	}
216 	rcu_read_unlock();
217 
218 	if (WARN_ON_ONCE(!compat))
219 		return;
220 
221 	ieee80211_change_chanctx(local, ctx, compat);
222 }
223 
224 static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
225 					   struct ieee80211_chanctx *ctx)
226 {
227 	struct ieee80211_local *local = sdata->local;
228 
229 	lockdep_assert_held(&local->chanctx_mtx);
230 
231 	ctx->refcount--;
232 	rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
233 
234 	sdata->vif.bss_conf.idle = true;
235 
236 	if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
237 	    sdata->vif.type != NL80211_IFTYPE_MONITOR)
238 		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
239 
240 	drv_unassign_vif_chanctx(local, sdata, ctx);
241 
242 	if (ctx->refcount > 0) {
243 		ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
244 		ieee80211_recalc_smps_chanctx(local, ctx);
245 		ieee80211_recalc_radar_chanctx(local, ctx);
246 	}
247 }
248 
249 static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
250 {
251 	struct ieee80211_local *local = sdata->local;
252 	struct ieee80211_chanctx_conf *conf;
253 	struct ieee80211_chanctx *ctx;
254 
255 	lockdep_assert_held(&local->chanctx_mtx);
256 
257 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
258 					 lockdep_is_held(&local->chanctx_mtx));
259 	if (!conf)
260 		return;
261 
262 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
263 
264 	ieee80211_unassign_vif_chanctx(sdata, ctx);
265 	if (ctx->refcount == 0)
266 		ieee80211_free_chanctx(local, ctx);
267 }
268 
269 void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
270 				    struct ieee80211_chanctx *chanctx)
271 {
272 	bool radar_enabled;
273 
274 	lockdep_assert_held(&local->chanctx_mtx);
275 
276 	radar_enabled = ieee80211_is_radar_required(local);
277 
278 	if (radar_enabled == chanctx->conf.radar_enabled)
279 		return;
280 
281 	chanctx->conf.radar_enabled = radar_enabled;
282 	local->radar_detect_enabled = chanctx->conf.radar_enabled;
283 
284 	if (!local->use_chanctx) {
285 		local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
286 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
287 	}
288 
289 	drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
290 }
291 
292 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
293 				   struct ieee80211_chanctx *chanctx)
294 {
295 	struct ieee80211_sub_if_data *sdata;
296 	u8 rx_chains_static, rx_chains_dynamic;
297 
298 	lockdep_assert_held(&local->chanctx_mtx);
299 
300 	rx_chains_static = 1;
301 	rx_chains_dynamic = 1;
302 
303 	rcu_read_lock();
304 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
305 		u8 needed_static, needed_dynamic;
306 
307 		if (!ieee80211_sdata_running(sdata))
308 			continue;
309 
310 		if (rcu_access_pointer(sdata->vif.chanctx_conf) !=
311 						&chanctx->conf)
312 			continue;
313 
314 		switch (sdata->vif.type) {
315 		case NL80211_IFTYPE_P2P_DEVICE:
316 			continue;
317 		case NL80211_IFTYPE_STATION:
318 			if (!sdata->u.mgd.associated)
319 				continue;
320 			break;
321 		case NL80211_IFTYPE_AP_VLAN:
322 			continue;
323 		case NL80211_IFTYPE_AP:
324 		case NL80211_IFTYPE_ADHOC:
325 		case NL80211_IFTYPE_WDS:
326 		case NL80211_IFTYPE_MESH_POINT:
327 			break;
328 		default:
329 			WARN_ON_ONCE(1);
330 		}
331 
332 		switch (sdata->smps_mode) {
333 		default:
334 			WARN_ONCE(1, "Invalid SMPS mode %d\n",
335 				  sdata->smps_mode);
336 			/* fall through */
337 		case IEEE80211_SMPS_OFF:
338 			needed_static = sdata->needed_rx_chains;
339 			needed_dynamic = sdata->needed_rx_chains;
340 			break;
341 		case IEEE80211_SMPS_DYNAMIC:
342 			needed_static = 1;
343 			needed_dynamic = sdata->needed_rx_chains;
344 			break;
345 		case IEEE80211_SMPS_STATIC:
346 			needed_static = 1;
347 			needed_dynamic = 1;
348 			break;
349 		}
350 
351 		rx_chains_static = max(rx_chains_static, needed_static);
352 		rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
353 	}
354 	rcu_read_unlock();
355 
356 	if (!local->use_chanctx) {
357 		if (rx_chains_static > 1)
358 			local->smps_mode = IEEE80211_SMPS_OFF;
359 		else if (rx_chains_dynamic > 1)
360 			local->smps_mode = IEEE80211_SMPS_DYNAMIC;
361 		else
362 			local->smps_mode = IEEE80211_SMPS_STATIC;
363 		ieee80211_hw_config(local, 0);
364 	}
365 
366 	if (rx_chains_static == chanctx->conf.rx_chains_static &&
367 	    rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
368 		return;
369 
370 	chanctx->conf.rx_chains_static = rx_chains_static;
371 	chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
372 	drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
373 }
374 
375 int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
376 			      const struct cfg80211_chan_def *chandef,
377 			      enum ieee80211_chanctx_mode mode)
378 {
379 	struct ieee80211_local *local = sdata->local;
380 	struct ieee80211_chanctx *ctx;
381 	int ret;
382 
383 	WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
384 
385 	mutex_lock(&local->chanctx_mtx);
386 	__ieee80211_vif_release_channel(sdata);
387 
388 	ctx = ieee80211_find_chanctx(local, chandef, mode);
389 	if (!ctx)
390 		ctx = ieee80211_new_chanctx(local, chandef, mode);
391 	if (IS_ERR(ctx)) {
392 		ret = PTR_ERR(ctx);
393 		goto out;
394 	}
395 
396 	sdata->vif.bss_conf.chandef = *chandef;
397 
398 	ret = ieee80211_assign_vif_chanctx(sdata, ctx);
399 	if (ret) {
400 		/* if assign fails refcount stays the same */
401 		if (ctx->refcount == 0)
402 			ieee80211_free_chanctx(local, ctx);
403 		goto out;
404 	}
405 
406 	ieee80211_recalc_smps_chanctx(local, ctx);
407 	ieee80211_recalc_radar_chanctx(local, ctx);
408  out:
409 	mutex_unlock(&local->chanctx_mtx);
410 	return ret;
411 }
412 
413 int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
414 				 const struct cfg80211_chan_def *chandef,
415 				 u32 *changed)
416 {
417 	struct ieee80211_local *local = sdata->local;
418 	struct ieee80211_chanctx_conf *conf;
419 	struct ieee80211_chanctx *ctx;
420 	int ret;
421 	u32 chanctx_changed = 0;
422 
423 	/* should never be called if not performing a channel switch. */
424 	if (WARN_ON(!sdata->vif.csa_active))
425 		return -EINVAL;
426 
427 	if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
428 				     IEEE80211_CHAN_DISABLED))
429 		return -EINVAL;
430 
431 	mutex_lock(&local->chanctx_mtx);
432 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
433 					 lockdep_is_held(&local->chanctx_mtx));
434 	if (!conf) {
435 		ret = -EINVAL;
436 		goto out;
437 	}
438 
439 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
440 	if (ctx->refcount != 1) {
441 		ret = -EINVAL;
442 		goto out;
443 	}
444 
445 	if (sdata->vif.bss_conf.chandef.width != chandef->width) {
446 		chanctx_changed = IEEE80211_CHANCTX_CHANGE_WIDTH;
447 		*changed |= BSS_CHANGED_BANDWIDTH;
448 	}
449 
450 	sdata->vif.bss_conf.chandef = *chandef;
451 	ctx->conf.def = *chandef;
452 
453 	chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL;
454 	drv_change_chanctx(local, ctx, chanctx_changed);
455 
456 	ieee80211_recalc_chanctx_chantype(local, ctx);
457 	ieee80211_recalc_smps_chanctx(local, ctx);
458 	ieee80211_recalc_radar_chanctx(local, ctx);
459 
460 	ret = 0;
461  out:
462 	mutex_unlock(&local->chanctx_mtx);
463 	return ret;
464 }
465 
466 int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
467 				   const struct cfg80211_chan_def *chandef,
468 				   u32 *changed)
469 {
470 	struct ieee80211_local *local = sdata->local;
471 	struct ieee80211_chanctx_conf *conf;
472 	struct ieee80211_chanctx *ctx;
473 	int ret;
474 
475 	if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
476 				     IEEE80211_CHAN_DISABLED))
477 		return -EINVAL;
478 
479 	mutex_lock(&local->chanctx_mtx);
480 	if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) {
481 		ret = 0;
482 		goto out;
483 	}
484 
485 	if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
486 	    sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
487 		ret = -EINVAL;
488 		goto out;
489 	}
490 
491 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
492 					 lockdep_is_held(&local->chanctx_mtx));
493 	if (!conf) {
494 		ret = -EINVAL;
495 		goto out;
496 	}
497 
498 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
499 	if (!cfg80211_chandef_compatible(&conf->def, chandef)) {
500 		ret = -EINVAL;
501 		goto out;
502 	}
503 
504 	sdata->vif.bss_conf.chandef = *chandef;
505 
506 	ieee80211_recalc_chanctx_chantype(local, ctx);
507 
508 	*changed |= BSS_CHANGED_BANDWIDTH;
509 	ret = 0;
510  out:
511 	mutex_unlock(&local->chanctx_mtx);
512 	return ret;
513 }
514 
515 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
516 {
517 	WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
518 
519 	mutex_lock(&sdata->local->chanctx_mtx);
520 	__ieee80211_vif_release_channel(sdata);
521 	mutex_unlock(&sdata->local->chanctx_mtx);
522 }
523 
524 void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
525 {
526 	struct ieee80211_local *local = sdata->local;
527 	struct ieee80211_sub_if_data *ap;
528 	struct ieee80211_chanctx_conf *conf;
529 
530 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
531 		return;
532 
533 	ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
534 
535 	mutex_lock(&local->chanctx_mtx);
536 
537 	conf = rcu_dereference_protected(ap->vif.chanctx_conf,
538 					 lockdep_is_held(&local->chanctx_mtx));
539 	rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
540 	mutex_unlock(&local->chanctx_mtx);
541 }
542 
543 void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
544 					 bool clear)
545 {
546 	struct ieee80211_local *local = sdata->local;
547 	struct ieee80211_sub_if_data *vlan;
548 	struct ieee80211_chanctx_conf *conf;
549 
550 	ASSERT_RTNL();
551 
552 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
553 		return;
554 
555 	mutex_lock(&local->chanctx_mtx);
556 
557 	/*
558 	 * Check that conf exists, even when clearing this function
559 	 * must be called with the AP's channel context still there
560 	 * as it would otherwise cause VLANs to have an invalid
561 	 * channel context pointer for a while, possibly pointing
562 	 * to a channel context that has already been freed.
563 	 */
564 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
565 				lockdep_is_held(&local->chanctx_mtx));
566 	WARN_ON(!conf);
567 
568 	if (clear)
569 		conf = NULL;
570 
571 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
572 		rcu_assign_pointer(vlan->vif.chanctx_conf, conf);
573 
574 	mutex_unlock(&local->chanctx_mtx);
575 }
576 
577 void ieee80211_iter_chan_contexts_atomic(
578 	struct ieee80211_hw *hw,
579 	void (*iter)(struct ieee80211_hw *hw,
580 		     struct ieee80211_chanctx_conf *chanctx_conf,
581 		     void *data),
582 	void *iter_data)
583 {
584 	struct ieee80211_local *local = hw_to_local(hw);
585 	struct ieee80211_chanctx *ctx;
586 
587 	rcu_read_lock();
588 	list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
589 		if (ctx->driver_present)
590 			iter(hw, &ctx->conf, iter_data);
591 	rcu_read_unlock();
592 }
593 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
594