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