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