1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: wlan_hdd_mlo.c 20 * 21 * WLAN Host Device Driver file for 802.11be (Extremely High Throughput) 22 * support. 23 * 24 */ 25 #include "wlan_hdd_main.h" 26 #include "wlan_hdd_mlo.h" 27 #include "osif_vdev_sync.h" 28 #include "wlan_osif_features.h" 29 #include "wlan_dp_ucfg_api.h" 30 #include "wlan_psoc_mlme_ucfg_api.h" 31 #include "wlan_osif_request_manager.h" 32 #include "wlan_hdd_object_manager.h" 33 #include <wlan_osif_priv.h> 34 35 /*max time in ms, caller may wait for link state request get serviced */ 36 #define WLAN_WAIT_TIME_LINK_STATE 800 37 38 #if defined(CFG80211_11BE_BASIC) 39 #ifndef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV 40 #ifdef CFG80211_IFTYPE_MLO_LINK_SUPPORT 41 42 static 43 void wlan_hdd_register_ml_link(struct hdd_adapter *sta_adapter, 44 struct hdd_adapter *link_adapter) 45 { 46 int ret; 47 48 link_adapter->wdev.iftype = NL80211_IFTYPE_MLO_LINK; 49 mutex_lock(&sta_adapter->wdev.mtx); 50 ret = cfg80211_register_sta_mlo_link(&sta_adapter->wdev, 51 &link_adapter->wdev); 52 mutex_unlock(&sta_adapter->wdev.mtx); 53 54 if (ret) { 55 hdd_err("Failed to register ml link wdev %d", ret); 56 return; 57 } 58 } 59 60 static 61 void wlan_hdd_unregister_ml_link(struct hdd_adapter *link_adapter, 62 bool rtnl_held) 63 { 64 if (rtnl_held) 65 rtnl_unlock(); 66 67 cfg80211_unregister_wdev(&link_adapter->wdev); 68 69 if (rtnl_held) 70 rtnl_lock(); 71 } 72 #else 73 static 74 void wlan_hdd_register_ml_link(struct hdd_adapter *sta_adapter, 75 struct hdd_adapter *link_adapter) 76 { 77 } 78 79 static 80 void wlan_hdd_unregister_ml_link(struct hdd_adapter *link_adapter, 81 bool rtnl_held) 82 { 83 } 84 #endif 85 86 void hdd_register_wdev(struct hdd_adapter *sta_adapter, 87 struct hdd_adapter *link_adapter, 88 struct hdd_adapter_create_param *adapter_params) 89 { 90 int i; 91 92 hdd_enter_dev(sta_adapter->dev); 93 /* Set the relation between adapters*/ 94 wlan_hdd_register_ml_link(sta_adapter, link_adapter); 95 sta_adapter->mlo_adapter_info.is_ml_adapter = true; 96 sta_adapter->mlo_adapter_info.is_link_adapter = false; 97 link_adapter->mlo_adapter_info.is_link_adapter = true; 98 link_adapter->mlo_adapter_info.is_ml_adapter = false; 99 link_adapter->mlo_adapter_info.ml_adapter = sta_adapter; 100 link_adapter->mlo_adapter_info.associate_with_ml_adapter = 101 adapter_params->associate_with_ml_adapter; 102 qdf_set_bit(WDEV_ONLY_REGISTERED, &link_adapter->event_flags); 103 104 for (i = 0; i < WLAN_MAX_MLD; i++) { 105 if (sta_adapter->mlo_adapter_info.link_adapter[i]) 106 continue; 107 sta_adapter->mlo_adapter_info.link_adapter[i] = link_adapter; 108 break; 109 } 110 111 qdf_mem_copy(link_adapter->mld_addr.bytes, sta_adapter->mld_addr.bytes, 112 QDF_MAC_ADDR_SIZE); 113 hdd_exit(); 114 } 115 116 static 117 void hdd_mlo_close_adapter(struct hdd_adapter *link_adapter, bool rtnl_held) 118 { 119 struct osif_vdev_sync *vdev_sync; 120 121 vdev_sync = osif_vdev_sync_unregister(link_adapter->dev); 122 if (vdev_sync) 123 osif_vdev_sync_wait_for_ops(vdev_sync); 124 125 hdd_check_for_net_dev_ref_leak(link_adapter); 126 policy_mgr_clear_concurrency_mode(link_adapter->hdd_ctx->psoc, 127 link_adapter->device_mode); 128 link_adapter->wdev.netdev = NULL; 129 130 wlan_hdd_unregister_ml_link(link_adapter, rtnl_held); 131 free_netdev(link_adapter->dev); 132 133 if (vdev_sync) 134 osif_vdev_sync_destroy(vdev_sync); 135 } 136 137 QDF_STATUS hdd_wlan_unregister_mlo_interfaces(struct hdd_adapter *adapter, 138 bool rtnl_held) 139 { 140 int i; 141 struct hdd_mlo_adapter_info *mlo_adapter_info; 142 struct hdd_adapter *link_adapter; 143 144 mlo_adapter_info = &adapter->mlo_adapter_info; 145 146 if (mlo_adapter_info->is_link_adapter) { 147 ucfg_dp_destroy_intf(adapter->hdd_ctx->psoc, 148 &adapter->mac_addr); 149 hdd_remove_front_adapter(adapter->hdd_ctx, &adapter); 150 return QDF_STATUS_E_AGAIN; 151 } 152 153 for (i = 0; i < WLAN_MAX_MLD; i++) { 154 link_adapter = mlo_adapter_info->link_adapter[i]; 155 if (!link_adapter) 156 continue; 157 hdd_cleanup_conn_info(link_adapter->deflink); 158 ucfg_dp_destroy_intf(link_adapter->hdd_ctx->psoc, 159 &link_adapter->mac_addr); 160 hdd_remove_adapter(link_adapter->hdd_ctx, link_adapter); 161 hdd_mlo_close_adapter(link_adapter, rtnl_held); 162 } 163 164 return QDF_STATUS_SUCCESS; 165 } 166 167 void hdd_wlan_register_mlo_interfaces(struct hdd_context *hdd_ctx) 168 { 169 int i = 0; 170 QDF_STATUS status; 171 struct hdd_adapter *ml_adapter; 172 struct wlan_hdd_link_info *link_info; 173 struct hdd_adapter_create_param params = {0}; 174 struct qdf_mac_addr link_addr[WLAN_MAX_ML_BSS_LINKS] = {0}; 175 176 ml_adapter = hdd_get_ml_adapter(hdd_ctx); 177 if (!ml_adapter) 178 return; 179 180 status = hdd_derive_link_address_from_mld(&ml_adapter->mld_addr, 181 &link_addr[0], 182 WLAN_MAX_ML_BSS_LINKS); 183 if (QDF_IS_STATUS_ERROR(status)) 184 return; 185 186 /* if target supports MLO create a new dev */ 187 params.only_wdev_register = true; 188 params.associate_with_ml_adapter = true; 189 status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE, "null", 190 link_addr[0].bytes, ¶ms); 191 if (QDF_IS_STATUS_ERROR(status)) 192 hdd_err("Failed to register link adapter:%d", status); 193 194 qdf_mem_zero(¶ms, sizeof(params)); 195 params.only_wdev_register = true; 196 params.associate_with_ml_adapter = false; 197 /* if target supports MLO create a new dev */ 198 status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE, "null", 199 link_addr[1].bytes, ¶ms); 200 if (QDF_IS_STATUS_ERROR(status)) { 201 hdd_err("Failed to register link adapter:%d", status); 202 } else { 203 hdd_adapter_for_each_link_info(ml_adapter, link_info) { 204 qdf_copy_macaddr(&link_info->link_addr, 205 &link_addr[i++]); 206 } 207 } 208 } 209 210 void 211 hdd_adapter_set_sl_ml_adapter(struct hdd_adapter *adapter) 212 { 213 adapter->mlo_adapter_info.is_single_link_ml = true; 214 } 215 216 void 217 hdd_adapter_clear_sl_ml_adapter(struct hdd_adapter *adapter) 218 { 219 adapter->mlo_adapter_info.is_single_link_ml = false; 220 } 221 222 struct hdd_adapter *hdd_get_ml_adapter(struct hdd_context *hdd_ctx) 223 { 224 struct hdd_adapter *adapter, *next_adapter = NULL; 225 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_VDEV; 226 227 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, 228 dbgid) { 229 if (hdd_adapter_is_ml_adapter(adapter)) { 230 hdd_adapter_dev_put_debug(adapter, dbgid); 231 if (next_adapter) 232 hdd_adapter_dev_put_debug(next_adapter, 233 dbgid); 234 return adapter; 235 } 236 hdd_adapter_dev_put_debug(adapter, dbgid); 237 } 238 239 return NULL; 240 } 241 #endif 242 243 #ifndef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV 244 void hdd_adapter_set_ml_adapter(struct hdd_adapter *adapter) 245 { 246 adapter->mlo_adapter_info.is_ml_adapter = true; 247 qdf_copy_macaddr(&adapter->mld_addr, &adapter->mac_addr); 248 } 249 #else 250 void hdd_adapter_set_ml_adapter(struct hdd_adapter *adapter) 251 { 252 adapter->mlo_adapter_info.is_ml_adapter = true; 253 } 254 255 static struct mlo_osif_ext_ops mlo_osif_ops = { 256 .mlo_mgr_osif_update_bss_info = hdd_cm_save_connected_links_info, 257 .mlo_mgr_osif_update_mac_addr = hdd_link_switch_vdev_mac_addr_update, 258 .mlo_mgr_osif_link_switch_notification = 259 hdd_adapter_link_switch_notification, 260 }; 261 262 QDF_STATUS hdd_mlo_mgr_register_osif_ops(void) 263 { 264 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 265 266 return wlan_mlo_mgr_register_osif_ext_ops(mlo_mgr_ctx, &mlo_osif_ops); 267 } 268 269 QDF_STATUS hdd_mlo_mgr_unregister_osif_ops(void) 270 { 271 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 272 273 return wlan_mlo_mgr_unregister_osif_ext_ops(mlo_mgr_ctx); 274 } 275 276 QDF_STATUS hdd_adapter_link_switch_notification(struct wlan_objmgr_vdev *vdev, 277 uint8_t non_trans_vdev_id) 278 { 279 int errno; 280 bool found = false; 281 struct hdd_adapter *adapter; 282 struct vdev_osif_priv *osif_priv; 283 struct wlan_hdd_link_info *link_info, *iter_link_info; 284 struct osif_vdev_sync *vdev_sync; 285 286 osif_priv = wlan_vdev_get_ospriv(vdev); 287 if (!osif_priv) { 288 hdd_err("Invalid osif priv"); 289 return QDF_STATUS_E_INVAL; 290 } 291 292 link_info = osif_priv->legacy_osif_priv; 293 adapter = link_info->adapter; 294 295 if (link_info->vdev_id != adapter->deflink->vdev_id) { 296 hdd_err("Default VDEV %d not equal", adapter->deflink->vdev_id); 297 QDF_ASSERT(0); 298 return QDF_STATUS_E_INVAL; 299 } 300 301 errno = osif_vdev_sync_trans_start_wait(adapter->dev, &vdev_sync); 302 if (errno) 303 return QDF_STATUS_E_FAILURE; 304 305 osif_vdev_sync_wait_for_ops(vdev_sync); 306 hdd_adapter_for_each_link_info(adapter, iter_link_info) { 307 if (non_trans_vdev_id == iter_link_info->vdev_id) { 308 adapter->deflink = iter_link_info; 309 found = true; 310 break; 311 } 312 } 313 osif_vdev_sync_trans_stop(vdev_sync); 314 315 if (!found) 316 return QDF_STATUS_E_FAILURE; 317 318 return QDF_STATUS_SUCCESS; 319 } 320 #endif 321 322 void hdd_mlo_t2lm_register_callback(struct wlan_objmgr_vdev *vdev) 323 { 324 if (!vdev || !vdev->mlo_dev_ctx) 325 return; 326 327 wlan_register_t2lm_link_update_notify_handler( 328 hdd_mlo_dev_t2lm_notify_link_update, 329 vdev->mlo_dev_ctx); 330 } 331 332 void hdd_mlo_t2lm_unregister_callback(struct wlan_objmgr_vdev *vdev) 333 { 334 if (!vdev || !vdev->mlo_dev_ctx) 335 return; 336 337 wlan_unregister_t2lm_link_update_notify_handler(vdev->mlo_dev_ctx, 0); 338 } 339 340 QDF_STATUS hdd_derive_link_address_from_mld(struct qdf_mac_addr *mld_addr, 341 struct qdf_mac_addr *link_addr_list, 342 uint8_t max_idx) 343 { 344 uint8_t last_byte, temp_byte, idx; 345 struct qdf_mac_addr new_addr; 346 struct qdf_mac_addr *link_addr; 347 348 if (!mld_addr || !link_addr_list || !max_idx || 349 max_idx > WLAN_MAX_ML_BSS_LINKS || qdf_is_macaddr_zero(mld_addr)) { 350 hdd_err("Invalid values"); 351 return QDF_STATUS_E_INVAL; 352 } 353 354 qdf_copy_macaddr(&new_addr, mld_addr); 355 /* Set locally administered bit */ 356 new_addr.bytes[0] |= 0x02; 357 358 link_addr = link_addr_list; 359 last_byte = mld_addr->bytes[5]; 360 hdd_debug("MLD addr: " QDF_MAC_ADDR_FMT, 361 QDF_MAC_ADDR_REF(mld_addr->bytes)); 362 363 for (idx = 0; idx < max_idx; idx++) { 364 temp_byte = ((last_byte >> 4 & INTF_MACADDR_MASK) + idx) & 365 INTF_MACADDR_MASK; 366 new_addr.bytes[5] = last_byte + temp_byte; 367 new_addr.bytes[5] ^= (1 << 7); 368 369 qdf_copy_macaddr(link_addr, &new_addr); 370 link_addr++; 371 hdd_debug("Derived link addr: " QDF_MAC_ADDR_FMT ", idx: %d", 372 QDF_MAC_ADDR_REF(new_addr.bytes), idx); 373 } 374 375 return QDF_STATUS_SUCCESS; 376 } 377 378 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE 379 #ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV 380 static void hdd_adapter_restore_link_vdev_map(struct hdd_adapter *adapter) 381 { 382 int i; 383 unsigned long link_flags; 384 uint8_t vdev_id, cur_link_idx, temp_link_idx; 385 struct vdev_osif_priv *osif_priv; 386 struct wlan_objmgr_vdev *vdev; 387 struct wlan_hdd_link_info *temp_link_info, *link_info; 388 389 hdd_adapter_for_each_link_info(adapter, link_info) { 390 cur_link_idx = hdd_adapter_get_index_of_link_info(link_info); 391 /* If the current index matches the current pos in mapping 392 * then the link info is in same position 393 */ 394 if (adapter->curr_link_info_map[cur_link_idx] == cur_link_idx) 395 continue; 396 397 /* Find the index where current link info is moved to perform 398 * VDEV info swap. 399 */ 400 for (i = cur_link_idx + 1; i < WLAN_MAX_ML_BSS_LINKS; i++) { 401 if (adapter->curr_link_info_map[i] == cur_link_idx) { 402 temp_link_idx = i; 403 break; 404 } 405 } 406 407 if (i == WLAN_MAX_ML_BSS_LINKS) 408 continue; 409 410 temp_link_info = &adapter->link_info[temp_link_idx]; 411 412 /* Move VDEV info from current link info */ 413 qdf_spin_lock_bh(&temp_link_info->vdev_lock); 414 vdev = temp_link_info->vdev; 415 vdev_id = temp_link_info->vdev_id; 416 temp_link_info->vdev = link_info->vdev; 417 temp_link_info->vdev_id = link_info->vdev_id; 418 qdf_spin_unlock_bh(&temp_link_info->vdev_lock); 419 420 /* Fill current link info's actual VDEV info */ 421 qdf_spin_lock_bh(&link_info->vdev_lock); 422 link_info->vdev = vdev; 423 link_info->vdev_id = vdev_id; 424 qdf_spin_unlock_bh(&link_info->vdev_lock); 425 426 /* Swap link flags */ 427 link_flags = temp_link_info->link_flags; 428 temp_link_info->link_flags = link_info->link_flags; 429 link_info->link_flags = link_flags; 430 431 /* Update VDEV-OSIF priv pointer to new link info. */ 432 if (!vdev) 433 continue; 434 435 osif_priv = wlan_vdev_get_ospriv(vdev); 436 if (!osif_priv) 437 continue; 438 osif_priv->legacy_osif_priv = link_info; 439 440 /* Update the mapping, current link info's mapping will be 441 * set to be proper. 442 */ 443 adapter->curr_link_info_map[temp_link_idx] = 444 adapter->curr_link_info_map[cur_link_idx]; 445 adapter->curr_link_info_map[cur_link_idx] = cur_link_idx; 446 } 447 hdd_adapter_disable_all_links(adapter); 448 } 449 450 int hdd_update_vdev_mac_address(struct hdd_adapter *adapter, 451 struct qdf_mac_addr mac_addr) 452 { 453 int idx, i, ret = 0; 454 bool eht_capab, update_self_peer; 455 QDF_STATUS status; 456 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 457 struct wlan_hdd_link_info *link_info; 458 uint8_t *addr_list[WLAN_MAX_ML_BSS_LINKS + 1] = {0}; 459 struct qdf_mac_addr link_addrs[WLAN_MAX_ML_BSS_LINKS] = {0}; 460 461 /* This API is only called with is ml adapter set for STA mode adapter. 462 * For SAP mode, hdd_hostapd_set_mac_address() is the entry point for 463 * MAC address update. 464 */ 465 ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab); 466 if (!(eht_capab && hdd_adapter_is_ml_adapter(adapter))) { 467 struct qdf_mac_addr mld_addr = QDF_MAC_ADDR_ZERO_INIT; 468 469 ret = hdd_dynamic_mac_address_set(adapter->deflink, mac_addr, 470 mld_addr, true); 471 return ret; 472 } 473 474 status = hdd_derive_link_address_from_mld(&mac_addr, &link_addrs[0], 475 WLAN_MAX_ML_BSS_LINKS); 476 477 if (QDF_IS_STATUS_ERROR(status)) 478 return qdf_status_to_os_return(status); 479 480 hdd_adapter_restore_link_vdev_map(adapter); 481 482 i = 0; 483 hdd_adapter_for_each_active_link_info(adapter, link_info) { 484 idx = hdd_adapter_get_index_of_link_info(link_info); 485 addr_list[i++] = &link_addrs[idx].bytes[0]; 486 } 487 488 status = sme_check_for_duplicate_session(hdd_ctx->mac_handle, 489 &addr_list[0]); 490 if (QDF_IS_STATUS_ERROR(status)) 491 return qdf_status_to_os_return(status); 492 493 i = 0; 494 hdd_adapter_for_each_link_info(adapter, link_info) 495 qdf_copy_macaddr(&link_info->link_addr, &link_addrs[i++]); 496 497 hdd_adapter_for_each_active_link_info(adapter, link_info) { 498 idx = hdd_adapter_get_index_of_link_info(link_info); 499 update_self_peer = 500 (link_info == adapter->deflink) ? true : false; 501 ret = hdd_dynamic_mac_address_set(link_info, link_addrs[idx], 502 mac_addr, update_self_peer); 503 if (ret) 504 return ret; 505 506 qdf_copy_macaddr(&link_info->link_addr, &link_addrs[idx]); 507 } 508 509 hdd_adapter_update_mlo_mgr_mac_addr(adapter); 510 return ret; 511 } 512 #else 513 int hdd_update_vdev_mac_address(struct hdd_adapter *adapter, 514 struct qdf_mac_addr mac_addr) 515 { 516 int i, ret = 0; 517 QDF_STATUS status; 518 bool eht_capab, update_self_peer; 519 struct hdd_adapter *link_adapter; 520 struct hdd_mlo_adapter_info *mlo_adapter_info; 521 struct hdd_context *hdd_ctx = adapter->hdd_ctx; 522 uint8_t *addr_list[WLAN_MAX_MLD + 1] = {0}; 523 struct qdf_mac_addr link_addrs[WLAN_MAX_ML_BSS_LINKS] = {0}; 524 525 /* This API is only called with is ml adapter set for STA mode adapter. 526 * For SAP mode, hdd_hostapd_set_mac_address() is the entry point for 527 * MAC address update. 528 */ 529 ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab); 530 if (!(eht_capab && hdd_adapter_is_ml_adapter(adapter))) { 531 struct qdf_mac_addr mld_addr = QDF_MAC_ADDR_ZERO_INIT; 532 533 ret = hdd_dynamic_mac_address_set(adapter->deflink, mac_addr, 534 mld_addr, true); 535 return ret; 536 } 537 538 status = hdd_derive_link_address_from_mld(&mac_addr, &link_addrs[0], 539 WLAN_MAX_ML_BSS_LINKS); 540 541 if (QDF_IS_STATUS_ERROR(status)) 542 return qdf_status_to_os_return(status); 543 544 for (i = 0; i < WLAN_MAX_MLD; i++) 545 addr_list[i] = &link_addrs[i].bytes[0]; 546 547 status = sme_check_for_duplicate_session(hdd_ctx->mac_handle, 548 &addr_list[0]); 549 if (QDF_IS_STATUS_ERROR(status)) 550 return qdf_status_to_os_return(status); 551 552 mlo_adapter_info = &adapter->mlo_adapter_info; 553 for (i = 0; i < WLAN_MAX_MLD; i++) { 554 link_adapter = mlo_adapter_info->link_adapter[i]; 555 if (!link_adapter) 556 continue; 557 558 if (hdd_adapter_is_associated_with_ml_adapter(link_adapter)) 559 update_self_peer = true; 560 else 561 update_self_peer = false; 562 563 ret = hdd_dynamic_mac_address_set(link_adapter->deflink, 564 link_addrs[i], mac_addr, 565 update_self_peer); 566 if (ret) 567 return ret; 568 569 /* Update DP intf and new link address in link adapter 570 */ 571 ucfg_dp_update_intf_mac(hdd_ctx->psoc, &link_adapter->mac_addr, 572 &link_addrs[i], 573 link_adapter->deflink->vdev); 574 qdf_copy_macaddr(&link_adapter->mac_addr, &link_addrs[i]); 575 qdf_copy_macaddr(&adapter->link_info[i].link_addr, 576 &link_addrs[i]); 577 } 578 579 qdf_copy_macaddr(&adapter->link_info[i].link_addr, &link_addrs[i]); 580 hdd_adapter_update_mlo_mgr_mac_addr(adapter); 581 582 return ret; 583 } 584 #endif 585 #endif /* WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE */ 586 587 const struct nla_policy 588 ml_link_state_config_policy [QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_MAX + 1] = { 589 [QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID] = {.type = NLA_U8}, 590 [QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE] = {.type = NLA_U32}, 591 }; 592 593 const struct nla_policy 594 ml_link_state_request_policy[QCA_WLAN_VENDOR_ATTR_LINK_STATE_MAX + 1] = { 595 [QCA_WLAN_VENDOR_ATTR_LINK_STATE_OP_TYPE] = {.type = NLA_U32}, 596 [QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE] = {.type = NLA_U32}, 597 [QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG] = {.type = NLA_NESTED}, 598 [QCA_WLAN_VENDOR_ATTR_LINK_STATE_MIXED_MODE_ACTIVE_NUM_LINKS] = { 599 .type = NLA_U8}, 600 }; 601 602 static int 603 __wlan_hdd_cfg80211_process_ml_link_state(struct wiphy *wiphy, 604 struct wireless_dev *wdev, 605 const void *data, int data_len) 606 { 607 int ret = 0; 608 struct net_device *dev = wdev->netdev; 609 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 610 struct wlan_objmgr_vdev *vdev; 611 struct hdd_context *hdd_ctx = NULL; 612 613 hdd_enter_dev(wdev->netdev); 614 615 if (hdd_validate_adapter(adapter)) 616 return -EINVAL; 617 618 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 619 if (!hdd_ctx) 620 return -EINVAL; 621 622 if (adapter->device_mode != QDF_STA_MODE) 623 return -EINVAL; 624 625 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID); 626 627 if (!vdev) 628 return -EINVAL; 629 630 ret = wlan_handle_mlo_link_state_operation(wiphy, vdev, hdd_ctx, 631 data, data_len); 632 633 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID); 634 635 return ret; 636 } 637 638 int wlan_hdd_cfg80211_process_ml_link_state(struct wiphy *wiphy, 639 struct wireless_dev *wdev, 640 const void *data, int data_len) 641 { 642 int errno; 643 struct osif_vdev_sync *vdev_sync; 644 645 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); 646 if (errno) 647 return errno; 648 649 errno = __wlan_hdd_cfg80211_process_ml_link_state(wiphy, wdev, data, 650 data_len); 651 652 osif_vdev_sync_op_stop(vdev_sync); 653 654 return errno; 655 } 656 657 static inline void ml_link_state_resp_cb(struct ml_link_state_info_event *ev, 658 void *cookie) 659 { 660 struct ml_link_state_info_event *priv; 661 struct osif_request *request; 662 663 request = osif_request_get(cookie); 664 665 if (!request) { 666 hdd_err("Obsolete request"); 667 return; 668 } 669 670 priv = osif_request_priv(request); 671 672 qdf_mem_copy(priv, ev, sizeof(*priv)); 673 osif_request_complete(request); 674 osif_request_put(request); 675 } 676 677 static uint32_t 678 hdd_get_ml_link_state_response_len(const struct ml_link_state_info_event *event) 679 { 680 uint32_t len = 0; 681 uint32_t info_len = 0; 682 683 len = NLMSG_HDRLEN; 684 /* QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE */ 685 len += NLA_HDRLEN + sizeof(u32); 686 687 /* QCA_WLAN_VENDOR_ATTR_LINK_STATE_OPERATION_MODE */ 688 len += NLA_HDRLEN + sizeof(u32); 689 690 /* nest */ 691 info_len = NLA_HDRLEN; 692 /* QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID */ 693 info_len += NLA_HDRLEN + sizeof(u8); 694 /* QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE */ 695 info_len += NLA_HDRLEN + sizeof(u32); 696 697 /* QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG */ 698 len += NLA_HDRLEN + (info_len * event->num_mlo_vdev_link_info); 699 700 return len; 701 } 702 703 static int 704 hdd_ml_generate_link_state_resp_nlmsg(struct sk_buff *skb, 705 struct ml_link_state_info_event *params, 706 uint32_t num_link_info) 707 { 708 struct nlattr *nla_config_attr, *nla_config_params; 709 uint32_t i = 0, attr; 710 int errno; 711 uint32_t value; 712 713 attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE; 714 715 /* Default control mode is only supported */ 716 value = QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_DEFAULT; 717 errno = nla_put_u32(skb, attr, value); 718 if (errno) 719 return errno; 720 721 attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_OPERATION_MODE; 722 723 /* Default link state operation mode is only supported */ 724 value = QCA_WLAN_VENDOR_LINK_STATE_OPERATION_MODE_DEFAULT; 725 errno = nla_put_u32(skb, attr, value); 726 if (errno) 727 return errno; 728 729 attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG; 730 nla_config_attr = nla_nest_start(skb, attr); 731 732 if (!nla_config_attr) 733 return -EINVAL; 734 735 for (i = 0; i < num_link_info; i++) { 736 nla_config_params = nla_nest_start(skb, attr); 737 if (!nla_config_params) 738 return -EINVAL; 739 740 attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID; 741 value = params->link_info[i].link_id; 742 errno = nla_put_u8(skb, attr, value); 743 if (errno) 744 return errno; 745 746 attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE; 747 value = params->link_info[i].link_status; 748 errno = nla_put_u32(skb, attr, value); 749 750 if (errno) 751 return errno; 752 753 nla_nest_end(skb, nla_config_params); 754 } 755 756 nla_nest_end(skb, nla_config_attr); 757 758 return 0; 759 } 760 761 static QDF_STATUS wlan_hdd_link_state_request(struct wiphy *wiphy, 762 struct wlan_objmgr_vdev *vdev) 763 { 764 int errno; 765 int skb_len; 766 struct sk_buff *reply_skb = NULL; 767 QDF_STATUS status = QDF_STATUS_E_INVAL; 768 void *cookie; 769 struct ml_link_state_info_event *link_state_event = NULL; 770 struct osif_request *request; 771 struct ml_link_state_cmd_info info = {0}; 772 int num_info = 0; 773 static const struct osif_request_params params = { 774 .priv_size = sizeof(*link_state_event), 775 .timeout_ms = WLAN_WAIT_TIME_LINK_STATE, 776 .dealloc = NULL, 777 }; 778 779 if (!wiphy || !vdev) 780 return status; 781 782 request = osif_request_alloc(¶ms); 783 if (!request) 784 return QDF_STATUS_E_NOMEM; 785 786 cookie = osif_request_cookie(request); 787 link_state_event = osif_request_priv(request); 788 789 info.request_cookie = cookie; 790 info.ml_link_state_resp_cb = ml_link_state_resp_cb; 791 792 status = mlo_get_link_state_register_resp_cb(vdev, 793 &info); 794 if (QDF_IS_STATUS_ERROR(status)) { 795 hdd_err("Failed to register resp callback: %d", status); 796 status = qdf_status_to_os_return(status); 797 goto free_event; 798 } 799 800 status = ml_post_get_link_state_msg(vdev); 801 if (QDF_IS_STATUS_ERROR(status)) { 802 hdd_err("Failed to post scheduler msg"); 803 goto free_event; 804 return status; 805 } 806 807 status = osif_request_wait_for_response(request); 808 if (status) { 809 hdd_err("wait failed or timed out ret: %d", status); 810 goto free_event; 811 } 812 813 hdd_debug("ml_link_state_resp: vdev id %d status %d num %d MAC addr " QDF_MAC_ADDR_FMT, 814 link_state_event->vdev_id, link_state_event->status, 815 link_state_event->num_mlo_vdev_link_info, 816 QDF_MAC_ADDR_REF(link_state_event->mldaddr.bytes)); 817 818 for (num_info = 0; num_info < link_state_event->num_mlo_vdev_link_info; 819 num_info++) { 820 hdd_debug("ml_link_state_resp: chan_freq %d vdev_id %d link_id %d link_status %d", 821 link_state_event->link_info[num_info].chan_freq, 822 link_state_event->link_info[num_info].vdev_id, 823 link_state_event->link_info[num_info].link_id, 824 link_state_event->link_info[num_info].link_status); 825 } 826 827 skb_len = hdd_get_ml_link_state_response_len(link_state_event); 828 829 reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb( 830 wiphy, 831 skb_len); 832 if (!reply_skb) { 833 hdd_err("Get stats - alloc reply_skb failed"); 834 status = QDF_STATUS_E_NOMEM; 835 goto free_event; 836 } 837 838 status = hdd_ml_generate_link_state_resp_nlmsg( 839 reply_skb, link_state_event, 840 link_state_event->num_mlo_vdev_link_info); 841 if (QDF_IS_STATUS_ERROR(status)) { 842 hdd_err("Failed to pack nl response"); 843 goto free_skb; 844 } 845 846 osif_request_put(request); 847 848 errno = wlan_cfg80211_vendor_cmd_reply(reply_skb); 849 return qdf_status_from_os_return(errno); 850 851 free_skb: 852 wlan_cfg80211_vendor_free_skb(reply_skb); 853 free_event: 854 osif_request_put(request); 855 856 return status; 857 } 858 859 #define MLD_MAX_SUPPORTED_LINKS 2 860 861 int wlan_handle_mlo_link_state_operation(struct wiphy *wiphy, 862 struct wlan_objmgr_vdev *vdev, 863 struct hdd_context *hdd_ctx, 864 const void *data, int data_len) 865 { 866 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_LINK_STATE_MAX + 1]; 867 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_MAX + 1]; 868 enum qca_wlan_vendor_link_state_op_types ml_link_op; 869 struct nlattr *link_oper_attr, *mode_attr, *curr_attr, *num_link_attr; 870 int rem_len = 0, rc; 871 uint32_t attr_id, ml_config_state; 872 uint8_t ml_active_num_links, ml_link_control_mode; 873 uint8_t ml_config_link_id, num_links = 0; 874 uint8_t vdev_id = vdev->vdev_objmgr.vdev_id; 875 uint8_t link_id_list[MLD_MAX_SUPPORTED_LINKS] = {0}; 876 uint32_t config_state_list[MLD_MAX_SUPPORTED_LINKS] = {0}; 877 QDF_STATUS status; 878 879 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_LINK_STATE_MAX, 880 data, data_len, 881 ml_link_state_request_policy)) { 882 hdd_debug("vdev %d: invalid mlo link state attr", vdev_id); 883 return -EINVAL; 884 } 885 886 attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_OP_TYPE; 887 link_oper_attr = tb[attr_id]; 888 if (!link_oper_attr) { 889 hdd_debug("vdev %d: link state op not specified", vdev_id); 890 return -EINVAL; 891 } 892 ml_link_op = nla_get_u8(link_oper_attr); 893 switch (ml_link_op) { 894 case QCA_WLAN_VENDOR_LINK_STATE_OP_GET: 895 return wlan_hdd_link_state_request(wiphy, vdev); 896 case QCA_WLAN_VENDOR_LINK_STATE_OP_SET: 897 break; 898 default: 899 hdd_debug("vdev %d: Invalid op type:%d", vdev_id, ml_link_op); 900 return -EINVAL; 901 } 902 903 attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE; 904 mode_attr = tb[attr_id]; 905 if (!mode_attr) { 906 hdd_debug("vdev %d: ml links control mode attr not present", 907 vdev_id); 908 return -EINVAL; 909 } 910 ml_link_control_mode = nla_get_u8(mode_attr); 911 912 switch (ml_link_control_mode) { 913 case QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_DEFAULT: 914 /* clear mlo link(s) settings in fw as per driver */ 915 status = policy_mgr_clear_ml_links_settings_in_fw(hdd_ctx->psoc, 916 vdev_id); 917 if (QDF_IS_STATUS_ERROR(status)) 918 return -EINVAL; 919 break; 920 case QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_USER: 921 attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG; 922 if (!tb[attr_id]) { 923 hdd_debug("vdev %d: state config attr not present", 924 vdev_id); 925 return -EINVAL; 926 } 927 928 nla_for_each_nested(curr_attr, tb[attr_id], rem_len) { 929 rc = wlan_cfg80211_nla_parse_nested( 930 tb2, QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_MAX, 931 curr_attr, 932 ml_link_state_config_policy); 933 if (rc) { 934 hdd_debug("vdev %d: nested attr not present", 935 vdev_id); 936 return -EINVAL; 937 } 938 939 attr_id = 940 QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID; 941 if (!tb2[attr_id]) { 942 hdd_debug("vdev %d: link id attr not present", 943 vdev_id); 944 return -EINVAL; 945 } 946 947 ml_config_link_id = nla_get_u8(tb2[attr_id]); 948 949 attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE; 950 if (!tb2[attr_id]) { 951 hdd_debug("vdev %d: config attr not present", 952 vdev_id); 953 return -EINVAL; 954 } 955 956 ml_config_state = nla_get_u32(tb2[attr_id]); 957 hdd_debug("vdev %d: ml_link_id %d, ml_link_state:%d", 958 vdev_id, ml_config_link_id, ml_config_state); 959 link_id_list[num_links] = ml_config_link_id; 960 config_state_list[num_links] = ml_config_state; 961 num_links++; 962 963 if (num_links >= MLD_MAX_SUPPORTED_LINKS) 964 break; 965 } 966 967 status = policy_mgr_update_mlo_links_based_on_linkid( 968 hdd_ctx->psoc, 969 vdev_id, num_links, 970 link_id_list, 971 config_state_list); 972 if (QDF_IS_STATUS_ERROR(status)) 973 return -EINVAL; 974 break; 975 case QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_MIXED: 976 attr_id = 977 QCA_WLAN_VENDOR_ATTR_LINK_STATE_MIXED_MODE_ACTIVE_NUM_LINKS; 978 num_link_attr = tb[attr_id]; 979 if (!num_link_attr) { 980 hdd_debug("number of active state links not specified"); 981 return -EINVAL; 982 } 983 ml_active_num_links = nla_get_u8(num_link_attr); 984 hdd_debug("vdev %d: ml_active_num_links: %d", vdev_id, 985 ml_active_num_links); 986 if (ml_active_num_links > MLD_MAX_SUPPORTED_LINKS) 987 return -EINVAL; 988 status = policy_mgr_update_active_mlo_num_links(hdd_ctx->psoc, 989 vdev_id, ml_active_num_links); 990 if (QDF_IS_STATUS_ERROR(status)) 991 return -EINVAL; 992 break; 993 default: 994 hdd_debug("vdev %d: invalid ml_link_control_mode: %d", vdev_id, 995 ml_link_control_mode); 996 return -EINVAL; 997 } 998 999 hdd_debug("vdev: %d, processed link state command successfully", 1000 vdev_id); 1001 return 0; 1002 } 1003 1004 static uint32_t 1005 hdd_get_t2lm_setup_event_len(void) 1006 { 1007 uint32_t len = 0; 1008 uint32_t info_len = 0; 1009 1010 len = NLMSG_HDRLEN; 1011 1012 /* QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AP_MLD_ADDR */ 1013 len += nla_total_size(QDF_MAC_ADDR_SIZE); 1014 1015 /* nest */ 1016 info_len = NLA_HDRLEN; 1017 /* QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK */ 1018 info_len += NLA_HDRLEN + sizeof(u16); 1019 /* QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK */ 1020 info_len += NLA_HDRLEN + sizeof(u16); 1021 1022 /* QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS */ 1023 len += NLA_HDRLEN + (info_len * T2LM_MAX_NUM_TIDS); 1024 1025 return len; 1026 } 1027 1028 static QDF_STATUS 1029 hdd_t2lm_pack_nl_response(struct sk_buff *skb, 1030 struct wlan_objmgr_vdev *vdev, 1031 struct wlan_t2lm_info *t2lm, 1032 struct qdf_mac_addr mld_addr) 1033 { 1034 struct nlattr *config_attr, *config_params; 1035 uint32_t i = 0, attr, attr1; 1036 int errno; 1037 uint32_t value; 1038 uint8_t tid_num; 1039 1040 attr = QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AP_MLD_ADDR; 1041 if (nla_put(skb, attr, QDF_MAC_ADDR_SIZE, mld_addr.bytes)) { 1042 hdd_err("Failed to put mac_addr"); 1043 return QDF_STATUS_E_INVAL; 1044 } 1045 1046 if (t2lm->default_link_mapping) { 1047 hdd_debug("update mld addr for default mapping"); 1048 return QDF_STATUS_SUCCESS; 1049 } 1050 1051 attr = QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS; 1052 config_attr = nla_nest_start(skb, attr); 1053 if (!config_attr) { 1054 hdd_err("nla_nest_start error"); 1055 return QDF_STATUS_E_INVAL; 1056 } 1057 1058 switch (t2lm->direction) { 1059 case WLAN_T2LM_UL_DIRECTION: 1060 for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) { 1061 config_params = nla_nest_start(skb, tid_num + 1); 1062 if (!config_params) 1063 return -EINVAL; 1064 1065 attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK; 1066 value = t2lm->ieee_link_map_tid[i]; 1067 errno = nla_put_u16(skb, attr1, value); 1068 if (errno) 1069 return errno; 1070 1071 attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK; 1072 value = 0; 1073 errno = nla_put_u16(skb, attr1, value); 1074 if (errno) 1075 return errno; 1076 nla_nest_end(skb, config_params); 1077 } 1078 break; 1079 case WLAN_T2LM_DL_DIRECTION: 1080 for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) { 1081 config_params = nla_nest_start(skb, tid_num + 1); 1082 if (!config_params) 1083 return -EINVAL; 1084 attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK; 1085 value = t2lm->ieee_link_map_tid[i]; 1086 errno = nla_put_u16(skb, attr1, value); 1087 if (errno) 1088 return errno; 1089 1090 attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK; 1091 value = 0; 1092 errno = nla_put_u16(skb, attr1, value); 1093 if (errno) 1094 return errno; 1095 nla_nest_end(skb, config_params); 1096 } 1097 break; 1098 case WLAN_T2LM_BIDI_DIRECTION: 1099 for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) { 1100 config_params = nla_nest_start(skb, tid_num + 1); 1101 if (!config_params) 1102 return -EINVAL; 1103 1104 attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK; 1105 value = t2lm->ieee_link_map_tid[i]; 1106 errno = nla_put_u16(skb, attr1, value); 1107 if (errno) 1108 return errno; 1109 1110 attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK; 1111 value = t2lm->ieee_link_map_tid[i]; 1112 errno = nla_put_u16(skb, attr1, value); 1113 if (errno) 1114 return errno; 1115 nla_nest_end(skb, config_params); 1116 } 1117 break; 1118 default: 1119 return -EINVAL; 1120 } 1121 nla_nest_end(skb, config_attr); 1122 return QDF_STATUS_SUCCESS; 1123 } 1124 1125 QDF_STATUS wlan_hdd_send_t2lm_event(struct wlan_objmgr_vdev *vdev, 1126 struct wlan_t2lm_info *t2lm) 1127 { 1128 struct sk_buff *skb; 1129 size_t data_len; 1130 QDF_STATUS status; 1131 struct qdf_mac_addr mld_addr; 1132 struct hdd_adapter *adapter; 1133 struct wlan_hdd_link_info *link_info; 1134 1135 enum qca_nl80211_vendor_subcmds_index index = 1136 QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP_INDEX; 1137 1138 link_info = wlan_hdd_get_link_info_from_objmgr(vdev); 1139 if (!link_info) { 1140 hdd_err("Invalid VDEV"); 1141 return QDF_STATUS_E_FAILURE; 1142 } 1143 1144 adapter = link_info->adapter; 1145 data_len = hdd_get_t2lm_setup_event_len(); 1146 skb = wlan_cfg80211_vendor_event_alloc(adapter->hdd_ctx->wiphy, 1147 NULL, 1148 data_len, 1149 index, GFP_KERNEL); 1150 if (!skb) { 1151 hdd_err("wlan_cfg80211_vendor_event_alloc failed"); 1152 return -EINVAL; 1153 } 1154 1155 /* get mld addr */ 1156 status = wlan_vdev_get_bss_peer_mld_mac(vdev, &mld_addr); 1157 if (QDF_IS_STATUS_ERROR(status)) { 1158 hdd_err("Failed to get mld address"); 1159 goto free_skb; 1160 } 1161 1162 status = hdd_t2lm_pack_nl_response(skb, vdev, t2lm, mld_addr); 1163 if (QDF_IS_STATUS_ERROR(status)) { 1164 hdd_err("Failed to pack nl response"); 1165 goto free_skb; 1166 } 1167 1168 wlan_cfg80211_vendor_event(skb, GFP_KERNEL); 1169 1170 return status; 1171 free_skb: 1172 wlan_cfg80211_vendor_free_skb(skb); 1173 1174 return status; 1175 } 1176 #endif 1177