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