1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2015 Intel Deutschland GmbH 4 * Copyright (C) 2022-2024 Intel Corporation 5 */ 6 #include <net/mac80211.h> 7 #include "ieee80211_i.h" 8 #include "trace.h" 9 #include "driver-ops.h" 10 #include "debugfs_sta.h" 11 #include "debugfs_netdev.h" 12 13 int drv_start(struct ieee80211_local *local) 14 { 15 int ret; 16 17 might_sleep(); 18 lockdep_assert_wiphy(local->hw.wiphy); 19 20 if (WARN_ON(local->started)) 21 return -EALREADY; 22 23 trace_drv_start(local); 24 local->started = true; 25 /* allow rx frames */ 26 smp_mb(); 27 ret = local->ops->start(&local->hw); 28 trace_drv_return_int(local, ret); 29 30 if (ret) 31 local->started = false; 32 33 return ret; 34 } 35 36 void drv_stop(struct ieee80211_local *local, bool suspend) 37 { 38 might_sleep(); 39 lockdep_assert_wiphy(local->hw.wiphy); 40 41 if (WARN_ON(!local->started)) 42 return; 43 44 trace_drv_stop(local, suspend); 45 local->ops->stop(&local->hw, suspend); 46 trace_drv_return_void(local); 47 48 /* sync away all work on the tasklet before clearing started */ 49 tasklet_disable(&local->tasklet); 50 tasklet_enable(&local->tasklet); 51 52 barrier(); 53 54 local->started = false; 55 } 56 57 int drv_add_interface(struct ieee80211_local *local, 58 struct ieee80211_sub_if_data *sdata) 59 { 60 int ret; 61 62 might_sleep(); 63 lockdep_assert_wiphy(local->hw.wiphy); 64 65 if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || 66 (sdata->vif.type == NL80211_IFTYPE_MONITOR && 67 !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) && 68 !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) && 69 !(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)))) 70 return -EINVAL; 71 72 trace_drv_add_interface(local, sdata); 73 ret = local->ops->add_interface(&local->hw, &sdata->vif); 74 trace_drv_return_int(local, ret); 75 76 if (ret) 77 return ret; 78 79 if (!(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) { 80 sdata->flags |= IEEE80211_SDATA_IN_DRIVER; 81 82 drv_vif_add_debugfs(local, sdata); 83 /* initially vif is not MLD */ 84 ieee80211_link_debugfs_drv_add(&sdata->deflink); 85 } 86 87 return 0; 88 } 89 90 int drv_change_interface(struct ieee80211_local *local, 91 struct ieee80211_sub_if_data *sdata, 92 enum nl80211_iftype type, bool p2p) 93 { 94 int ret; 95 96 might_sleep(); 97 lockdep_assert_wiphy(local->hw.wiphy); 98 99 if (!check_sdata_in_driver(sdata)) 100 return -EIO; 101 102 trace_drv_change_interface(local, sdata, type, p2p); 103 ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); 104 trace_drv_return_int(local, ret); 105 return ret; 106 } 107 108 void drv_remove_interface(struct ieee80211_local *local, 109 struct ieee80211_sub_if_data *sdata) 110 { 111 might_sleep(); 112 lockdep_assert_wiphy(local->hw.wiphy); 113 114 if (!check_sdata_in_driver(sdata)) 115 return; 116 117 sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER; 118 119 /* Remove driver debugfs entries */ 120 ieee80211_debugfs_recreate_netdev(sdata, sdata->vif.valid_links); 121 122 trace_drv_remove_interface(local, sdata); 123 local->ops->remove_interface(&local->hw, &sdata->vif); 124 trace_drv_return_void(local); 125 } 126 127 __must_check 128 int drv_sta_state(struct ieee80211_local *local, 129 struct ieee80211_sub_if_data *sdata, 130 struct sta_info *sta, 131 enum ieee80211_sta_state old_state, 132 enum ieee80211_sta_state new_state) 133 { 134 int ret = 0; 135 136 might_sleep(); 137 lockdep_assert_wiphy(local->hw.wiphy); 138 139 sdata = get_bss_sdata(sdata); 140 if (!check_sdata_in_driver(sdata)) 141 return -EIO; 142 143 trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); 144 if (local->ops->sta_state) { 145 ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta, 146 old_state, new_state); 147 } else if (old_state == IEEE80211_STA_AUTH && 148 new_state == IEEE80211_STA_ASSOC) { 149 ret = drv_sta_add(local, sdata, &sta->sta); 150 if (ret == 0) { 151 sta->uploaded = true; 152 if (rcu_access_pointer(sta->sta.rates)) 153 drv_sta_rate_tbl_update(local, sdata, &sta->sta); 154 } 155 } else if (old_state == IEEE80211_STA_ASSOC && 156 new_state == IEEE80211_STA_AUTH) { 157 drv_sta_remove(local, sdata, &sta->sta); 158 } 159 trace_drv_return_int(local, ret); 160 return ret; 161 } 162 163 __must_check 164 int drv_sta_set_txpwr(struct ieee80211_local *local, 165 struct ieee80211_sub_if_data *sdata, 166 struct sta_info *sta) 167 { 168 int ret = -EOPNOTSUPP; 169 170 might_sleep(); 171 lockdep_assert_wiphy(local->hw.wiphy); 172 173 sdata = get_bss_sdata(sdata); 174 if (!check_sdata_in_driver(sdata)) 175 return -EIO; 176 177 trace_drv_sta_set_txpwr(local, sdata, &sta->sta); 178 if (local->ops->sta_set_txpwr) 179 ret = local->ops->sta_set_txpwr(&local->hw, &sdata->vif, 180 &sta->sta); 181 trace_drv_return_int(local, ret); 182 return ret; 183 } 184 185 void drv_link_sta_rc_update(struct ieee80211_local *local, 186 struct ieee80211_sub_if_data *sdata, 187 struct ieee80211_link_sta *link_sta, 188 u32 changed) 189 { 190 sdata = get_bss_sdata(sdata); 191 if (!check_sdata_in_driver(sdata)) 192 return; 193 194 WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && 195 (sdata->vif.type != NL80211_IFTYPE_ADHOC && 196 sdata->vif.type != NL80211_IFTYPE_MESH_POINT)); 197 198 trace_drv_link_sta_rc_update(local, sdata, link_sta, changed); 199 if (local->ops->link_sta_rc_update) 200 local->ops->link_sta_rc_update(&local->hw, &sdata->vif, 201 link_sta, changed); 202 203 trace_drv_return_void(local); 204 } 205 206 int drv_conf_tx(struct ieee80211_local *local, 207 struct ieee80211_link_data *link, u16 ac, 208 const struct ieee80211_tx_queue_params *params) 209 { 210 struct ieee80211_sub_if_data *sdata = link->sdata; 211 int ret = -EOPNOTSUPP; 212 213 might_sleep(); 214 lockdep_assert_wiphy(local->hw.wiphy); 215 216 if (!check_sdata_in_driver(sdata)) 217 return -EIO; 218 219 if (!ieee80211_vif_link_active(&sdata->vif, link->link_id)) 220 return 0; 221 222 if (params->cw_min == 0 || params->cw_min > params->cw_max) { 223 /* 224 * If we can't configure hardware anyway, don't warn. We may 225 * never have initialized the CW parameters. 226 */ 227 WARN_ONCE(local->ops->conf_tx, 228 "%s: invalid CW_min/CW_max: %d/%d\n", 229 sdata->name, params->cw_min, params->cw_max); 230 return -EINVAL; 231 } 232 233 trace_drv_conf_tx(local, sdata, link->link_id, ac, params); 234 if (local->ops->conf_tx) 235 ret = local->ops->conf_tx(&local->hw, &sdata->vif, 236 link->link_id, ac, params); 237 trace_drv_return_int(local, ret); 238 return ret; 239 } 240 241 u64 drv_get_tsf(struct ieee80211_local *local, 242 struct ieee80211_sub_if_data *sdata) 243 { 244 u64 ret = -1ULL; 245 246 might_sleep(); 247 lockdep_assert_wiphy(local->hw.wiphy); 248 249 if (!check_sdata_in_driver(sdata)) 250 return ret; 251 252 trace_drv_get_tsf(local, sdata); 253 if (local->ops->get_tsf) 254 ret = local->ops->get_tsf(&local->hw, &sdata->vif); 255 trace_drv_return_u64(local, ret); 256 return ret; 257 } 258 259 void drv_set_tsf(struct ieee80211_local *local, 260 struct ieee80211_sub_if_data *sdata, 261 u64 tsf) 262 { 263 might_sleep(); 264 lockdep_assert_wiphy(local->hw.wiphy); 265 266 if (!check_sdata_in_driver(sdata)) 267 return; 268 269 trace_drv_set_tsf(local, sdata, tsf); 270 if (local->ops->set_tsf) 271 local->ops->set_tsf(&local->hw, &sdata->vif, tsf); 272 trace_drv_return_void(local); 273 } 274 275 void drv_offset_tsf(struct ieee80211_local *local, 276 struct ieee80211_sub_if_data *sdata, 277 s64 offset) 278 { 279 might_sleep(); 280 lockdep_assert_wiphy(local->hw.wiphy); 281 282 if (!check_sdata_in_driver(sdata)) 283 return; 284 285 trace_drv_offset_tsf(local, sdata, offset); 286 if (local->ops->offset_tsf) 287 local->ops->offset_tsf(&local->hw, &sdata->vif, offset); 288 trace_drv_return_void(local); 289 } 290 291 void drv_reset_tsf(struct ieee80211_local *local, 292 struct ieee80211_sub_if_data *sdata) 293 { 294 might_sleep(); 295 lockdep_assert_wiphy(local->hw.wiphy); 296 297 if (!check_sdata_in_driver(sdata)) 298 return; 299 300 trace_drv_reset_tsf(local, sdata); 301 if (local->ops->reset_tsf) 302 local->ops->reset_tsf(&local->hw, &sdata->vif); 303 trace_drv_return_void(local); 304 } 305 306 int drv_assign_vif_chanctx(struct ieee80211_local *local, 307 struct ieee80211_sub_if_data *sdata, 308 struct ieee80211_bss_conf *link_conf, 309 struct ieee80211_chanctx *ctx) 310 { 311 int ret = 0; 312 313 might_sleep(); 314 lockdep_assert_wiphy(local->hw.wiphy); 315 316 /* 317 * We should perhaps push emulate chanctx down and only 318 * make it call ->config() when the chanctx is actually 319 * assigned here (and unassigned below), but that's yet 320 * another change to all drivers to add assign/unassign 321 * emulation callbacks. Maybe later. 322 */ 323 if (sdata->vif.type == NL80211_IFTYPE_MONITOR && 324 local->emulate_chanctx && 325 !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) 326 return 0; 327 328 if (!check_sdata_in_driver(sdata)) 329 return -EIO; 330 331 if (!ieee80211_vif_link_active(&sdata->vif, link_conf->link_id)) 332 return 0; 333 334 trace_drv_assign_vif_chanctx(local, sdata, link_conf, ctx); 335 if (local->ops->assign_vif_chanctx) { 336 WARN_ON_ONCE(!ctx->driver_present); 337 ret = local->ops->assign_vif_chanctx(&local->hw, 338 &sdata->vif, 339 link_conf, 340 &ctx->conf); 341 } 342 trace_drv_return_int(local, ret); 343 344 return ret; 345 } 346 347 void drv_unassign_vif_chanctx(struct ieee80211_local *local, 348 struct ieee80211_sub_if_data *sdata, 349 struct ieee80211_bss_conf *link_conf, 350 struct ieee80211_chanctx *ctx) 351 { 352 might_sleep(); 353 lockdep_assert_wiphy(local->hw.wiphy); 354 355 if (sdata->vif.type == NL80211_IFTYPE_MONITOR && 356 local->emulate_chanctx && 357 !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) 358 return; 359 360 if (!check_sdata_in_driver(sdata)) 361 return; 362 363 if (!ieee80211_vif_link_active(&sdata->vif, link_conf->link_id)) 364 return; 365 366 trace_drv_unassign_vif_chanctx(local, sdata, link_conf, ctx); 367 if (local->ops->unassign_vif_chanctx) { 368 WARN_ON_ONCE(!ctx->driver_present); 369 local->ops->unassign_vif_chanctx(&local->hw, 370 &sdata->vif, 371 link_conf, 372 &ctx->conf); 373 } 374 trace_drv_return_void(local); 375 } 376 377 int drv_switch_vif_chanctx(struct ieee80211_local *local, 378 struct ieee80211_vif_chanctx_switch *vifs, 379 int n_vifs, enum ieee80211_chanctx_switch_mode mode) 380 { 381 int ret = 0; 382 int i; 383 384 might_sleep(); 385 lockdep_assert_wiphy(local->hw.wiphy); 386 387 if (!local->ops->switch_vif_chanctx) 388 return -EOPNOTSUPP; 389 390 for (i = 0; i < n_vifs; i++) { 391 struct ieee80211_chanctx *new_ctx = 392 container_of(vifs[i].new_ctx, 393 struct ieee80211_chanctx, 394 conf); 395 struct ieee80211_chanctx *old_ctx = 396 container_of(vifs[i].old_ctx, 397 struct ieee80211_chanctx, 398 conf); 399 400 WARN_ON_ONCE(!old_ctx->driver_present); 401 WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS && 402 new_ctx->driver_present) || 403 (mode == CHANCTX_SWMODE_REASSIGN_VIF && 404 !new_ctx->driver_present)); 405 } 406 407 trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode); 408 ret = local->ops->switch_vif_chanctx(&local->hw, 409 vifs, n_vifs, mode); 410 trace_drv_return_int(local, ret); 411 412 if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) { 413 for (i = 0; i < n_vifs; i++) { 414 struct ieee80211_chanctx *new_ctx = 415 container_of(vifs[i].new_ctx, 416 struct ieee80211_chanctx, 417 conf); 418 struct ieee80211_chanctx *old_ctx = 419 container_of(vifs[i].old_ctx, 420 struct ieee80211_chanctx, 421 conf); 422 423 new_ctx->driver_present = true; 424 old_ctx->driver_present = false; 425 } 426 } 427 428 return ret; 429 } 430 431 int drv_ampdu_action(struct ieee80211_local *local, 432 struct ieee80211_sub_if_data *sdata, 433 struct ieee80211_ampdu_params *params) 434 { 435 int ret = -EOPNOTSUPP; 436 437 might_sleep(); 438 lockdep_assert_wiphy(local->hw.wiphy); 439 440 sdata = get_bss_sdata(sdata); 441 if (!check_sdata_in_driver(sdata)) 442 return -EIO; 443 444 trace_drv_ampdu_action(local, sdata, params); 445 446 if (local->ops->ampdu_action) 447 ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params); 448 449 trace_drv_return_int(local, ret); 450 451 return ret; 452 } 453 454 void drv_link_info_changed(struct ieee80211_local *local, 455 struct ieee80211_sub_if_data *sdata, 456 struct ieee80211_bss_conf *info, 457 int link_id, u64 changed) 458 { 459 might_sleep(); 460 lockdep_assert_wiphy(local->hw.wiphy); 461 462 if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON | 463 BSS_CHANGED_BEACON_ENABLED) && 464 sdata->vif.type != NL80211_IFTYPE_AP && 465 sdata->vif.type != NL80211_IFTYPE_ADHOC && 466 sdata->vif.type != NL80211_IFTYPE_MESH_POINT && 467 sdata->vif.type != NL80211_IFTYPE_OCB)) 468 return; 469 470 if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || 471 sdata->vif.type == NL80211_IFTYPE_NAN || 472 (sdata->vif.type == NL80211_IFTYPE_MONITOR && 473 !sdata->vif.bss_conf.mu_mimo_owner && 474 !(changed & BSS_CHANGED_TXPOWER)))) 475 return; 476 477 if (!check_sdata_in_driver(sdata)) 478 return; 479 480 if (!ieee80211_vif_link_active(&sdata->vif, link_id)) 481 return; 482 483 trace_drv_link_info_changed(local, sdata, info, changed); 484 if (local->ops->link_info_changed) 485 local->ops->link_info_changed(&local->hw, &sdata->vif, 486 info, changed); 487 else if (local->ops->bss_info_changed) 488 local->ops->bss_info_changed(&local->hw, &sdata->vif, 489 info, changed); 490 trace_drv_return_void(local); 491 } 492 493 int drv_set_key(struct ieee80211_local *local, 494 enum set_key_cmd cmd, 495 struct ieee80211_sub_if_data *sdata, 496 struct ieee80211_sta *sta, 497 struct ieee80211_key_conf *key) 498 { 499 int ret; 500 501 might_sleep(); 502 lockdep_assert_wiphy(local->hw.wiphy); 503 504 sdata = get_bss_sdata(sdata); 505 if (!check_sdata_in_driver(sdata)) 506 return -EIO; 507 508 if (WARN_ON(key->link_id >= 0 && sdata->vif.active_links && 509 !(sdata->vif.active_links & BIT(key->link_id)))) 510 return -ENOLINK; 511 512 trace_drv_set_key(local, cmd, sdata, sta, key); 513 ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); 514 trace_drv_return_int(local, ret); 515 return ret; 516 } 517 518 int drv_change_vif_links(struct ieee80211_local *local, 519 struct ieee80211_sub_if_data *sdata, 520 u16 old_links, u16 new_links, 521 struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) 522 { 523 struct ieee80211_link_data *link; 524 unsigned long links_to_add; 525 unsigned long links_to_rem; 526 unsigned int link_id; 527 int ret = -EOPNOTSUPP; 528 529 might_sleep(); 530 lockdep_assert_wiphy(local->hw.wiphy); 531 532 if (!check_sdata_in_driver(sdata)) 533 return -EIO; 534 535 if (old_links == new_links) 536 return 0; 537 538 links_to_add = ~old_links & new_links; 539 links_to_rem = old_links & ~new_links; 540 541 for_each_set_bit(link_id, &links_to_rem, IEEE80211_MLD_MAX_NUM_LINKS) { 542 link = rcu_access_pointer(sdata->link[link_id]); 543 544 ieee80211_link_debugfs_drv_remove(link); 545 } 546 547 trace_drv_change_vif_links(local, sdata, old_links, new_links); 548 if (local->ops->change_vif_links) 549 ret = local->ops->change_vif_links(&local->hw, &sdata->vif, 550 old_links, new_links, old); 551 trace_drv_return_int(local, ret); 552 553 if (ret) 554 return ret; 555 556 if (!local->in_reconfig && !local->resuming) { 557 for_each_set_bit(link_id, &links_to_add, 558 IEEE80211_MLD_MAX_NUM_LINKS) { 559 link = rcu_access_pointer(sdata->link[link_id]); 560 561 ieee80211_link_debugfs_drv_add(link); 562 } 563 } 564 565 return 0; 566 } 567 568 int drv_change_sta_links(struct ieee80211_local *local, 569 struct ieee80211_sub_if_data *sdata, 570 struct ieee80211_sta *sta, 571 u16 old_links, u16 new_links) 572 { 573 struct sta_info *info = container_of(sta, struct sta_info, sta); 574 struct link_sta_info *link_sta; 575 unsigned long links_to_add; 576 unsigned long links_to_rem; 577 unsigned int link_id; 578 int ret = -EOPNOTSUPP; 579 580 might_sleep(); 581 lockdep_assert_wiphy(local->hw.wiphy); 582 583 if (!check_sdata_in_driver(sdata)) 584 return -EIO; 585 586 old_links &= sdata->vif.active_links; 587 new_links &= sdata->vif.active_links; 588 589 if (old_links == new_links) 590 return 0; 591 592 links_to_add = ~old_links & new_links; 593 links_to_rem = old_links & ~new_links; 594 595 for_each_set_bit(link_id, &links_to_rem, IEEE80211_MLD_MAX_NUM_LINKS) { 596 link_sta = rcu_dereference_protected(info->link[link_id], 597 lockdep_is_held(&local->hw.wiphy->mtx)); 598 599 ieee80211_link_sta_debugfs_drv_remove(link_sta); 600 } 601 602 trace_drv_change_sta_links(local, sdata, sta, old_links, new_links); 603 if (local->ops->change_sta_links) 604 ret = local->ops->change_sta_links(&local->hw, &sdata->vif, sta, 605 old_links, new_links); 606 trace_drv_return_int(local, ret); 607 608 if (ret) 609 return ret; 610 611 /* during reconfig don't add it to debugfs again */ 612 if (local->in_reconfig || local->resuming) 613 return 0; 614 615 for_each_set_bit(link_id, &links_to_add, IEEE80211_MLD_MAX_NUM_LINKS) { 616 link_sta = rcu_dereference_protected(info->link[link_id], 617 lockdep_is_held(&local->hw.wiphy->mtx)); 618 ieee80211_link_sta_debugfs_drv_add(link_sta); 619 } 620 621 return 0; 622 } 623