xref: /linux/net/mac80211/chan.c (revision c75c5ab575af7db707689cdbb5a5c458e9a034bb)
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_channel_type = cfg80211_get_chandef_type(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 struct ieee80211_chanctx *
61 ieee80211_new_chanctx(struct ieee80211_local *local,
62 		      const struct cfg80211_chan_def *chandef,
63 		      enum ieee80211_chanctx_mode mode)
64 {
65 	struct ieee80211_chanctx *ctx;
66 	u32 changed;
67 	int err;
68 
69 	lockdep_assert_held(&local->chanctx_mtx);
70 
71 	ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
72 	if (!ctx)
73 		return ERR_PTR(-ENOMEM);
74 
75 	ctx->conf.def = *chandef;
76 	ctx->conf.rx_chains_static = 1;
77 	ctx->conf.rx_chains_dynamic = 1;
78 	ctx->mode = mode;
79 
80 	/* acquire mutex to prevent idle from changing */
81 	mutex_lock(&local->mtx);
82 	/* turn idle off *before* setting channel -- some drivers need that */
83 	changed = ieee80211_idle_off(local);
84 	if (changed)
85 		ieee80211_hw_config(local, changed);
86 
87 	if (!local->use_chanctx) {
88 		local->_oper_channel_type =
89 			cfg80211_get_chandef_type(chandef);
90 		local->_oper_channel = chandef->chan;
91 		ieee80211_hw_config(local, 0);
92 	} else {
93 		err = drv_add_chanctx(local, ctx);
94 		if (err) {
95 			kfree(ctx);
96 			ctx = ERR_PTR(err);
97 
98 			ieee80211_recalc_idle(local);
99 			goto out;
100 		}
101 	}
102 
103 	/* and keep the mutex held until the new chanctx is on the list */
104 	list_add_rcu(&ctx->list, &local->chanctx_list);
105 
106  out:
107 	mutex_unlock(&local->mtx);
108 
109 	return ctx;
110 }
111 
112 static void ieee80211_free_chanctx(struct ieee80211_local *local,
113 				   struct ieee80211_chanctx *ctx)
114 {
115 	lockdep_assert_held(&local->chanctx_mtx);
116 
117 	WARN_ON_ONCE(ctx->refcount != 0);
118 
119 	if (!local->use_chanctx) {
120 		local->_oper_channel_type = NL80211_CHAN_NO_HT;
121 		ieee80211_hw_config(local, 0);
122 	} else {
123 		drv_remove_chanctx(local, ctx);
124 	}
125 
126 	list_del_rcu(&ctx->list);
127 	kfree_rcu(ctx, rcu_head);
128 
129 	mutex_lock(&local->mtx);
130 	ieee80211_recalc_idle(local);
131 	mutex_unlock(&local->mtx);
132 }
133 
134 static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
135 					struct ieee80211_chanctx *ctx)
136 {
137 	struct ieee80211_local *local = sdata->local;
138 	int ret;
139 
140 	lockdep_assert_held(&local->chanctx_mtx);
141 
142 	ret = drv_assign_vif_chanctx(local, sdata, ctx);
143 	if (ret)
144 		return ret;
145 
146 	rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
147 	ctx->refcount++;
148 
149 	ieee80211_recalc_txpower(sdata);
150 	sdata->vif.bss_conf.idle = false;
151 
152 	if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
153 	    sdata->vif.type != NL80211_IFTYPE_MONITOR)
154 		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
155 
156 	return 0;
157 }
158 
159 static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
160 					      struct ieee80211_chanctx *ctx)
161 {
162 	struct ieee80211_chanctx_conf *conf = &ctx->conf;
163 	struct ieee80211_sub_if_data *sdata;
164 	const struct cfg80211_chan_def *compat = NULL;
165 
166 	lockdep_assert_held(&local->chanctx_mtx);
167 
168 	rcu_read_lock();
169 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
170 
171 		if (!ieee80211_sdata_running(sdata))
172 			continue;
173 		if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
174 			continue;
175 
176 		if (!compat)
177 			compat = &sdata->vif.bss_conf.chandef;
178 
179 		compat = cfg80211_chandef_compatible(
180 				&sdata->vif.bss_conf.chandef, compat);
181 		if (!compat)
182 			break;
183 	}
184 	rcu_read_unlock();
185 
186 	if (WARN_ON_ONCE(!compat))
187 		return;
188 
189 	ieee80211_change_chanctx(local, ctx, compat);
190 }
191 
192 static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
193 					   struct ieee80211_chanctx *ctx)
194 {
195 	struct ieee80211_local *local = sdata->local;
196 
197 	lockdep_assert_held(&local->chanctx_mtx);
198 
199 	ctx->refcount--;
200 	rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
201 
202 	sdata->vif.bss_conf.idle = true;
203 
204 	if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
205 	    sdata->vif.type != NL80211_IFTYPE_MONITOR)
206 		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
207 
208 	drv_unassign_vif_chanctx(local, sdata, ctx);
209 
210 	if (ctx->refcount > 0) {
211 		ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
212 		ieee80211_recalc_smps_chanctx(local, ctx);
213 		ieee80211_recalc_radar_chanctx(local, ctx);
214 	}
215 }
216 
217 static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
218 {
219 	struct ieee80211_local *local = sdata->local;
220 	struct ieee80211_chanctx_conf *conf;
221 	struct ieee80211_chanctx *ctx;
222 
223 	lockdep_assert_held(&local->chanctx_mtx);
224 
225 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
226 					 lockdep_is_held(&local->chanctx_mtx));
227 	if (!conf)
228 		return;
229 
230 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
231 
232 	ieee80211_unassign_vif_chanctx(sdata, ctx);
233 	if (ctx->refcount == 0)
234 		ieee80211_free_chanctx(local, ctx);
235 }
236 
237 void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
238 				    struct ieee80211_chanctx *chanctx)
239 {
240 	struct ieee80211_sub_if_data *sdata;
241 	bool radar_enabled = false;
242 
243 	lockdep_assert_held(&local->chanctx_mtx);
244 
245 	rcu_read_lock();
246 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
247 		if (sdata->radar_required) {
248 			radar_enabled = true;
249 			break;
250 		}
251 	}
252 	rcu_read_unlock();
253 
254 	if (radar_enabled == chanctx->conf.radar_enabled)
255 		return;
256 
257 	chanctx->conf.radar_enabled = radar_enabled;
258 	local->radar_detect_enabled = chanctx->conf.radar_enabled;
259 
260 	if (!local->use_chanctx) {
261 		local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
262 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
263 	}
264 
265 	drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
266 }
267 
268 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
269 				   struct ieee80211_chanctx *chanctx)
270 {
271 	struct ieee80211_sub_if_data *sdata;
272 	u8 rx_chains_static, rx_chains_dynamic;
273 
274 	lockdep_assert_held(&local->chanctx_mtx);
275 
276 	rx_chains_static = 1;
277 	rx_chains_dynamic = 1;
278 
279 	rcu_read_lock();
280 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
281 		u8 needed_static, needed_dynamic;
282 
283 		if (!ieee80211_sdata_running(sdata))
284 			continue;
285 
286 		if (rcu_access_pointer(sdata->vif.chanctx_conf) !=
287 						&chanctx->conf)
288 			continue;
289 
290 		switch (sdata->vif.type) {
291 		case NL80211_IFTYPE_P2P_DEVICE:
292 			continue;
293 		case NL80211_IFTYPE_STATION:
294 			if (!sdata->u.mgd.associated)
295 				continue;
296 			break;
297 		case NL80211_IFTYPE_AP_VLAN:
298 			continue;
299 		case NL80211_IFTYPE_AP:
300 		case NL80211_IFTYPE_ADHOC:
301 		case NL80211_IFTYPE_WDS:
302 		case NL80211_IFTYPE_MESH_POINT:
303 			break;
304 		default:
305 			WARN_ON_ONCE(1);
306 		}
307 
308 		switch (sdata->smps_mode) {
309 		default:
310 			WARN_ONCE(1, "Invalid SMPS mode %d\n",
311 				  sdata->smps_mode);
312 			/* fall through */
313 		case IEEE80211_SMPS_OFF:
314 			needed_static = sdata->needed_rx_chains;
315 			needed_dynamic = sdata->needed_rx_chains;
316 			break;
317 		case IEEE80211_SMPS_DYNAMIC:
318 			needed_static = 1;
319 			needed_dynamic = sdata->needed_rx_chains;
320 			break;
321 		case IEEE80211_SMPS_STATIC:
322 			needed_static = 1;
323 			needed_dynamic = 1;
324 			break;
325 		}
326 
327 		rx_chains_static = max(rx_chains_static, needed_static);
328 		rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
329 	}
330 	rcu_read_unlock();
331 
332 	if (!local->use_chanctx) {
333 		if (rx_chains_static > 1)
334 			local->smps_mode = IEEE80211_SMPS_OFF;
335 		else if (rx_chains_dynamic > 1)
336 			local->smps_mode = IEEE80211_SMPS_DYNAMIC;
337 		else
338 			local->smps_mode = IEEE80211_SMPS_STATIC;
339 		ieee80211_hw_config(local, 0);
340 	}
341 
342 	if (rx_chains_static == chanctx->conf.rx_chains_static &&
343 	    rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
344 		return;
345 
346 	chanctx->conf.rx_chains_static = rx_chains_static;
347 	chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
348 	drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
349 }
350 
351 int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
352 			      const struct cfg80211_chan_def *chandef,
353 			      enum ieee80211_chanctx_mode mode)
354 {
355 	struct ieee80211_local *local = sdata->local;
356 	struct ieee80211_chanctx *ctx;
357 	int ret;
358 
359 	WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
360 
361 	mutex_lock(&local->chanctx_mtx);
362 	__ieee80211_vif_release_channel(sdata);
363 
364 	ctx = ieee80211_find_chanctx(local, chandef, mode);
365 	if (!ctx)
366 		ctx = ieee80211_new_chanctx(local, chandef, mode);
367 	if (IS_ERR(ctx)) {
368 		ret = PTR_ERR(ctx);
369 		goto out;
370 	}
371 
372 	sdata->vif.bss_conf.chandef = *chandef;
373 
374 	ret = ieee80211_assign_vif_chanctx(sdata, ctx);
375 	if (ret) {
376 		/* if assign fails refcount stays the same */
377 		if (ctx->refcount == 0)
378 			ieee80211_free_chanctx(local, ctx);
379 		goto out;
380 	}
381 
382 	ieee80211_recalc_smps_chanctx(local, ctx);
383 	ieee80211_recalc_radar_chanctx(local, ctx);
384  out:
385 	mutex_unlock(&local->chanctx_mtx);
386 	return ret;
387 }
388 
389 int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
390 				   const struct cfg80211_chan_def *chandef,
391 				   u32 *changed)
392 {
393 	struct ieee80211_local *local = sdata->local;
394 	struct ieee80211_chanctx_conf *conf;
395 	struct ieee80211_chanctx *ctx;
396 	int ret;
397 
398 	if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
399 				     IEEE80211_CHAN_DISABLED))
400 		return -EINVAL;
401 
402 	mutex_lock(&local->chanctx_mtx);
403 	if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) {
404 		ret = 0;
405 		goto out;
406 	}
407 
408 	if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
409 	    sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
410 		ret = -EINVAL;
411 		goto out;
412 	}
413 
414 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
415 					 lockdep_is_held(&local->chanctx_mtx));
416 	if (!conf) {
417 		ret = -EINVAL;
418 		goto out;
419 	}
420 
421 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
422 	if (!cfg80211_chandef_compatible(&conf->def, chandef)) {
423 		ret = -EINVAL;
424 		goto out;
425 	}
426 
427 	sdata->vif.bss_conf.chandef = *chandef;
428 
429 	ieee80211_recalc_chanctx_chantype(local, ctx);
430 
431 	*changed |= BSS_CHANGED_BANDWIDTH;
432 	ret = 0;
433  out:
434 	mutex_unlock(&local->chanctx_mtx);
435 	return ret;
436 }
437 
438 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
439 {
440 	WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
441 
442 	mutex_lock(&sdata->local->chanctx_mtx);
443 	__ieee80211_vif_release_channel(sdata);
444 	mutex_unlock(&sdata->local->chanctx_mtx);
445 }
446 
447 void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
448 {
449 	struct ieee80211_local *local = sdata->local;
450 	struct ieee80211_sub_if_data *ap;
451 	struct ieee80211_chanctx_conf *conf;
452 
453 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
454 		return;
455 
456 	ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
457 
458 	mutex_lock(&local->chanctx_mtx);
459 
460 	conf = rcu_dereference_protected(ap->vif.chanctx_conf,
461 					 lockdep_is_held(&local->chanctx_mtx));
462 	rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
463 	mutex_unlock(&local->chanctx_mtx);
464 }
465 
466 void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
467 					 bool clear)
468 {
469 	struct ieee80211_local *local = sdata->local;
470 	struct ieee80211_sub_if_data *vlan;
471 	struct ieee80211_chanctx_conf *conf;
472 
473 	ASSERT_RTNL();
474 
475 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
476 		return;
477 
478 	mutex_lock(&local->chanctx_mtx);
479 
480 	/*
481 	 * Check that conf exists, even when clearing this function
482 	 * must be called with the AP's channel context still there
483 	 * as it would otherwise cause VLANs to have an invalid
484 	 * channel context pointer for a while, possibly pointing
485 	 * to a channel context that has already been freed.
486 	 */
487 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
488 				lockdep_is_held(&local->chanctx_mtx));
489 	WARN_ON(!conf);
490 
491 	if (clear)
492 		conf = NULL;
493 
494 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
495 		rcu_assign_pointer(vlan->vif.chanctx_conf, conf);
496 
497 	mutex_unlock(&local->chanctx_mtx);
498 }
499 
500 void ieee80211_iter_chan_contexts_atomic(
501 	struct ieee80211_hw *hw,
502 	void (*iter)(struct ieee80211_hw *hw,
503 		     struct ieee80211_chanctx_conf *chanctx_conf,
504 		     void *data),
505 	void *iter_data)
506 {
507 	struct ieee80211_local *local = hw_to_local(hw);
508 	struct ieee80211_chanctx *ctx;
509 
510 	rcu_read_lock();
511 	list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
512 		if (ctx->driver_present)
513 			iter(hw, &ctx->conf, iter_data);
514 	rcu_read_unlock();
515 }
516 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
517