xref: /linux/net/mac80211/nan.c (revision fafb66e5903c2bcfc7b7e259042a8282f18a6faa)
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 __free(kfree) = kmalloc_obj(*backup_sched);
257 	int ret;
258 
259 	if (!backup_sched)
260 		return -ENOMEM;
261 
262 	if (sched->n_channels > IEEE80211_NAN_MAX_CHANNELS)
263 		return -EOPNOTSUPP;
264 
265 	if (sched->nan_avail_blob_len > IEEE80211_NAN_AVAIL_BLOB_MAX_LEN)
266 		return -EINVAL;
267 
268 	/*
269 	 * If a deferred schedule update is pending completion, new updates are
270 	 * not allowed. Only allow to configure an empty schedule so NAN can be
271 	 * stopped in the middle of a deferred update. This is fine because
272 	 * empty schedule means the local NAN device will not be available for
273 	 * peers anymore so there is no need to update peers about a new
274 	 * schedule.
275 	 */
276 	if (WARN_ON(sched_cfg->deferred && sched->n_channels))
277 		return -EBUSY;
278 
279 	bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
280 
281 	memcpy(backup_sched->schedule, sched_cfg->schedule,
282 	       sizeof(backup_sched->schedule));
283 	memcpy(backup_sched->channels, sched_cfg->channels,
284 	       sizeof(backup_sched->channels));
285 	memcpy(backup_sched->avail_blob, sched_cfg->avail_blob,
286 	       sizeof(backup_sched->avail_blob));
287 	backup_sched->avail_blob_len = sched_cfg->avail_blob_len;
288 
289 	memcpy(sched_cfg->avail_blob, sched->nan_avail_blob,
290 	       sched->nan_avail_blob_len);
291 	sched_cfg->avail_blob_len = sched->nan_avail_blob_len;
292 
293 	/*
294 	 * Remove channels that are no longer in the new schedule to free up
295 	 * resources before adding new channels. For deferred schedule, channels
296 	 * will be removed when the schedule is applied.
297 	 * Create a mapping from sched index to sched_cfg channel
298 	 */
299 	for (int i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) {
300 		bool still_needed = false;
301 
302 		if (!sched_cfg->channels[i].chanreq.oper.chan)
303 			continue;
304 
305 		for (int j = 0; j < sched->n_channels; j++) {
306 			if (cfg80211_chandef_identical(&sched_cfg->channels[i].chanreq.oper,
307 						       &sched->nan_channels[j].chandef)) {
308 				sched_idx_to_chan[j] =
309 					&sched_cfg->channels[i];
310 				still_needed = true;
311 				break;
312 			}
313 		}
314 
315 		if (!still_needed) {
316 			__set_bit(i, sdata->u.nan.removed_channels);
317 			if (!sched->deferred)
318 				ieee80211_nan_remove_channel(sdata,
319 							     &sched_cfg->channels[i]);
320 		}
321 	}
322 
323 	for (int i = 0; i < sched->n_channels; i++) {
324 		struct ieee80211_nan_channel *chan = sched_idx_to_chan[i];
325 
326 		if (chan) {
327 			ieee80211_nan_update_channel(sdata->local, chan,
328 						     &sched->nan_channels[i],
329 						     sched->deferred);
330 		} else {
331 			chan = ieee80211_nan_find_free_channel(sched_cfg);
332 			if (WARN_ON(!chan)) {
333 				ret = -EINVAL;
334 				goto err;
335 			}
336 
337 			sched_idx_to_chan[i] = chan;
338 			ieee80211_nan_init_channel(chan,
339 						   &sched->nan_channels[i]);
340 		}
341 
342 		/* Also a pre-existing channel might have been ULWed, so no chanctx */
343 		if (!chan->chanctx_conf) {
344 			ret = ieee80211_nan_use_chanctx(sdata, chan, false);
345 			if (ret) {
346 				memset(chan, 0, sizeof(*chan));
347 				goto err;
348 			}
349 		}
350 	}
351 
352 	for (int s = 0; s < ARRAY_SIZE(sched_cfg->schedule); s++) {
353 		if (sched->schedule[s] < ARRAY_SIZE(sched_idx_to_chan))
354 			sched_cfg->schedule[s] =
355 				sched_idx_to_chan[sched->schedule[s]];
356 		else
357 			sched_cfg->schedule[s] = NULL;
358 	}
359 
360 	sched_cfg->deferred = sched->deferred;
361 
362 	drv_vif_cfg_changed(sdata->local, sdata, BSS_CHANGED_NAN_LOCAL_SCHED);
363 
364 	/*
365 	 * For deferred update, don't update NDI carriers yet as the new
366 	 * schedule is not yet applied so common slots don't change. The NDI
367 	 * carrier will be updated once the driver notifies the new schedule is
368 	 * applied.
369 	 */
370 	if (sched_cfg->deferred)
371 		return 0;
372 
373 	ieee80211_nan_update_all_ndi_carriers(sdata->local);
374 	bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
375 
376 	return 0;
377 err:
378 	/* Remove newly added channels */
379 	for (int i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) {
380 		struct cfg80211_chan_def *chan_def =
381 			&sched_cfg->channels[i].chanreq.oper;
382 
383 		if (!chan_def->chan)
384 			continue;
385 
386 		if (!cfg80211_chandef_identical(&backup_sched->channels[i].chanreq.oper,
387 						chan_def))
388 			ieee80211_nan_remove_channel(sdata,
389 						     &sched_cfg->channels[i]);
390 	}
391 
392 	/* Re-add all backed up channels */
393 	for (int i = 0; i < ARRAY_SIZE(backup_sched->channels); i++) {
394 		struct ieee80211_nan_channel *chan = &sched_cfg->channels[i];
395 
396 		*chan = backup_sched->channels[i];
397 
398 		/*
399 		 * For deferred update, no channels were removed and the channel
400 		 * context didn't change, so nothing else to do.
401 		 */
402 		if (!chan->chanctx_conf || sched->deferred)
403 			continue;
404 
405 		if (test_bit(i, sdata->u.nan.removed_channels)) {
406 			/* Clear the stale chanctx pointer */
407 			chan->chanctx_conf = NULL;
408 			/*
409 			 * We removed the newly added channels so we don't lack
410 			 * resources. So the only reason that this would fail
411 			 * is a FW error which we ignore. Therefore, this
412 			 * should never fail.
413 			 */
414 			WARN_ON(ieee80211_nan_use_chanctx(sdata, chan, true));
415 		} else {
416 			struct ieee80211_chanctx_conf *conf = chan->chanctx_conf;
417 
418 			/* FIXME: detect no-op? */
419 			/* Channel was not removed but may have been updated */
420 			ieee80211_recalc_smps_chanctx(sdata->local,
421 						     container_of(conf,
422 								  struct ieee80211_chanctx,
423 								  conf));
424 		}
425 	}
426 
427 	memcpy(sched_cfg->schedule, backup_sched->schedule,
428 	       sizeof(backup_sched->schedule));
429 	memcpy(sched_cfg->avail_blob, backup_sched->avail_blob,
430 	       sizeof(backup_sched->avail_blob));
431 	sched_cfg->avail_blob_len = backup_sched->avail_blob_len;
432 	sched_cfg->deferred = false;
433 	bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
434 
435 	drv_vif_cfg_changed(sdata->local, sdata, BSS_CHANGED_NAN_LOCAL_SCHED);
436 	ieee80211_nan_update_all_ndi_carriers(sdata->local);
437 	return ret;
438 }
439 
440 void ieee80211_nan_sched_update_done(struct ieee80211_vif *vif)
441 {
442 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
443 	struct ieee80211_nan_sched_cfg *sched_cfg = &vif->cfg.nan_sched;
444 	unsigned int i;
445 
446 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
447 
448 	if (WARN_ON(!sched_cfg->deferred))
449 		return;
450 
451 	ieee80211_nan_update_all_ndi_carriers(sdata->local);
452 
453 	/*
454 	 * Clear the deferred flag before removing channels. Removing channels
455 	 * will trigger another schedule update to the driver, and there is no
456 	 * need for this update to be deferred since removed channels are not
457 	 * part of the schedule anymore, so no need to notify peers about
458 	 * removing them.
459 	 */
460 	sched_cfg->deferred = false;
461 
462 	for (i = 0; i < ARRAY_SIZE(sched_cfg->channels); i++) {
463 		struct ieee80211_nan_channel *chan = &sched_cfg->channels[i];
464 		struct ieee80211_chanctx_conf *conf = chan->chanctx_conf;
465 
466 		if (!chan->chanreq.oper.chan)
467 			continue;
468 
469 		if (test_bit(i, sdata->u.nan.removed_channels))
470 			ieee80211_nan_remove_channel(sdata, chan);
471 		else if (conf)
472 			/*
473 			 * We might have called this already for some channels,
474 			 * but this knows to handle a no-op.
475 			 */
476 			ieee80211_recalc_smps_chanctx(sdata->local,
477 						      container_of(conf,
478 								   struct ieee80211_chanctx,
479 								   conf));
480 	}
481 
482 	bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
483 	cfg80211_nan_sched_update_done(ieee80211_vif_to_wdev(vif), true,
484 				       GFP_KERNEL);
485 }
486 EXPORT_SYMBOL(ieee80211_nan_sched_update_done);
487 
488 void ieee80211_nan_free_peer_sched(struct ieee80211_nan_peer_sched *sched)
489 {
490 	if (!sched)
491 		return;
492 
493 	kfree(sched->init_ulw);
494 	kfree(sched);
495 }
496 
497 static int
498 ieee80211_nan_init_peer_channel(struct ieee80211_sub_if_data *sdata,
499 				const struct sta_info *sta,
500 				const struct cfg80211_nan_channel *cfg_chan,
501 				struct ieee80211_nan_channel *new_chan)
502 {
503 	struct ieee80211_nan_sched_cfg *sched_cfg = &sdata->vif.cfg.nan_sched;
504 
505 	/* Find compatible local channel */
506 	for (int j = 0; j < ARRAY_SIZE(sched_cfg->channels); j++) {
507 		struct ieee80211_nan_channel *local_chan =
508 			&sched_cfg->channels[j];
509 		const struct cfg80211_chan_def *compat;
510 
511 		if (!local_chan->chanreq.oper.chan)
512 			continue;
513 
514 		compat = cfg80211_chandef_compatible(&local_chan->chanreq.oper,
515 						     &cfg_chan->chandef);
516 		if (!compat)
517 			continue;
518 
519 		/* compat is the wider chandef, and we want the narrower one */
520 		new_chan->chanreq.oper = compat == &local_chan->chanreq.oper ?
521 					 cfg_chan->chandef : local_chan->chanreq.oper;
522 		new_chan->needed_rx_chains = min(local_chan->needed_rx_chains,
523 						 cfg_chan->rx_nss);
524 		new_chan->chanctx_conf = local_chan->chanctx_conf;
525 
526 		break;
527 	}
528 
529 	/*
530 	 * nl80211 already validated that each peer channel is compatible
531 	 * with at least one local channel, so this should never happen.
532 	 */
533 	if (WARN_ON(!new_chan->chanreq.oper.chan))
534 		return -EINVAL;
535 
536 	memcpy(new_chan->channel_entry, cfg_chan->channel_entry,
537 	       sizeof(new_chan->channel_entry));
538 
539 	return 0;
540 }
541 
542 static void
543 ieee80211_nan_init_peer_map(struct ieee80211_nan_peer_sched *peer_sched,
544 			    const struct cfg80211_nan_peer_map *cfg_map,
545 			    struct ieee80211_nan_peer_map *new_map)
546 {
547 	new_map->map_id = cfg_map->map_id;
548 
549 	if (new_map->map_id == CFG80211_NAN_INVALID_MAP_ID)
550 		return;
551 
552 	/* Set up the slots array */
553 	for (int slot = 0; slot < ARRAY_SIZE(new_map->slots); slot++) {
554 		u8 chan_idx = cfg_map->schedule[slot];
555 
556 		if (chan_idx < peer_sched->n_channels)
557 			new_map->slots[slot] = &peer_sched->channels[chan_idx];
558 	}
559 }
560 
561 /*
562  * Check if the local schedule and a peer schedule have at least one common
563  * slot - a slot where both schedules are active on compatible channels.
564  */
565 static bool
566 ieee80211_nan_has_common_slots(struct ieee80211_sub_if_data *sdata,
567 			       struct ieee80211_nan_peer_sched *peer_sched)
568 {
569 	for (int slot = 0; slot < CFG80211_NAN_SCHED_NUM_TIME_SLOTS; slot++) {
570 		struct ieee80211_nan_channel *local_chan =
571 			sdata->vif.cfg.nan_sched.schedule[slot];
572 
573 		if (!local_chan || !local_chan->chanctx_conf)
574 			continue;
575 
576 		/* Check all peer maps for this slot */
577 		for (int m = 0; m < CFG80211_NAN_MAX_PEER_MAPS; m++) {
578 			struct ieee80211_nan_peer_map *map = &peer_sched->maps[m];
579 			struct ieee80211_nan_channel *peer_chan;
580 
581 			if (map->map_id == CFG80211_NAN_INVALID_MAP_ID)
582 				continue;
583 
584 			peer_chan = map->slots[slot];
585 			if (!peer_chan)
586 				continue;
587 
588 			if (local_chan->chanctx_conf == peer_chan->chanctx_conf)
589 				return true;
590 		}
591 	}
592 
593 	return false;
594 }
595 
596 void ieee80211_nan_update_ndi_carrier(struct ieee80211_sub_if_data *ndi_sdata)
597 {
598 	struct ieee80211_local *local = ndi_sdata->local;
599 	struct ieee80211_sub_if_data *nmi_sdata;
600 	struct sta_info *sta;
601 
602 	lockdep_assert_wiphy(local->hw.wiphy);
603 
604 	if (WARN_ON(ndi_sdata->vif.type != NL80211_IFTYPE_NAN_DATA ||
605 		    !ndi_sdata->dev) || !ieee80211_sdata_running(ndi_sdata))
606 		return;
607 
608 	nmi_sdata = wiphy_dereference(local->hw.wiphy, ndi_sdata->u.nan_data.nmi);
609 	if (WARN_ON(!nmi_sdata))
610 		return;
611 
612 	list_for_each_entry(sta, &local->sta_list, list) {
613 		struct ieee80211_sta *nmi_sta;
614 
615 		if (sta->sdata != ndi_sdata ||
616 		    !test_sta_flag(sta, WLAN_STA_AUTHORIZED))
617 			continue;
618 
619 		nmi_sta = wiphy_dereference(local->hw.wiphy, sta->sta.nmi);
620 		if (WARN_ON(!nmi_sta) || !nmi_sta->nan_sched)
621 			continue;
622 
623 		if (ieee80211_nan_has_common_slots(nmi_sdata, nmi_sta->nan_sched)) {
624 			netif_carrier_on(ndi_sdata->dev);
625 			return;
626 		}
627 	}
628 
629 	netif_carrier_off(ndi_sdata->dev);
630 }
631 
632 static void
633 ieee80211_nan_update_peer_ndis_carrier(struct ieee80211_local *local,
634 				       struct sta_info *nmi_sta)
635 {
636 	struct sta_info *sta;
637 
638 	lockdep_assert_wiphy(local->hw.wiphy);
639 
640 	list_for_each_entry(sta, &local->sta_list, list) {
641 		if (rcu_access_pointer(sta->sta.nmi) == &nmi_sta->sta)
642 			ieee80211_nan_update_ndi_carrier(sta->sdata);
643 	}
644 }
645 
646 int ieee80211_nan_set_peer_sched(struct ieee80211_sub_if_data *sdata,
647 				 struct cfg80211_nan_peer_sched *sched)
648 {
649 	struct ieee80211_nan_peer_sched *new_sched, *old_sched, *to_free;
650 	struct sta_info *sta;
651 	int ret;
652 
653 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
654 
655 	if (!sdata->u.nan.started)
656 		return -EINVAL;
657 
658 	sta = sta_info_get(sdata, sched->peer_addr);
659 	if (!sta)
660 		return -ENOENT;
661 
662 	new_sched = kzalloc(struct_size(new_sched, channels, sched->n_channels),
663 			    GFP_KERNEL);
664 	if (!new_sched)
665 		return -ENOMEM;
666 
667 	to_free = new_sched;
668 
669 	new_sched->seq_id = sched->seq_id;
670 	new_sched->committed_dw = sched->committed_dw;
671 	new_sched->max_chan_switch = sched->max_chan_switch;
672 	new_sched->n_channels = sched->n_channels;
673 
674 	if (sched->ulw_size && sched->init_ulw) {
675 		new_sched->init_ulw = kmemdup(sched->init_ulw, sched->ulw_size,
676 					      GFP_KERNEL);
677 		if (!new_sched->init_ulw) {
678 			ret = -ENOMEM;
679 			goto out;
680 		}
681 		new_sched->ulw_size = sched->ulw_size;
682 	}
683 
684 	for (int i = 0; i < sched->n_channels; i++) {
685 		ret = ieee80211_nan_init_peer_channel(sdata, sta,
686 						      &sched->nan_channels[i],
687 						      &new_sched->channels[i]);
688 		if (ret)
689 			goto out;
690 	}
691 
692 	for (int m = 0; m < ARRAY_SIZE(sched->maps); m++)
693 		ieee80211_nan_init_peer_map(new_sched, &sched->maps[m],
694 					    &new_sched->maps[m]);
695 
696 	/* Install the new schedule before calling the driver */
697 	old_sched = sta->sta.nan_sched;
698 	sta->sta.nan_sched = new_sched;
699 
700 	ret = drv_nan_peer_sched_changed(sdata->local, sdata, sta);
701 	if (ret) {
702 		/* Revert to old schedule */
703 		sta->sta.nan_sched = old_sched;
704 		goto out;
705 	}
706 
707 	ieee80211_nan_update_peer_ndis_carrier(sdata->local, sta);
708 
709 	/* Success - free old schedule */
710 	to_free = old_sched;
711 	ret = 0;
712 
713 out:
714 	ieee80211_nan_free_peer_sched(to_free);
715 	return ret;
716 }
717 
718 void
719 ieee80211_nan_evacuate_channel(struct ieee80211_sub_if_data *sdata,
720 			       struct ieee80211_nan_channel *nan_channel)
721 {
722 	struct ieee80211_chanctx_conf *conf;
723 	struct ieee80211_chanctx *ctx;
724 
725 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
726 
727 	if (WARN_ON(!nan_channel || !nan_channel->chanreq.oper.chan))
728 		return;
729 
730 	conf = nan_channel->chanctx_conf;
731 	if (WARN_ON(!conf))
732 		return;
733 
734 	nan_channel->chanctx_conf = NULL;
735 
736 	/* Update all peer channels that reference this chanctx */
737 	ieee80211_nan_update_peer_channels(sdata, conf);
738 
739 	drv_vif_cfg_changed(sdata->local, sdata, BSS_CHANGED_NAN_LOCAL_SCHED);
740 
741 	cfg80211_nan_channel_evac(&sdata->wdev, &nan_channel->chanreq.oper,
742 				  GFP_KERNEL);
743 
744 	/* Update NDI carrier states */
745 	ieee80211_nan_update_all_ndi_carriers(sdata->local);
746 
747 	/* Clean up the channel context if no longer used */
748 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
749 
750 	if (ieee80211_chanctx_num_assigned(sdata->local, ctx) > 0) {
751 		ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
752 		ieee80211_recalc_smps_chanctx(sdata->local, ctx);
753 		ieee80211_recalc_chanctx_min_def(sdata->local, ctx);
754 	}
755 
756 	if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0)
757 		ieee80211_free_chanctx(sdata->local, ctx, false);
758 }
759 
760 struct ieee80211_nan_channel *
761 ieee80211_nan_find_evac_chan(struct ieee80211_local *local,
762 			     struct ieee80211_sub_if_data *sdata,
763 			     struct ieee80211_chanctx *ctx)
764 {
765 	struct ieee80211_nan_sched_cfg *sched_cfg;
766 	struct ieee80211_nan_channel *evac_chan = NULL;
767 	int min_slot_count = INT_MAX;
768 	int usable_channels = 0;
769 
770 	lockdep_assert_wiphy(local->hw.wiphy);
771 
772 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_NAN))
773 		return NULL;
774 
775 	sched_cfg = &sdata->vif.cfg.nan_sched;
776 
777 	/* Find the channel to evacuate and count usable channels */
778 	for (int i = 0; i < IEEE80211_NAN_MAX_CHANNELS; i++) {
779 		struct ieee80211_nan_channel *chan =
780 			&sched_cfg->channels[i];
781 		struct ieee80211_chanctx *chan_ctx;
782 		int slot_count = 0;
783 
784 		if (!chan->chanreq.oper.chan || !chan->chanctx_conf)
785 			continue;
786 
787 		usable_channels++;
788 
789 		chan_ctx = container_of(chan->chanctx_conf,
790 					struct ieee80211_chanctx, conf);
791 
792 		/* If ctx specified, only consider that specific chanctx */
793 		if (ctx) {
794 			if (chan_ctx == ctx)
795 				evac_chan = chan;
796 			continue;
797 		}
798 
799 		/* Can only evacuate channels whose chanctx is NAN-only */
800 		if (ieee80211_chanctx_refcount(local, chan_ctx) > 1)
801 			continue;
802 
803 		/* Count how many time slots use this channel */
804 		for (int s = 0; s < CFG80211_NAN_SCHED_NUM_TIME_SLOTS; s++)
805 			if (sched_cfg->schedule[s] == chan)
806 				slot_count++;
807 
808 		if (slot_count < min_slot_count) {
809 			min_slot_count = slot_count;
810 			evac_chan = chan;
811 		}
812 	}
813 
814 	/* No suitable NAN channel found */
815 	if (!evac_chan)
816 		return NULL;
817 
818 	/* NAN needs at least one remaining usable channel after evacuation */
819 	if (usable_channels < 2)
820 		return NULL;
821 
822 	return evac_chan;
823 }
824 
825 bool ieee80211_nan_try_evacuate(struct ieee80211_hw *hw,
826 				struct ieee80211_chanctx_conf *conf)
827 {
828 	struct ieee80211_local *local = hw_to_local(hw);
829 	struct ieee80211_sub_if_data *sdata =
830 		ieee80211_find_nan_sdata(local);
831 	struct ieee80211_nan_channel *evac_chan;
832 	struct ieee80211_chanctx *ctx = NULL;
833 
834 	lockdep_assert_wiphy(local->hw.wiphy);
835 
836 	if (!sdata)
837 		return false;
838 
839 	if (conf)
840 		ctx = container_of(conf, struct ieee80211_chanctx, conf);
841 
842 	evac_chan = ieee80211_nan_find_evac_chan(local, sdata, ctx);
843 	if (!evac_chan)
844 		return false;
845 
846 	ieee80211_nan_evacuate_channel(sdata, evac_chan);
847 
848 	return true;
849 }
850 EXPORT_SYMBOL(ieee80211_nan_try_evacuate);
851