xref: /linux/net/mac80211/nan.c (revision 6a4c4656b0d2d4056a1f0c35442db4e8a5cf8021)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * NAN mode implementation
4  * Copyright(c) 2025-2026 Intel Corporation
5  */
6 #include <net/mac80211.h>
7 
8 #include "ieee80211_i.h"
9 #include "driver-ops.h"
10 #include "sta_info.h"
11 
12 static void
13 ieee80211_nan_init_channel(struct ieee80211_nan_channel *nan_channel,
14 			   struct cfg80211_nan_channel *cfg_nan_channel)
15 {
16 	memset(nan_channel, 0, sizeof(*nan_channel));
17 
18 	nan_channel->chanreq.oper = cfg_nan_channel->chandef;
19 	memcpy(nan_channel->channel_entry, cfg_nan_channel->channel_entry,
20 	       sizeof(nan_channel->channel_entry));
21 	nan_channel->needed_rx_chains = cfg_nan_channel->rx_nss;
22 }
23 
24 static void
25 ieee80211_nan_update_channel(struct ieee80211_local *local,
26 			     struct ieee80211_nan_channel *nan_channel,
27 			     struct cfg80211_nan_channel *cfg_nan_channel,
28 			     bool deferred)
29 {
30 	struct ieee80211_chanctx_conf *conf;
31 	bool reducing_nss;
32 
33 	if (WARN_ON(!cfg80211_chandef_identical(&nan_channel->chanreq.oper,
34 						&cfg_nan_channel->chandef)))
35 		return;
36 
37 	if (WARN_ON(memcmp(nan_channel->channel_entry,
38 			   cfg_nan_channel->channel_entry,
39 			   sizeof(nan_channel->channel_entry))))
40 		return;
41 
42 	if (nan_channel->needed_rx_chains == cfg_nan_channel->rx_nss)
43 		return;
44 
45 	reducing_nss = nan_channel->needed_rx_chains > cfg_nan_channel->rx_nss;
46 	nan_channel->needed_rx_chains = cfg_nan_channel->rx_nss;
47 
48 	conf = nan_channel->chanctx_conf;
49 
50 	/*
51 	 * If we are adding NSSs, we need to be ready before notifying the peer,
52 	 * if we are reducing NSSs, we need to wait until the peer is notified.
53 	 */
54 	if (!conf || (deferred && reducing_nss))
55 		return;
56 
57 	ieee80211_recalc_smps_chanctx(local, container_of(conf,
58 							  struct ieee80211_chanctx,
59 							  conf));
60 }
61 
62 static int
63 ieee80211_nan_use_chanctx(struct ieee80211_sub_if_data *sdata,
64 			  struct ieee80211_nan_channel *nan_channel,
65 			  bool assign_on_failure)
66 {
67 	struct ieee80211_chanctx *ctx;
68 	bool reused_ctx;
69 
70 	if (!nan_channel->chanreq.oper.chan)
71 		return -EINVAL;
72 
73 	if (ieee80211_check_combinations(sdata, &nan_channel->chanreq.oper,
74 					 IEEE80211_CHANCTX_SHARED, 0, -1))
75 		return -EBUSY;
76 
77 	ctx = ieee80211_find_or_create_chanctx(sdata, &nan_channel->chanreq,
78 					       IEEE80211_CHANCTX_SHARED,
79 					       assign_on_failure,
80 					       &reused_ctx);
81 	if (IS_ERR(ctx))
82 		return PTR_ERR(ctx);
83 
84 	nan_channel->chanctx_conf = &ctx->conf;
85 
86 	/*
87 	 * In case an existing channel context is being used, we marked it as
88 	 * will_be_used, now that it is assigned - clear this indication
89 	 */
90 	if (reused_ctx) {
91 		WARN_ON(!ctx->will_be_used);
92 		ctx->will_be_used = false;
93 	}
94 	ieee80211_recalc_chanctx_min_def(sdata->local, ctx);
95 	ieee80211_recalc_smps_chanctx(sdata->local, ctx);
96 
97 	return 0;
98 }
99 
100 static void
101 ieee80211_nan_update_peer_channels(struct ieee80211_sub_if_data *sdata,
102 				   struct ieee80211_chanctx_conf *removed_conf)
103 {
104 	struct ieee80211_local *local = sdata->local;
105 	struct sta_info *sta;
106 
107 	lockdep_assert_wiphy(local->hw.wiphy);
108 
109 	list_for_each_entry(sta, &local->sta_list, list) {
110 		struct ieee80211_nan_peer_sched *peer_sched;
111 		int write_idx = 0;
112 		bool updated = false;
113 
114 		if (sta->sdata != sdata)
115 			continue;
116 
117 		peer_sched = sta->sta.nan_sched;
118 		if (!peer_sched)
119 			continue;
120 
121 		/* NULL out map slots for channels being removed */
122 		for (int i = 0; i < peer_sched->n_channels; i++) {
123 			if (peer_sched->channels[i].chanctx_conf != removed_conf)
124 				continue;
125 
126 			for (int m = 0; m < CFG80211_NAN_MAX_PEER_MAPS; m++) {
127 				struct ieee80211_nan_peer_map *map =
128 					&peer_sched->maps[m];
129 
130 				if (map->map_id == CFG80211_NAN_INVALID_MAP_ID)
131 					continue;
132 
133 				for (int s = 0; s < ARRAY_SIZE(map->slots); s++)
134 					if (map->slots[s] == &peer_sched->channels[i])
135 						map->slots[s] = NULL;
136 			}
137 		}
138 
139 		/* Compact channels array, removing those with removed_conf */
140 		for (int i = 0; i < peer_sched->n_channels; i++) {
141 			if (peer_sched->channels[i].chanctx_conf == removed_conf) {
142 				updated = true;
143 				continue;
144 			}
145 
146 			if (write_idx != i) {
147 				/* Update map pointers before moving */
148 				for (int m = 0; m < CFG80211_NAN_MAX_PEER_MAPS; m++) {
149 					struct ieee80211_nan_peer_map *map =
150 						&peer_sched->maps[m];
151 
152 					if (map->map_id == CFG80211_NAN_INVALID_MAP_ID)
153 						continue;
154 
155 					for (int s = 0; s < ARRAY_SIZE(map->slots); s++)
156 						if (map->slots[s] == &peer_sched->channels[i])
157 							map->slots[s] = &peer_sched->channels[write_idx];
158 				}
159 
160 				peer_sched->channels[write_idx] = peer_sched->channels[i];
161 			}
162 			write_idx++;
163 		}
164 
165 		/* Clear any remaining entries at the end */
166 		for (int i = write_idx; i < peer_sched->n_channels; i++)
167 			memset(&peer_sched->channels[i], 0, sizeof(peer_sched->channels[i]));
168 
169 		peer_sched->n_channels = write_idx;
170 
171 		if (updated)
172 			drv_nan_peer_sched_changed(local, sdata, sta);
173 	}
174 }
175 
176 static void
177 ieee80211_nan_remove_channel(struct ieee80211_sub_if_data *sdata,
178 			     struct ieee80211_nan_channel *nan_channel)
179 {
180 	struct ieee80211_chanctx_conf *conf;
181 	struct ieee80211_chanctx *ctx;
182 	struct ieee80211_nan_sched_cfg *sched_cfg = &sdata->vif.cfg.nan_sched;
183 
184 	if (WARN_ON(!nan_channel))
185 		return;
186 
187 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
188 
189 	if (!nan_channel->chanreq.oper.chan)
190 		return;
191 
192 	for (int slot = 0; slot < ARRAY_SIZE(sched_cfg->schedule); slot++)
193 		if (sched_cfg->schedule[slot] == nan_channel)
194 			sched_cfg->schedule[slot] = NULL;
195 
196 	conf = nan_channel->chanctx_conf;
197 
198 	/* If any peer nan schedule uses this chanctx, update them */
199 	if (conf)
200 		ieee80211_nan_update_peer_channels(sdata, conf);
201 
202 	memset(nan_channel, 0, sizeof(*nan_channel));
203 
204 	/* Update the driver before (possibly) releasing the channel context */
205 	drv_vif_cfg_changed(sdata->local, sdata, BSS_CHANGED_NAN_LOCAL_SCHED);
206 
207 	/* Channel might not have a chanctx if it was ULWed */
208 	if (!conf)
209 		return;
210 
211 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
212 
213 	if (ieee80211_chanctx_num_assigned(sdata->local, ctx) > 0) {
214 		ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
215 		ieee80211_recalc_smps_chanctx(sdata->local, ctx);
216 		ieee80211_recalc_chanctx_min_def(sdata->local, ctx);
217 	}
218 
219 	if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0)
220 		ieee80211_free_chanctx(sdata->local, ctx, false);
221 }
222 
223 static void
224 ieee80211_nan_update_all_ndi_carriers(struct ieee80211_local *local)
225 {
226 	struct ieee80211_sub_if_data *sdata;
227 
228 	lockdep_assert_wiphy(local->hw.wiphy);
229 
230 	/* Iterate all interfaces and update carrier for NDI interfaces */
231 	list_for_each_entry(sdata, &local->interfaces, list) {
232 		if (!ieee80211_sdata_running(sdata) ||
233 		    sdata->vif.type != NL80211_IFTYPE_NAN_DATA)
234 			continue;
235 
236 		ieee80211_nan_update_ndi_carrier(sdata);
237 	}
238 }
239 
240 static struct ieee80211_nan_channel *
241 ieee80211_nan_find_free_channel(struct ieee80211_nan_sched_cfg *sched_cfg)
242 {
243 	for (int i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) {
244 		if (!sched_cfg->channels[i].chanreq.oper.chan)
245 			return &sched_cfg->channels[i];
246 	}
247 
248 	return NULL;
249 }
250 
251 int ieee80211_nan_set_local_sched(struct ieee80211_sub_if_data *sdata,
252 				  struct cfg80211_nan_local_sched *sched)
253 {
254 	struct ieee80211_nan_channel *sched_idx_to_chan[IEEE80211_NAN_MAX_CHANNELS] = {};
255 	struct ieee80211_nan_sched_cfg *sched_cfg = &sdata->vif.cfg.nan_sched;
256 	struct ieee80211_nan_sched_cfg backup_sched;
257 	int ret;
258 
259 	if (sched->n_channels > IEEE80211_NAN_MAX_CHANNELS)
260 		return -EOPNOTSUPP;
261 
262 	if (sched->nan_avail_blob_len > IEEE80211_NAN_AVAIL_BLOB_MAX_LEN)
263 		return -EINVAL;
264 
265 	/*
266 	 * If a deferred schedule update is pending completion, new updates are
267 	 * not allowed. Only allow to configure an empty schedule so NAN can be
268 	 * stopped in the middle of a deferred update. This is fine because
269 	 * empty schedule means the local NAN device will not be available for
270 	 * peers anymore so there is no need to update peers about a new
271 	 * schedule.
272 	 */
273 	if (WARN_ON(sched_cfg->deferred && sched->n_channels))
274 		return -EBUSY;
275 
276 	bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
277 
278 	memcpy(backup_sched.schedule, sched_cfg->schedule,
279 	       sizeof(backup_sched.schedule));
280 	memcpy(backup_sched.channels, sched_cfg->channels,
281 	       sizeof(backup_sched.channels));
282 	memcpy(backup_sched.avail_blob, sched_cfg->avail_blob,
283 	       sizeof(backup_sched.avail_blob));
284 	backup_sched.avail_blob_len = sched_cfg->avail_blob_len;
285 
286 	memcpy(sched_cfg->avail_blob, sched->nan_avail_blob,
287 	       sched->nan_avail_blob_len);
288 	sched_cfg->avail_blob_len = sched->nan_avail_blob_len;
289 
290 	/*
291 	 * Remove channels that are no longer in the new schedule to free up
292 	 * resources before adding new channels. For deferred schedule, channels
293 	 * will be removed when the schedule is applied.
294 	 * Create a mapping from sched index to sched_cfg channel
295 	 */
296 	for (int i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) {
297 		bool still_needed = false;
298 
299 		if (!sched_cfg->channels[i].chanreq.oper.chan)
300 			continue;
301 
302 		for (int j = 0; j < sched->n_channels; j++) {
303 			if (cfg80211_chandef_identical(&sched_cfg->channels[i].chanreq.oper,
304 						       &sched->nan_channels[j].chandef)) {
305 				sched_idx_to_chan[j] =
306 					&sched_cfg->channels[i];
307 				still_needed = true;
308 				break;
309 			}
310 		}
311 
312 		if (!still_needed) {
313 			__set_bit(i, sdata->u.nan.removed_channels);
314 			if (!sched->deferred)
315 				ieee80211_nan_remove_channel(sdata,
316 							     &sched_cfg->channels[i]);
317 		}
318 	}
319 
320 	for (int i = 0; i < sched->n_channels; i++) {
321 		struct ieee80211_nan_channel *chan = sched_idx_to_chan[i];
322 
323 		if (chan) {
324 			ieee80211_nan_update_channel(sdata->local, chan,
325 						     &sched->nan_channels[i],
326 						     sched->deferred);
327 		} else {
328 			chan = ieee80211_nan_find_free_channel(sched_cfg);
329 			if (WARN_ON(!chan)) {
330 				ret = -EINVAL;
331 				goto err;
332 			}
333 
334 			sched_idx_to_chan[i] = chan;
335 			ieee80211_nan_init_channel(chan,
336 						   &sched->nan_channels[i]);
337 		}
338 
339 		/* Also a pre-existing channel might have been ULWed, so no chanctx */
340 		if (!chan->chanctx_conf) {
341 			ret = ieee80211_nan_use_chanctx(sdata, chan, false);
342 			if (ret) {
343 				memset(chan, 0, sizeof(*chan));
344 				goto err;
345 			}
346 		}
347 	}
348 
349 	for (int s = 0; s < ARRAY_SIZE(sched_cfg->schedule); s++) {
350 		if (sched->schedule[s] < ARRAY_SIZE(sched_idx_to_chan))
351 			sched_cfg->schedule[s] =
352 				sched_idx_to_chan[sched->schedule[s]];
353 		else
354 			sched_cfg->schedule[s] = NULL;
355 	}
356 
357 	sched_cfg->deferred = sched->deferred;
358 
359 	drv_vif_cfg_changed(sdata->local, sdata, BSS_CHANGED_NAN_LOCAL_SCHED);
360 
361 	/*
362 	 * For deferred update, don't update NDI carriers yet as the new
363 	 * schedule is not yet applied so common slots don't change. The NDI
364 	 * carrier will be updated once the driver notifies the new schedule is
365 	 * applied.
366 	 */
367 	if (sched_cfg->deferred)
368 		return 0;
369 
370 	ieee80211_nan_update_all_ndi_carriers(sdata->local);
371 	bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
372 
373 	return 0;
374 err:
375 	/* Remove newly added channels */
376 	for (int i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) {
377 		struct cfg80211_chan_def *chan_def =
378 			&sched_cfg->channels[i].chanreq.oper;
379 
380 		if (!chan_def->chan)
381 			continue;
382 
383 		if (!cfg80211_chandef_identical(&backup_sched.channels[i].chanreq.oper,
384 						chan_def))
385 			ieee80211_nan_remove_channel(sdata,
386 						     &sched_cfg->channels[i]);
387 	}
388 
389 	/* Re-add all backed up channels */
390 	for (int i = 0; i < ARRAY_SIZE(backup_sched.channels); i++) {
391 		struct ieee80211_nan_channel *chan = &sched_cfg->channels[i];
392 
393 		*chan = backup_sched.channels[i];
394 
395 		/*
396 		 * For deferred update, no channels were removed and the channel
397 		 * context didn't change, so nothing else to do.
398 		 */
399 		if (!chan->chanctx_conf || sched->deferred)
400 			continue;
401 
402 		if (test_bit(i, sdata->u.nan.removed_channels)) {
403 			/* Clear the stale chanctx pointer */
404 			chan->chanctx_conf = NULL;
405 			/*
406 			 * We removed the newly added channels so we don't lack
407 			 * resources. So the only reason that this would fail
408 			 * is a FW error which we ignore. Therefore, this
409 			 * should never fail.
410 			 */
411 			WARN_ON(ieee80211_nan_use_chanctx(sdata, chan, true));
412 		} else {
413 			struct ieee80211_chanctx_conf *conf = chan->chanctx_conf;
414 
415 			/* FIXME: detect no-op? */
416 			/* Channel was not removed but may have been updated */
417 			ieee80211_recalc_smps_chanctx(sdata->local,
418 						     container_of(conf,
419 								  struct ieee80211_chanctx,
420 								  conf));
421 		}
422 	}
423 
424 	memcpy(sched_cfg->schedule, backup_sched.schedule,
425 	       sizeof(backup_sched.schedule));
426 	memcpy(sched_cfg->avail_blob, backup_sched.avail_blob,
427 	       sizeof(backup_sched.avail_blob));
428 	sched_cfg->avail_blob_len = backup_sched.avail_blob_len;
429 	sched_cfg->deferred = false;
430 	bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
431 
432 	drv_vif_cfg_changed(sdata->local, sdata, BSS_CHANGED_NAN_LOCAL_SCHED);
433 	ieee80211_nan_update_all_ndi_carriers(sdata->local);
434 	return ret;
435 }
436 
437 void ieee80211_nan_sched_update_done(struct ieee80211_vif *vif)
438 {
439 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
440 	struct ieee80211_nan_sched_cfg *sched_cfg = &vif->cfg.nan_sched;
441 	unsigned int i;
442 
443 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
444 
445 	if (WARN_ON(!sched_cfg->deferred))
446 		return;
447 
448 	ieee80211_nan_update_all_ndi_carriers(sdata->local);
449 
450 	/*
451 	 * Clear the deferred flag before removing channels. Removing channels
452 	 * will trigger another schedule update to the driver, and there is no
453 	 * need for this update to be deferred since removed channels are not
454 	 * part of the schedule anymore, so no need to notify peers about
455 	 * removing them.
456 	 */
457 	sched_cfg->deferred = false;
458 
459 	for (i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) {
460 		struct ieee80211_nan_channel *chan = &sched_cfg->channels[i];
461 		struct ieee80211_chanctx_conf *conf = chan->chanctx_conf;
462 
463 		if (!chan->chanreq.oper.chan)
464 			continue;
465 
466 		if (test_bit(i, sdata->u.nan.removed_channels))
467 			ieee80211_nan_remove_channel(sdata, chan);
468 		else if (conf)
469 			/*
470 			 * We might have called this already for some channels,
471 			 * but this knows to handle a no-op.
472 			 */
473 			ieee80211_recalc_smps_chanctx(sdata->local,
474 						      container_of(conf,
475 								   struct ieee80211_chanctx,
476 								   conf));
477 	}
478 
479 	bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
480 	cfg80211_nan_sched_update_done(ieee80211_vif_to_wdev(vif), true,
481 				       GFP_KERNEL);
482 }
483 EXPORT_SYMBOL(ieee80211_nan_sched_update_done);
484 
485 void ieee80211_nan_free_peer_sched(struct ieee80211_nan_peer_sched *sched)
486 {
487 	if (!sched)
488 		return;
489 
490 	kfree(sched->init_ulw);
491 	kfree(sched);
492 }
493 
494 static int
495 ieee80211_nan_init_peer_channel(struct ieee80211_sub_if_data *sdata,
496 				const struct sta_info *sta,
497 				const struct cfg80211_nan_channel *cfg_chan,
498 				struct ieee80211_nan_channel *new_chan)
499 {
500 	struct ieee80211_nan_sched_cfg *sched_cfg = &sdata->vif.cfg.nan_sched;
501 
502 	/* Find compatible local channel */
503 	for (int j = 0; j < ARRAY_SIZE(sched_cfg->channels); j++) {
504 		struct ieee80211_nan_channel *local_chan =
505 			&sched_cfg->channels[j];
506 		const struct cfg80211_chan_def *compat;
507 
508 		if (!local_chan->chanreq.oper.chan)
509 			continue;
510 
511 		compat = cfg80211_chandef_compatible(&local_chan->chanreq.oper,
512 						     &cfg_chan->chandef);
513 		if (!compat)
514 			continue;
515 
516 		/* compat is the wider chandef, and we want the narrower one */
517 		new_chan->chanreq.oper = compat == &local_chan->chanreq.oper ?
518 					 cfg_chan->chandef : local_chan->chanreq.oper;
519 		new_chan->needed_rx_chains = min(local_chan->needed_rx_chains,
520 						 cfg_chan->rx_nss);
521 		new_chan->chanctx_conf = local_chan->chanctx_conf;
522 
523 		break;
524 	}
525 
526 	/*
527 	 * nl80211 already validated that each peer channel is compatible
528 	 * with at least one local channel, so this should never happen.
529 	 */
530 	if (WARN_ON(!new_chan->chanreq.oper.chan))
531 		return -EINVAL;
532 
533 	memcpy(new_chan->channel_entry, cfg_chan->channel_entry,
534 	       sizeof(new_chan->channel_entry));
535 
536 	return 0;
537 }
538 
539 static void
540 ieee80211_nan_init_peer_map(struct ieee80211_nan_peer_sched *peer_sched,
541 			    const struct cfg80211_nan_peer_map *cfg_map,
542 			    struct ieee80211_nan_peer_map *new_map)
543 {
544 	new_map->map_id = cfg_map->map_id;
545 
546 	if (new_map->map_id == CFG80211_NAN_INVALID_MAP_ID)
547 		return;
548 
549 	/* Set up the slots array */
550 	for (int slot = 0; slot < ARRAY_SIZE(new_map->slots); slot++) {
551 		u8 chan_idx = cfg_map->schedule[slot];
552 
553 		if (chan_idx < peer_sched->n_channels)
554 			new_map->slots[slot] = &peer_sched->channels[chan_idx];
555 	}
556 }
557 
558 /*
559  * Check if the local schedule and a peer schedule have at least one common
560  * slot - a slot where both schedules are active on compatible channels.
561  */
562 static bool
563 ieee80211_nan_has_common_slots(struct ieee80211_sub_if_data *sdata,
564 			       struct ieee80211_nan_peer_sched *peer_sched)
565 {
566 	for (int slot = 0; slot < CFG80211_NAN_SCHED_NUM_TIME_SLOTS; slot++) {
567 		struct ieee80211_nan_channel *local_chan =
568 			sdata->vif.cfg.nan_sched.schedule[slot];
569 
570 		if (!local_chan || !local_chan->chanctx_conf)
571 			continue;
572 
573 		/* Check all peer maps for this slot */
574 		for (int m = 0; m < CFG80211_NAN_MAX_PEER_MAPS; m++) {
575 			struct ieee80211_nan_peer_map *map = &peer_sched->maps[m];
576 			struct ieee80211_nan_channel *peer_chan;
577 
578 			if (map->map_id == CFG80211_NAN_INVALID_MAP_ID)
579 				continue;
580 
581 			peer_chan = map->slots[slot];
582 			if (!peer_chan)
583 				continue;
584 
585 			if (local_chan->chanctx_conf == peer_chan->chanctx_conf)
586 				return true;
587 		}
588 	}
589 
590 	return false;
591 }
592 
593 void ieee80211_nan_update_ndi_carrier(struct ieee80211_sub_if_data *ndi_sdata)
594 {
595 	struct ieee80211_local *local = ndi_sdata->local;
596 	struct ieee80211_sub_if_data *nmi_sdata;
597 	struct sta_info *sta;
598 
599 	lockdep_assert_wiphy(local->hw.wiphy);
600 
601 	if (WARN_ON(ndi_sdata->vif.type != NL80211_IFTYPE_NAN_DATA ||
602 		    !ndi_sdata->dev) || !ieee80211_sdata_running(ndi_sdata))
603 		return;
604 
605 	nmi_sdata = wiphy_dereference(local->hw.wiphy, ndi_sdata->u.nan_data.nmi);
606 	if (WARN_ON(!nmi_sdata))
607 		return;
608 
609 	list_for_each_entry(sta, &local->sta_list, list) {
610 		struct ieee80211_sta *nmi_sta;
611 
612 		if (sta->sdata != ndi_sdata ||
613 		    !test_sta_flag(sta, WLAN_STA_AUTHORIZED))
614 			continue;
615 
616 		nmi_sta = wiphy_dereference(local->hw.wiphy, sta->sta.nmi);
617 		if (WARN_ON(!nmi_sta) || !nmi_sta->nan_sched)
618 			continue;
619 
620 		if (ieee80211_nan_has_common_slots(nmi_sdata, nmi_sta->nan_sched)) {
621 			netif_carrier_on(ndi_sdata->dev);
622 			return;
623 		}
624 	}
625 
626 	netif_carrier_off(ndi_sdata->dev);
627 }
628 
629 static void
630 ieee80211_nan_update_peer_ndis_carrier(struct ieee80211_local *local,
631 				       struct sta_info *nmi_sta)
632 {
633 	struct sta_info *sta;
634 
635 	lockdep_assert_wiphy(local->hw.wiphy);
636 
637 	list_for_each_entry(sta, &local->sta_list, list) {
638 		if (rcu_access_pointer(sta->sta.nmi) == &nmi_sta->sta)
639 			ieee80211_nan_update_ndi_carrier(sta->sdata);
640 	}
641 }
642 
643 int ieee80211_nan_set_peer_sched(struct ieee80211_sub_if_data *sdata,
644 				 struct cfg80211_nan_peer_sched *sched)
645 {
646 	struct ieee80211_nan_peer_sched *new_sched, *old_sched, *to_free;
647 	struct sta_info *sta;
648 	int ret;
649 
650 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
651 
652 	if (!sdata->u.nan.started)
653 		return -EINVAL;
654 
655 	sta = sta_info_get(sdata, sched->peer_addr);
656 	if (!sta)
657 		return -ENOENT;
658 
659 	new_sched = kzalloc(struct_size(new_sched, channels, sched->n_channels),
660 			    GFP_KERNEL);
661 	if (!new_sched)
662 		return -ENOMEM;
663 
664 	to_free = new_sched;
665 
666 	new_sched->seq_id = sched->seq_id;
667 	new_sched->committed_dw = sched->committed_dw;
668 	new_sched->max_chan_switch = sched->max_chan_switch;
669 	new_sched->n_channels = sched->n_channels;
670 
671 	if (sched->ulw_size && sched->init_ulw) {
672 		new_sched->init_ulw = kmemdup(sched->init_ulw, sched->ulw_size,
673 					      GFP_KERNEL);
674 		if (!new_sched->init_ulw) {
675 			ret = -ENOMEM;
676 			goto out;
677 		}
678 		new_sched->ulw_size = sched->ulw_size;
679 	}
680 
681 	for (int i = 0; i < sched->n_channels; i++) {
682 		ret = ieee80211_nan_init_peer_channel(sdata, sta,
683 						      &sched->nan_channels[i],
684 						      &new_sched->channels[i]);
685 		if (ret)
686 			goto out;
687 	}
688 
689 	for (int m = 0; m < ARRAY_SIZE(sched->maps); m++)
690 		ieee80211_nan_init_peer_map(new_sched, &sched->maps[m],
691 					    &new_sched->maps[m]);
692 
693 	/* Install the new schedule before calling the driver */
694 	old_sched = sta->sta.nan_sched;
695 	sta->sta.nan_sched = new_sched;
696 
697 	ret = drv_nan_peer_sched_changed(sdata->local, sdata, sta);
698 	if (ret) {
699 		/* Revert to old schedule */
700 		sta->sta.nan_sched = old_sched;
701 		goto out;
702 	}
703 
704 	ieee80211_nan_update_peer_ndis_carrier(sdata->local, sta);
705 
706 	/* Success - free old schedule */
707 	to_free = old_sched;
708 	ret = 0;
709 
710 out:
711 	ieee80211_nan_free_peer_sched(to_free);
712 	return ret;
713 }
714 
715 static void
716 ieee80211_nan_evacuate_channel(struct ieee80211_sub_if_data *sdata,
717 			       struct ieee80211_nan_channel *nan_channel)
718 {
719 	struct ieee80211_chanctx_conf *conf;
720 	struct ieee80211_chanctx *ctx;
721 
722 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
723 
724 	if (WARN_ON(!nan_channel || !nan_channel->chanreq.oper.chan))
725 		return;
726 
727 	conf = nan_channel->chanctx_conf;
728 	if (WARN_ON(!conf))
729 		return;
730 
731 	nan_channel->chanctx_conf = NULL;
732 
733 	/* Update all peer channels that reference this chanctx */
734 	ieee80211_nan_update_peer_channels(sdata, conf);
735 
736 	drv_vif_cfg_changed(sdata->local, sdata, BSS_CHANGED_NAN_LOCAL_SCHED);
737 
738 	cfg80211_nan_channel_evac(&sdata->wdev, &nan_channel->chanreq.oper,
739 				  GFP_KERNEL);
740 
741 	/* Update NDI carrier states */
742 	ieee80211_nan_update_all_ndi_carriers(sdata->local);
743 
744 	/* Clean up the channel context if no longer used */
745 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
746 
747 	if (ieee80211_chanctx_num_assigned(sdata->local, ctx) > 0) {
748 		ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
749 		ieee80211_recalc_smps_chanctx(sdata->local, ctx);
750 		ieee80211_recalc_chanctx_min_def(sdata->local, ctx);
751 	}
752 
753 	if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0)
754 		ieee80211_free_chanctx(sdata->local, ctx, false);
755 }
756 
757 bool ieee80211_nan_try_evacuate(struct ieee80211_hw *hw,
758 				struct ieee80211_chanctx_conf *conf)
759 {
760 	struct ieee80211_sub_if_data *sdata = NULL, *tmp;
761 	struct ieee80211_local *local = hw_to_local(hw);
762 	struct ieee80211_nan_channel *evac_chan = NULL;
763 	struct ieee80211_nan_sched_cfg *sched_cfg;
764 	struct ieee80211_chanctx *ctx = NULL;
765 	int min_slot_count = INT_MAX;
766 	int usable_channels = 0;
767 
768 	lockdep_assert_wiphy(local->hw.wiphy);
769 
770 	if (conf)
771 		ctx = container_of(conf, struct ieee80211_chanctx, conf);
772 
773 	/* Find the NAN interface - there can only be one */
774 	list_for_each_entry(tmp, &local->interfaces, list) {
775 		if (ieee80211_sdata_running(tmp) &&
776 		    tmp->vif.type == NL80211_IFTYPE_NAN) {
777 			sdata = tmp;
778 			break;
779 		}
780 	}
781 
782 	if (!sdata)
783 		return false;
784 
785 	sched_cfg = &sdata->vif.cfg.nan_sched;
786 
787 	/* Find the channel to evacuate and count usable channels */
788 	for (int i = 0; i < IEEE80211_NAN_MAX_CHANNELS; i++) {
789 		struct ieee80211_nan_channel *chan =
790 			&sched_cfg->channels[i];
791 		struct ieee80211_chanctx *chan_ctx;
792 		int slot_count = 0;
793 
794 		if (!chan->chanreq.oper.chan || !chan->chanctx_conf)
795 			continue;
796 
797 		usable_channels++;
798 
799 		chan_ctx = container_of(chan->chanctx_conf,
800 					struct ieee80211_chanctx, conf);
801 
802 		/* If ctx specified, only consider that specific chanctx */
803 		if (ctx) {
804 			if (chan_ctx == ctx)
805 				evac_chan = chan;
806 			continue;
807 		}
808 
809 		/* Can only evacuate channels whose chanctx is NAN-only */
810 		if (ieee80211_chanctx_refcount(local, chan_ctx) > 1)
811 			continue;
812 
813 		/* Count how many time slots use this channel */
814 		for (int s = 0; s < CFG80211_NAN_SCHED_NUM_TIME_SLOTS; s++)
815 			if (sched_cfg->schedule[s] == chan)
816 				slot_count++;
817 
818 		if (slot_count < min_slot_count) {
819 			min_slot_count = slot_count;
820 			evac_chan = chan;
821 		}
822 	}
823 
824 	/* No suitable NAN channel found */
825 	if (!evac_chan)
826 		return false;
827 
828 	/* NAN needs at least one remaining usable channel after evacuation */
829 	if (usable_channels < 2)
830 		return false;
831 
832 	ieee80211_nan_evacuate_channel(sdata, evac_chan);
833 
834 	return true;
835 }
836 EXPORT_SYMBOL(ieee80211_nan_try_evacuate);
837