1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: wlan_tdls_ct.c 22 * 23 * TDLS connection tracker function definitions 24 */ 25 26 #include "wlan_tdls_main.h" 27 #include "wlan_tdls_peer.h" 28 #include "wlan_tdls_ct.h" 29 #include "wlan_tdls_mgmt.h" 30 #include "wlan_mlo_mgr_sta.h" 31 #include "wlan_tdls_cmds_process.h" 32 #include "wlan_reg_services_api.h" 33 #include "wlan_policy_mgr_api.h" 34 #include "wlan_tdls_tgt_api.h" 35 36 bool tdls_is_vdev_authenticated(struct wlan_objmgr_vdev *vdev) 37 { 38 struct wlan_objmgr_peer *peer; 39 bool is_authenticated = false; 40 41 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID); 42 if (!peer) { 43 tdls_err("peer is null"); 44 return false; 45 } 46 47 is_authenticated = wlan_peer_mlme_get_auth_state(peer); 48 wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_NB_ID); 49 return is_authenticated; 50 } 51 52 /** 53 * tdls_peer_reset_discovery_processed() - reset discovery status 54 * @tdls_vdev: TDLS vdev object 55 * 56 * This function resets discovery processing bit for all TDLS peers 57 * 58 * Caller has to take the lock before calling this function 59 * 60 * Return: 0 61 */ 62 static int32_t tdls_peer_reset_discovery_processed( 63 struct tdls_vdev_priv_obj *tdls_vdev) 64 { 65 int i; 66 qdf_list_t *head; 67 qdf_list_node_t *p_node; 68 struct tdls_peer *peer; 69 QDF_STATUS status; 70 71 tdls_vdev->discovery_peer_cnt = 0; 72 73 for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) { 74 head = &tdls_vdev->peer_list[i]; 75 status = qdf_list_peek_front(head, &p_node); 76 while (QDF_IS_STATUS_SUCCESS(status)) { 77 peer = qdf_container_of(p_node, struct tdls_peer, node); 78 peer->discovery_processed = 0; 79 status = qdf_list_peek_next(head, p_node, &p_node); 80 } 81 } 82 83 return 0; 84 } 85 86 void tdls_discovery_timeout_peer_cb(void *user_data) 87 { 88 int i; 89 qdf_list_t *head; 90 qdf_list_node_t *p_node; 91 struct tdls_peer *peer; 92 QDF_STATUS status; 93 struct tdls_vdev_priv_obj *tdls_vdev; 94 struct tdls_soc_priv_obj *tdls_soc; 95 struct wlan_objmgr_vdev *vdev; 96 struct wlan_objmgr_vdev *select_vdev; 97 struct wlan_objmgr_vdev *tdls_link_vdev; 98 struct tdls_rx_mgmt_frame *rx_mgmt; 99 uint8_t *mac; 100 bool unforce = true; 101 102 if (!user_data) { 103 tdls_err("discovery time out data is null"); 104 return; 105 } 106 107 vdev = (struct wlan_objmgr_vdev *)user_data; 108 tdls_soc = wlan_vdev_get_tdls_soc_obj(vdev); 109 if (!tdls_soc) 110 return; 111 112 /* timer_cnt is reset when link switch happens */ 113 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 114 qdf_atomic_read(&tdls_soc->timer_cnt) == 0) 115 return; 116 117 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 118 qdf_atomic_dec_and_test(&tdls_soc->timer_cnt)) { 119 tdls_process_mlo_cal_tdls_link_score(vdev); 120 select_vdev = tdls_process_mlo_choice_tdls_vdev(vdev); 121 tdls_link_vdev = tdls_mlo_get_tdls_link_vdev(vdev); 122 if (select_vdev) { 123 tdls_vdev = 124 wlan_objmgr_vdev_get_comp_private_obj(select_vdev, 125 WLAN_UMAC_COMP_TDLS); 126 rx_mgmt = tdls_vdev->rx_mgmt; 127 if (tdls_link_vdev && tdls_link_vdev != select_vdev) { 128 tdls_debug("tdls link created on vdev %d", 129 wlan_vdev_get_id(tdls_link_vdev)); 130 } else { 131 mac = 132 &rx_mgmt->buf[TDLS_80211_PEER_ADDR_OFFSET]; 133 tdls_notice("[TDLS] TDLS Discovery Response," 134 "QDF_MAC_ADDR_FMT RSSI[%d]<---OTA", 135 rx_mgmt->rx_rssi); 136 tdls_debug("discovery resp on vdev %d", 137 wlan_vdev_get_id(tdls_vdev->vdev)); 138 tdls_recv_discovery_resp(tdls_vdev, mac); 139 tdls_set_rssi(tdls_vdev->vdev, mac, 140 rx_mgmt->rx_rssi); 141 if (tdls_soc && tdls_soc->tdls_rx_cb) 142 tdls_soc->tdls_rx_cb( 143 tdls_soc->tdls_rx_cb_data, 144 rx_mgmt); 145 } 146 147 qdf_mem_free(tdls_vdev->rx_mgmt); 148 tdls_vdev->rx_mgmt = NULL; 149 tdls_vdev->link_score = 0; 150 151 return; 152 } 153 154 tdls_debug("no discovery response"); 155 } 156 157 tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev); 158 if (!tdls_vdev) 159 return; 160 161 for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) { 162 head = &tdls_vdev->peer_list[i]; 163 status = qdf_list_peek_front(head, &p_node); 164 while (QDF_IS_STATUS_SUCCESS(status)) { 165 peer = qdf_container_of(p_node, struct tdls_peer, 166 node); 167 168 tdls_debug("Peer: " QDF_MAC_ADDR_FMT "link status %d, vdev id %d", 169 QDF_MAC_ADDR_REF(peer->peer_mac.bytes), 170 peer->link_status, wlan_vdev_get_id(vdev)); 171 172 if (peer->link_status != TDLS_LINK_DISCOVERING && 173 peer->link_status != TDLS_LINK_IDLE) 174 unforce = false; 175 176 if (TDLS_LINK_DISCOVERING != peer->link_status) { 177 status = qdf_list_peek_next(head, p_node, 178 &p_node); 179 continue; 180 } 181 tdls_debug(QDF_MAC_ADDR_FMT " to idle state", 182 QDF_MAC_ADDR_REF(peer->peer_mac.bytes)); 183 tdls_set_peer_link_status(peer, 184 TDLS_LINK_IDLE, 185 TDLS_LINK_NOT_SUPPORTED); 186 } 187 } 188 189 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && unforce) { 190 tdls_debug("try to set vdev %d to unforce", 191 wlan_vdev_get_id(vdev)); 192 tdls_set_link_unforce(vdev); 193 } 194 195 tdls_vdev->discovery_sent_cnt = 0; 196 /* add tdls power save prohibited */ 197 198 return; 199 } 200 201 /** 202 * tdls_reset_tx_rx() - reset tx/rx counters for all tdls peers 203 * @tdls_vdev: TDLS vdev object 204 * 205 * Caller has to take the TDLS lock before calling this function 206 * 207 * Return: Void 208 */ 209 static void tdls_reset_tx_rx(struct tdls_vdev_priv_obj *tdls_vdev) 210 { 211 int i; 212 qdf_list_t *head; 213 qdf_list_node_t *p_node; 214 struct tdls_peer *peer; 215 QDF_STATUS status; 216 struct tdls_soc_priv_obj *tdls_soc; 217 218 tdls_soc = wlan_vdev_get_tdls_soc_obj(tdls_vdev->vdev); 219 if (!tdls_soc) 220 return; 221 222 /* reset stale connection tracker */ 223 qdf_spin_lock_bh(&tdls_soc->tdls_ct_spinlock); 224 tdls_vdev->valid_mac_entries = 0; 225 qdf_spin_unlock_bh(&tdls_soc->tdls_ct_spinlock); 226 227 for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) { 228 head = &tdls_vdev->peer_list[i]; 229 status = qdf_list_peek_front(head, &p_node); 230 while (QDF_IS_STATUS_SUCCESS(status)) { 231 peer = qdf_container_of(p_node, struct tdls_peer, node); 232 peer->tx_pkt = 0; 233 peer->rx_pkt = 0; 234 status = qdf_list_peek_next(head, p_node, &p_node); 235 } 236 } 237 return; 238 } 239 240 void tdls_implicit_disable(struct tdls_vdev_priv_obj *tdls_vdev) 241 { 242 tdls_debug("Disable Implicit TDLS"); 243 tdls_timers_stop(tdls_vdev); 244 } 245 246 /** 247 * tdls_implicit_enable() - enable implicit tdls triggering 248 * @tdls_vdev: TDLS vdev 249 * 250 * Return: Void 251 */ 252 void tdls_implicit_enable(struct tdls_vdev_priv_obj *tdls_vdev) 253 { 254 tdls_debug("Enable Implicit TDLS"); 255 if (!tdls_vdev) 256 return; 257 258 tdls_peer_reset_discovery_processed(tdls_vdev); 259 tdls_reset_tx_rx(tdls_vdev); 260 /* TODO check whether tdls power save prohibited */ 261 262 /* Restart the connection tracker timer */ 263 tdls_timer_restart(tdls_vdev->vdev, &tdls_vdev->peer_update_timer, 264 tdls_vdev->threshold_config.tx_period_t); 265 } 266 267 /** 268 * tdls_ct_sampling_tx_rx() - collect tx/rx traffic sample 269 * @tdls_vdev: tdls vdev object 270 * @tdls_soc: tdls soc object 271 * 272 * Function to update data traffic information in tdls connection 273 * tracker data structure for connection tracker operation 274 * 275 * Return: None 276 */ 277 static void tdls_ct_sampling_tx_rx(struct tdls_vdev_priv_obj *tdls_vdev, 278 struct tdls_soc_priv_obj *tdls_soc) 279 { 280 struct tdls_peer *curr_peer; 281 uint8_t mac[QDF_MAC_ADDR_SIZE]; 282 uint8_t mac_cnt; 283 uint8_t mac_entries; 284 struct tdls_conn_tracker_mac_table mac_table[WLAN_TDLS_CT_TABLE_SIZE]; 285 286 qdf_spin_lock_bh(&tdls_soc->tdls_ct_spinlock); 287 288 if (0 == tdls_vdev->valid_mac_entries) { 289 qdf_spin_unlock_bh(&tdls_soc->tdls_ct_spinlock); 290 return; 291 } 292 293 mac_entries = QDF_MIN(tdls_vdev->valid_mac_entries, 294 WLAN_TDLS_CT_TABLE_SIZE); 295 296 qdf_mem_copy(mac_table, tdls_vdev->ct_peer_table, 297 (sizeof(struct tdls_conn_tracker_mac_table)) * mac_entries); 298 299 qdf_mem_zero(tdls_vdev->ct_peer_table, 300 (sizeof(struct tdls_conn_tracker_mac_table)) * mac_entries); 301 302 tdls_vdev->valid_mac_entries = 0; 303 304 qdf_spin_unlock_bh(&tdls_soc->tdls_ct_spinlock); 305 306 for (mac_cnt = 0; mac_cnt < mac_entries; mac_cnt++) { 307 qdf_mem_copy(mac, mac_table[mac_cnt].mac_address.bytes, 308 QDF_MAC_ADDR_SIZE); 309 curr_peer = tdls_get_peer(tdls_vdev, mac); 310 if (curr_peer) { 311 curr_peer->tx_pkt = 312 mac_table[mac_cnt].tx_packet_cnt; 313 curr_peer->rx_pkt = 314 mac_table[mac_cnt].rx_packet_cnt; 315 } 316 } 317 } 318 319 void tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev *vdev, 320 struct qdf_mac_addr *mac_addr, 321 struct qdf_mac_addr *dest_mac_addr) 322 { 323 struct tdls_vdev_priv_obj *tdls_vdev_obj; 324 struct tdls_soc_priv_obj *tdls_soc_obj; 325 uint8_t mac_cnt; 326 uint8_t valid_mac_entries; 327 struct tdls_conn_tracker_mac_table *mac_table; 328 struct wlan_objmgr_peer *bss_peer; 329 330 if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev, &tdls_vdev_obj, 331 &tdls_soc_obj)) 332 return; 333 334 if (!tdls_soc_obj->enable_tdls_connection_tracker) 335 return; 336 337 /* Here we do without lock to ensure that in high throughput scenarios 338 * its fast and we quickly check the right mac entry and increment 339 * the pkt count. Here it may happen that 340 * "tdls_vdev_obj->valid_mac_entries", "tdls_vdev_obj->ct_peer_table" 341 * becomes zero in another thread but we are ok as this will not 342 * lead to any crash. 343 */ 344 valid_mac_entries = tdls_vdev_obj->valid_mac_entries; 345 mac_table = tdls_vdev_obj->ct_peer_table; 346 347 for (mac_cnt = 0; mac_cnt < valid_mac_entries; mac_cnt++) { 348 if (qdf_mem_cmp(mac_table[mac_cnt].mac_address.bytes, 349 mac_addr, QDF_MAC_ADDR_SIZE) == 0) { 350 mac_table[mac_cnt].rx_packet_cnt++; 351 return; 352 } 353 } 354 355 if (qdf_is_macaddr_group(mac_addr)) 356 return; 357 358 if (qdf_is_macaddr_group(dest_mac_addr)) 359 return; 360 361 if (!qdf_mem_cmp(vdev->vdev_mlme.macaddr, mac_addr, 362 QDF_MAC_ADDR_SIZE)) 363 return; 364 365 bss_peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID); 366 if (bss_peer) { 367 if (!qdf_mem_cmp(bss_peer->macaddr, mac_addr, 368 QDF_MAC_ADDR_SIZE)) { 369 wlan_objmgr_peer_release_ref(bss_peer, WLAN_TDLS_NB_ID); 370 return; 371 } 372 wlan_objmgr_peer_release_ref(bss_peer, WLAN_TDLS_NB_ID); 373 } 374 qdf_spin_lock_bh(&tdls_soc_obj->tdls_ct_spinlock); 375 376 /* when we take the lock we need to get the valid mac entries 377 * again as it may become zero in another thread and if is 0 then 378 * we need to reset "mac_cnt" to zero so that at zeroth index we 379 * add new entry 380 */ 381 valid_mac_entries = tdls_vdev_obj->valid_mac_entries; 382 if (!valid_mac_entries) 383 mac_cnt = 0; 384 385 /* If we have more than 8 peers within 30 mins. we will 386 * stop tracking till the old entries are removed 387 */ 388 if (mac_cnt < WLAN_TDLS_CT_TABLE_SIZE) { 389 qdf_mem_copy(mac_table[mac_cnt].mac_address.bytes, 390 mac_addr, QDF_MAC_ADDR_SIZE); 391 tdls_vdev_obj->valid_mac_entries = mac_cnt+1; 392 mac_table[mac_cnt].rx_packet_cnt = 1; 393 } 394 395 qdf_spin_unlock_bh(&tdls_soc_obj->tdls_ct_spinlock); 396 return; 397 } 398 399 void tdls_update_tx_pkt_cnt(struct wlan_objmgr_vdev *vdev, 400 struct qdf_mac_addr *mac_addr) 401 { 402 struct tdls_vdev_priv_obj *tdls_vdev_obj; 403 struct tdls_soc_priv_obj *tdls_soc_obj; 404 uint8_t mac_cnt; 405 uint8_t valid_mac_entries; 406 struct tdls_conn_tracker_mac_table *mac_table; 407 struct wlan_objmgr_peer *bss_peer; 408 409 if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev, &tdls_vdev_obj, 410 &tdls_soc_obj)) 411 return; 412 413 if (!tdls_soc_obj->enable_tdls_connection_tracker) 414 return; 415 416 /* Here we do without lock to ensure that in high throughput scenarios 417 * its fast and we quickly check the right mac entry and increment 418 * the pkt count. Here it may happen that 419 * "tdls_vdev_obj->valid_mac_entries", "tdls_vdev_obj->ct_peer_table" 420 * becomes zero in another thread but we are ok as this will not 421 * lead to any crash. 422 */ 423 mac_table = tdls_vdev_obj->ct_peer_table; 424 valid_mac_entries = tdls_vdev_obj->valid_mac_entries; 425 426 for (mac_cnt = 0; mac_cnt < valid_mac_entries; mac_cnt++) { 427 if (qdf_mem_cmp(mac_table[mac_cnt].mac_address.bytes, 428 mac_addr, QDF_MAC_ADDR_SIZE) == 0) { 429 mac_table[mac_cnt].tx_packet_cnt++; 430 return; 431 } 432 } 433 434 if (qdf_is_macaddr_group(mac_addr)) 435 return; 436 437 if (!qdf_mem_cmp(vdev->vdev_mlme.macaddr, mac_addr, 438 QDF_MAC_ADDR_SIZE)) 439 return; 440 bss_peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID); 441 if (bss_peer) { 442 if (!qdf_mem_cmp(bss_peer->macaddr, mac_addr, 443 QDF_MAC_ADDR_SIZE)) { 444 wlan_objmgr_peer_release_ref(bss_peer, WLAN_TDLS_NB_ID); 445 return; 446 } 447 wlan_objmgr_peer_release_ref(bss_peer, WLAN_TDLS_NB_ID); 448 } 449 450 qdf_spin_lock_bh(&tdls_soc_obj->tdls_ct_spinlock); 451 452 /* when we take the lock we need to get the valid mac entries 453 * again as it may become zero in another thread and if is 0 then 454 * we need to reset "mac_cnt" to zero so that at zeroth index we 455 * add new entry 456 */ 457 valid_mac_entries = tdls_vdev_obj->valid_mac_entries; 458 if (!valid_mac_entries) 459 mac_cnt = 0; 460 461 /* If we have more than 8 peers within 30 mins. we will 462 * stop tracking till the old entries are removed 463 */ 464 if (mac_cnt < WLAN_TDLS_CT_TABLE_SIZE) { 465 qdf_mem_copy(mac_table[mac_cnt].mac_address.bytes, 466 mac_addr, QDF_MAC_ADDR_SIZE); 467 mac_table[mac_cnt].tx_packet_cnt = 1; 468 tdls_vdev_obj->valid_mac_entries++; 469 } 470 471 qdf_spin_unlock_bh(&tdls_soc_obj->tdls_ct_spinlock); 472 return; 473 } 474 475 void tdls_implicit_send_discovery_request( 476 struct tdls_vdev_priv_obj *tdls_vdev_obj) 477 { 478 struct tdls_peer *curr_peer; 479 struct tdls_peer *temp_peer; 480 struct tdls_soc_priv_obj *tdls_psoc; 481 struct tdls_osif_indication tdls_ind; 482 483 if (!tdls_vdev_obj) { 484 tdls_notice("tdls_vdev_obj is NULL"); 485 return; 486 } 487 488 tdls_psoc = wlan_vdev_get_tdls_soc_obj(tdls_vdev_obj->vdev); 489 490 if (!tdls_psoc) { 491 tdls_notice("tdls_psoc_obj is NULL"); 492 return; 493 } 494 495 curr_peer = tdls_vdev_obj->curr_candidate; 496 497 if (!curr_peer) { 498 tdls_err("curr_peer is NULL"); 499 return; 500 } 501 502 /* This function is called in mutex_lock */ 503 temp_peer = tdls_is_progress(tdls_vdev_obj, NULL, 0); 504 if (temp_peer) { 505 tdls_notice(QDF_MAC_ADDR_FMT " ongoing. pre_setup ignored", 506 QDF_MAC_ADDR_REF(temp_peer->peer_mac.bytes)); 507 goto done; 508 } 509 510 if (TDLS_CAP_UNKNOWN != curr_peer->tdls_support) 511 tdls_set_peer_link_status(curr_peer, 512 TDLS_LINK_DISCOVERING, 513 TDLS_LINK_SUCCESS); 514 515 qdf_mem_copy(tdls_ind.peer_mac, curr_peer->peer_mac.bytes, 516 QDF_MAC_ADDR_SIZE); 517 518 tdls_ind.vdev = tdls_vdev_obj->vdev; 519 520 tdls_debug("Implicit TDLS, Send Discovery request event"); 521 522 tdls_psoc->tdls_event_cb(tdls_psoc->tdls_evt_cb_data, 523 TDLS_EVENT_DISCOVERY_REQ, &tdls_ind); 524 525 if (!wlan_vdev_mlme_is_mlo_vdev(tdls_vdev_obj->vdev)) { 526 tdls_vdev_obj->discovery_sent_cnt++; 527 tdls_timer_restart(tdls_vdev_obj->vdev, 528 &tdls_vdev_obj->peer_discovery_timer, 529 tdls_vdev_obj->threshold_config.tx_period_t - 530 TDLS_DISCOVERY_TIMEOUT_ERE_UPDATE); 531 532 tdls_debug("discovery count %u timeout %u msec", 533 tdls_vdev_obj->discovery_sent_cnt, 534 tdls_vdev_obj->threshold_config.tx_period_t - 535 TDLS_DISCOVERY_TIMEOUT_ERE_UPDATE); 536 } 537 done: 538 tdls_vdev_obj->curr_candidate = NULL; 539 tdls_vdev_obj->magic = 0; 540 return; 541 } 542 543 int tdls_recv_discovery_resp(struct tdls_vdev_priv_obj *tdls_vdev, 544 const uint8_t *mac) 545 { 546 struct tdls_peer *curr_peer; 547 struct tdls_soc_priv_obj *tdls_soc; 548 struct tdls_osif_indication indication; 549 struct tdls_config_params *tdls_cfg; 550 int status = 0; 551 552 if (!tdls_vdev) 553 return -EINVAL; 554 555 tdls_soc = wlan_vdev_get_tdls_soc_obj(tdls_vdev->vdev); 556 if (!tdls_soc) { 557 tdls_err("tdls soc is NULL"); 558 return -EINVAL; 559 } 560 561 curr_peer = tdls_get_peer(tdls_vdev, mac); 562 if (!curr_peer) { 563 tdls_err("curr_peer is NULL"); 564 return -EINVAL; 565 } 566 567 if (!wlan_vdev_mlme_is_mlo_vdev(tdls_vdev->vdev)) { 568 if (tdls_vdev->discovery_sent_cnt) 569 tdls_vdev->discovery_sent_cnt--; 570 571 if (tdls_vdev->discovery_sent_cnt == 0) 572 qdf_mc_timer_stop(&tdls_vdev->peer_discovery_timer); 573 } 574 575 tdls_debug("Discovery(%u) Response from " QDF_MAC_ADDR_FMT 576 " link_status %d", tdls_vdev->discovery_sent_cnt, 577 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes), 578 curr_peer->link_status); 579 580 /* Since peer link status bases on vdev and stream goes through 581 * vdev0 (assoc link) at start, rx/tx pkt count on vdev0, but 582 * it choices vdev1 as tdls link, the peer status does not change on 583 * vdev1 though it has been changed for vdev0 per the rx/tx pkt count. 584 */ 585 if (wlan_vdev_mlme_is_mlo_vdev(tdls_vdev->vdev) && 586 curr_peer->link_status == TDLS_LINK_IDLE) 587 tdls_set_peer_link_status(curr_peer, TDLS_LINK_DISCOVERING, 588 TDLS_LINK_SUCCESS); 589 590 tdls_cfg = &tdls_vdev->threshold_config; 591 if (TDLS_LINK_DISCOVERING == curr_peer->link_status) { 592 /* Since we are here, it means Throughput threshold is 593 * already met. Make sure RSSI threshold is also met 594 * before setting up TDLS link. 595 */ 596 if ((int32_t) curr_peer->rssi > 597 (int32_t) tdls_cfg->rssi_trigger_threshold) { 598 tdls_set_peer_link_status(curr_peer, 599 TDLS_LINK_DISCOVERED, 600 TDLS_LINK_SUCCESS); 601 tdls_debug("Rssi Threshold met: " QDF_MAC_ADDR_FMT 602 " rssi = %d threshold= %d", 603 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes), 604 curr_peer->rssi, 605 tdls_cfg->rssi_trigger_threshold); 606 607 qdf_mem_copy(indication.peer_mac, mac, 608 QDF_MAC_ADDR_SIZE); 609 610 indication.vdev = tdls_vdev->vdev; 611 612 tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data, 613 TDLS_EVENT_SETUP_REQ, 614 &indication); 615 } else { 616 tdls_debug("Rssi Threshold not met: " QDF_MAC_ADDR_FMT 617 " rssi = %d threshold = %d ", 618 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes), 619 curr_peer->rssi, 620 tdls_cfg->rssi_trigger_threshold); 621 622 tdls_set_peer_link_status(curr_peer, 623 TDLS_LINK_IDLE, 624 TDLS_LINK_UNSPECIFIED); 625 626 /* if RSSI threshold is not met then allow 627 * further discovery attempts by decrementing 628 * count for the last attempt 629 */ 630 if (curr_peer->discovery_attempt) 631 curr_peer->discovery_attempt--; 632 } 633 } 634 635 curr_peer->tdls_support = TDLS_CAP_SUPPORTED; 636 637 return status; 638 } 639 640 void tdls_indicate_teardown(struct tdls_vdev_priv_obj *tdls_vdev, 641 struct tdls_peer *curr_peer, 642 uint16_t reason) 643 { 644 struct tdls_soc_priv_obj *tdls_soc; 645 struct tdls_osif_indication indication; 646 647 if (!tdls_vdev || !curr_peer) { 648 tdls_err("tdls_vdev: %pK, curr_peer: %pK", 649 tdls_vdev, curr_peer); 650 return; 651 } 652 653 tdls_soc = wlan_vdev_get_tdls_soc_obj(tdls_vdev->vdev); 654 if (!tdls_soc) { 655 tdls_err("tdls_soc: %pK", tdls_soc); 656 return; 657 } 658 659 if (curr_peer->link_status != TDLS_LINK_CONNECTED) { 660 tdls_err("link state %d peer:" QDF_MAC_ADDR_FMT, 661 curr_peer->link_status, 662 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes)); 663 return; 664 } 665 666 tdls_set_peer_link_status(curr_peer, 667 TDLS_LINK_TEARING, 668 TDLS_LINK_UNSPECIFIED); 669 tdls_notice("Teardown reason %d", reason); 670 671 if (tdls_soc->tdls_dp_vdev_update) 672 tdls_soc->tdls_dp_vdev_update( 673 &tdls_soc->soc, 674 wlan_vdev_get_id(tdls_vdev->vdev), 675 tdls_soc->tdls_update_dp_vdev_flags, 676 false); 677 678 indication.reason = reason; 679 indication.vdev = tdls_vdev->vdev; 680 qdf_mem_copy(indication.peer_mac, curr_peer->peer_mac.bytes, 681 QDF_MAC_ADDR_SIZE); 682 683 if (tdls_soc->tdls_event_cb) 684 tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data, 685 TDLS_EVENT_TEARDOWN_REQ, &indication); 686 } 687 688 /** 689 * tdls_get_conn_info() - get the tdls connection information. 690 * @tdls_soc: tdls soc object 691 * @peer_mac: peer MAC address 692 * 693 * Function to check tdls sta index 694 * 695 * Return: tdls connection information 696 */ 697 static struct tdls_conn_info * 698 tdls_get_conn_info(struct tdls_soc_priv_obj *tdls_soc, 699 struct qdf_mac_addr *peer_mac) 700 { 701 uint8_t sta_idx; 702 /* check if there is available index for this new TDLS STA */ 703 for (sta_idx = 0; sta_idx < WLAN_TDLS_STA_MAX_NUM; sta_idx++) { 704 if (!qdf_mem_cmp( 705 tdls_soc->tdls_conn_info[sta_idx].peer_mac.bytes, 706 peer_mac->bytes, QDF_MAC_ADDR_SIZE)) { 707 tdls_debug("tdls peer exists idx %d " QDF_MAC_ADDR_FMT, 708 sta_idx, 709 QDF_MAC_ADDR_REF(peer_mac->bytes)); 710 tdls_soc->tdls_conn_info[sta_idx].index = sta_idx; 711 return &tdls_soc->tdls_conn_info[sta_idx]; 712 } 713 } 714 715 tdls_err("tdls peer does not exists"); 716 return NULL; 717 } 718 719 static void 720 tdls_ct_process_idle_handler(struct wlan_objmgr_vdev *vdev, 721 struct tdls_conn_info *tdls_info) 722 { 723 struct tdls_peer *curr_peer; 724 struct tdls_vdev_priv_obj *tdls_vdev_obj; 725 struct tdls_soc_priv_obj *tdls_soc_obj; 726 727 if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev, &tdls_vdev_obj, 728 &tdls_soc_obj)) 729 return; 730 731 if (!tdls_info->valid_entry) { 732 tdls_err("peer doesn't exists"); 733 return; 734 } 735 736 curr_peer = tdls_find_peer(tdls_vdev_obj, 737 (u8 *) &tdls_info->peer_mac.bytes[0]); 738 739 if (!curr_peer) { 740 tdls_err("Invalid tdls idle timer expired"); 741 return; 742 } 743 744 tdls_debug(QDF_MAC_ADDR_FMT 745 " tx_pkt: %d, rx_pkt: %d, idle_packet_n: %d", 746 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes), 747 curr_peer->tx_pkt, 748 curr_peer->rx_pkt, 749 tdls_vdev_obj->threshold_config.idle_packet_n); 750 751 /* Check tx/rx statistics on this tdls link for recent activities and 752 * then decide whether to tear down the link or keep it. 753 */ 754 if ((curr_peer->tx_pkt >= 755 tdls_vdev_obj->threshold_config.idle_packet_n) || 756 (curr_peer->rx_pkt >= 757 tdls_vdev_obj->threshold_config.idle_packet_n)) { 758 /* this tdls link got back to normal, so keep it */ 759 tdls_debug("tdls link to " QDF_MAC_ADDR_FMT 760 " back to normal, will stay", 761 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes)); 762 } else { 763 /* this tdls link needs to get torn down */ 764 tdls_notice("trigger tdls link to "QDF_MAC_ADDR_FMT" down", 765 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes)); 766 tdls_indicate_teardown(tdls_vdev_obj, 767 curr_peer, 768 TDLS_TEARDOWN_PEER_UNSPEC_REASON); 769 } 770 771 return; 772 } 773 774 void tdls_ct_idle_handler(void *user_data) 775 { 776 struct wlan_objmgr_vdev *vdev; 777 struct tdls_conn_info *tdls_info; 778 struct tdls_soc_priv_obj *tdls_soc_obj; 779 uint32_t idx; 780 781 tdls_info = (struct tdls_conn_info *)user_data; 782 if (!tdls_info) 783 return; 784 785 idx = tdls_info->index; 786 if (idx == INVALID_TDLS_PEER_INDEX || idx >= WLAN_TDLS_STA_MAX_NUM) { 787 tdls_debug("invalid peer index %d" QDF_MAC_ADDR_FMT, idx, 788 QDF_MAC_ADDR_REF(tdls_info->peer_mac.bytes)); 789 return; 790 } 791 792 tdls_soc_obj = qdf_container_of(tdls_info, struct tdls_soc_priv_obj, 793 tdls_conn_info[idx]); 794 795 vdev = tdls_get_vdev(tdls_soc_obj->soc, WLAN_TDLS_NB_ID); 796 if (!vdev) { 797 tdls_err("Unable to fetch the vdev"); 798 return; 799 } 800 801 tdls_ct_process_idle_handler(vdev, tdls_info); 802 wlan_objmgr_vdev_release_ref(vdev, 803 WLAN_TDLS_NB_ID); 804 } 805 806 /** 807 * tdls_ct_process_idle_and_discovery() - process the traffic data 808 * @curr_peer: tdls peer needs to be examined 809 * @tdls_vdev_obj: tdls vdev object 810 * @tdls_soc_obj: tdls soc object 811 * 812 * Function to check the peer traffic data in idle link and tdls 813 * discovering link 814 * 815 * Return: None 816 */ 817 static void 818 tdls_ct_process_idle_and_discovery(struct tdls_peer *curr_peer, 819 struct tdls_vdev_priv_obj *tdls_vdev_obj, 820 struct tdls_soc_priv_obj *tdls_soc_obj) 821 { 822 uint16_t valid_peers; 823 824 valid_peers = tdls_soc_obj->connected_peer_count; 825 826 if ((curr_peer->tx_pkt + curr_peer->rx_pkt) >= 827 tdls_vdev_obj->threshold_config.tx_packet_n) { 828 if (WLAN_TDLS_STA_MAX_NUM > valid_peers) { 829 tdls_notice("Tput trigger TDLS pre-setup"); 830 tdls_vdev_obj->curr_candidate = curr_peer; 831 tdls_implicit_send_discovery_request(tdls_vdev_obj); 832 } else { 833 tdls_notice("Maximum peers connected already! %d", 834 valid_peers); 835 } 836 } 837 } 838 839 /** 840 * tdls_ct_process_connected_link() - process the traffic 841 * @curr_peer: tdls peer needs to be examined 842 * @tdls_vdev: tdls vdev 843 * @tdls_soc: tdls soc context 844 * 845 * Function to check the peer traffic data in active STA 846 * session 847 * 848 * Return: None 849 */ 850 static void tdls_ct_process_connected_link( 851 struct tdls_peer *curr_peer, 852 struct tdls_vdev_priv_obj *tdls_vdev, 853 struct tdls_soc_priv_obj *tdls_soc) 854 { 855 /* Don't trigger low rssi tear down here since FW will do it */ 856 /* Only teardown based on non zero idle packet threshold, to address 857 * a use case where this threshold does not get consider for TEAR DOWN 858 */ 859 if ((0 != tdls_vdev->threshold_config.idle_packet_n) && 860 ((curr_peer->tx_pkt < 861 tdls_vdev->threshold_config.idle_packet_n) && 862 (curr_peer->rx_pkt < 863 tdls_vdev->threshold_config.idle_packet_n))) { 864 if (!curr_peer->is_peer_idle_timer_initialised) { 865 struct tdls_conn_info *tdls_info; 866 tdls_info = tdls_get_conn_info(tdls_soc, 867 &curr_peer->peer_mac); 868 qdf_mc_timer_init(&curr_peer->peer_idle_timer, 869 QDF_TIMER_TYPE_SW, 870 tdls_ct_idle_handler, 871 (void *)tdls_info); 872 curr_peer->is_peer_idle_timer_initialised = true; 873 } 874 if (QDF_TIMER_STATE_RUNNING != 875 curr_peer->peer_idle_timer.state) { 876 tdls_warn("Tx/Rx Idle timer start: " 877 QDF_MAC_ADDR_FMT "!", 878 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes)); 879 tdls_timer_restart(tdls_vdev->vdev, 880 &curr_peer->peer_idle_timer, 881 tdls_vdev->threshold_config.idle_timeout_t); 882 } 883 } else if (QDF_TIMER_STATE_RUNNING == 884 curr_peer->peer_idle_timer.state) { 885 tdls_warn("Tx/Rx Idle timer stop: " QDF_MAC_ADDR_FMT "!", 886 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes)); 887 qdf_mc_timer_stop(&curr_peer->peer_idle_timer); 888 } 889 } 890 891 /** 892 * tdls_ct_process_cap_supported() - process TDLS supported peer. 893 * @curr_peer: tdls peer needs to be examined 894 * @tdls_vdev: tdls vdev context 895 * @tdls_soc_obj: tdls soc context 896 * 897 * Function to check the peer traffic data for tdls supported peer 898 * 899 * Return: None 900 */ 901 static void tdls_ct_process_cap_supported(struct tdls_peer *curr_peer, 902 struct tdls_vdev_priv_obj *tdls_vdev, 903 struct tdls_soc_priv_obj *tdls_soc_obj) 904 { 905 if (curr_peer->rx_pkt || curr_peer->tx_pkt) 906 tdls_debug(QDF_MAC_ADDR_FMT "link_status %d tdls_support %d tx %d rx %d rssi %d vdev %d", 907 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes), 908 curr_peer->link_status, curr_peer->tdls_support, 909 curr_peer->tx_pkt, curr_peer->rx_pkt, 910 curr_peer->rssi, wlan_vdev_get_id(tdls_vdev->vdev)); 911 912 switch (curr_peer->link_status) { 913 case TDLS_LINK_IDLE: 914 case TDLS_LINK_DISCOVERING: 915 if (TDLS_IS_EXTERNAL_CONTROL_ENABLED( 916 tdls_soc_obj->tdls_configs.tdls_feature_flags) && 917 (!curr_peer->is_forced_peer)) 918 break; 919 tdls_ct_process_idle_and_discovery(curr_peer, tdls_vdev, 920 tdls_soc_obj); 921 break; 922 case TDLS_LINK_CONNECTED: 923 tdls_ct_process_connected_link(curr_peer, tdls_vdev, 924 tdls_soc_obj); 925 break; 926 default: 927 break; 928 } 929 } 930 931 /** 932 * tdls_ct_process_cap_unknown() - process unknown peer 933 * @curr_peer: tdls peer needs to be examined 934 * @tdls_vdev: tdls vdev object 935 * @tdls_soc: tdls soc object 936 * 937 * Function check the peer traffic data , when tdls capability is unknown 938 * 939 * Return: None 940 */ 941 static void tdls_ct_process_cap_unknown(struct tdls_peer *curr_peer, 942 struct tdls_vdev_priv_obj *tdls_vdev, 943 struct tdls_soc_priv_obj *tdls_soc) 944 { 945 if (TDLS_IS_EXTERNAL_CONTROL_ENABLED( 946 tdls_soc->tdls_configs.tdls_feature_flags) && 947 (!curr_peer->is_forced_peer)) 948 return; 949 950 if (curr_peer->rx_pkt || curr_peer->tx_pkt) 951 tdls_debug(QDF_MAC_ADDR_FMT "link_status %d tdls_support %d tx %d rx %d vdev %d", 952 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes), 953 curr_peer->link_status, curr_peer->tdls_support, 954 curr_peer->tx_pkt, curr_peer->rx_pkt, 955 wlan_vdev_get_id(tdls_vdev->vdev)); 956 957 if (!TDLS_IS_LINK_CONNECTED(curr_peer) && 958 ((curr_peer->tx_pkt + curr_peer->rx_pkt) >= 959 tdls_vdev->threshold_config.tx_packet_n)) { 960 /* Ignore discovery attempt if External Control is enabled, that 961 * is, peer is forced. In that case, continue discovery attempt 962 * regardless attempt count 963 */ 964 tdls_debug("TDLS UNKNOWN pre discover "); 965 if (curr_peer->is_forced_peer || 966 curr_peer->discovery_attempt++ < 967 tdls_vdev->threshold_config.discovery_tries_n) { 968 tdls_debug("TDLS UNKNOWN discover "); 969 tdls_vdev->curr_candidate = curr_peer; 970 tdls_implicit_send_discovery_request(tdls_vdev); 971 } else { 972 if (curr_peer->link_status != TDLS_LINK_CONNECTING) { 973 curr_peer->tdls_support = 974 TDLS_CAP_NOT_SUPPORTED; 975 tdls_set_peer_link_status( 976 curr_peer, 977 TDLS_LINK_IDLE, 978 TDLS_LINK_NOT_SUPPORTED); 979 } 980 } 981 } 982 } 983 984 /** 985 * tdls_ct_process_peers() - process the peer 986 * @curr_peer: tdls peer needs to be examined 987 * @tdls_vdev_obj: tdls vdev object 988 * @tdls_soc_obj: tdls soc object 989 * 990 * This function check the peer capability and process the metadata from 991 * the peer 992 * 993 * Return: None 994 */ 995 static void tdls_ct_process_peers(struct tdls_peer *curr_peer, 996 struct tdls_vdev_priv_obj *tdls_vdev_obj, 997 struct tdls_soc_priv_obj *tdls_soc_obj) 998 { 999 switch (curr_peer->tdls_support) { 1000 case TDLS_CAP_SUPPORTED: 1001 tdls_ct_process_cap_supported(curr_peer, tdls_vdev_obj, 1002 tdls_soc_obj); 1003 break; 1004 1005 case TDLS_CAP_UNKNOWN: 1006 tdls_ct_process_cap_unknown(curr_peer, tdls_vdev_obj, 1007 tdls_soc_obj); 1008 break; 1009 default: 1010 break; 1011 } 1012 1013 } 1014 1015 static void tdls_ct_process_handler(struct wlan_objmgr_vdev *vdev) 1016 { 1017 int i; 1018 qdf_list_t *head; 1019 qdf_list_node_t *list_node; 1020 struct tdls_peer *curr_peer; 1021 QDF_STATUS status; 1022 struct tdls_vdev_priv_obj *tdls_vdev_obj; 1023 struct tdls_soc_priv_obj *tdls_soc_obj; 1024 1025 if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev, &tdls_vdev_obj, 1026 &tdls_soc_obj)) 1027 return; 1028 1029 /* If any concurrency is detected */ 1030 if (!tdls_soc_obj->enable_tdls_connection_tracker) { 1031 tdls_notice("Connection tracker is disabled"); 1032 return; 1033 } 1034 1035 /* Update tx rx traffic sample in tdls data structures */ 1036 tdls_ct_sampling_tx_rx(tdls_vdev_obj, tdls_soc_obj); 1037 1038 for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) { 1039 head = &tdls_vdev_obj->peer_list[i]; 1040 status = qdf_list_peek_front(head, &list_node); 1041 while (QDF_IS_STATUS_SUCCESS(status)) { 1042 curr_peer = qdf_container_of(list_node, 1043 struct tdls_peer, node); 1044 tdls_ct_process_peers(curr_peer, tdls_vdev_obj, 1045 tdls_soc_obj); 1046 curr_peer->tx_pkt = 0; 1047 curr_peer->rx_pkt = 0; 1048 status = qdf_list_peek_next(head, 1049 list_node, &list_node); 1050 } 1051 } 1052 1053 tdls_timer_restart(tdls_vdev_obj->vdev, 1054 &tdls_vdev_obj->peer_update_timer, 1055 tdls_vdev_obj->threshold_config.tx_period_t); 1056 1057 } 1058 1059 void tdls_ct_handler(void *user_data) 1060 { 1061 struct wlan_objmgr_vdev *vdev; 1062 struct wlan_objmgr_vdev *link_vdev; 1063 1064 if (!user_data) 1065 return; 1066 1067 vdev = (struct wlan_objmgr_vdev *)user_data; 1068 if (!vdev) 1069 return; 1070 1071 link_vdev = tdls_mlo_get_tdls_link_vdev(vdev); 1072 if (link_vdev) { 1073 if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_TDLS_NB_ID) == 1074 QDF_STATUS_SUCCESS) { 1075 tdls_ct_process_handler(link_vdev); 1076 wlan_objmgr_vdev_release_ref(link_vdev, 1077 WLAN_TDLS_NB_ID); 1078 } 1079 } else { 1080 tdls_ct_process_handler(vdev); 1081 } 1082 } 1083 1084 int tdls_set_tdls_offchannel(struct tdls_soc_priv_obj *tdls_soc, 1085 int offchannel) 1086 { 1087 uint32_t tdls_feature_flags; 1088 1089 tdls_feature_flags = tdls_soc->tdls_configs.tdls_feature_flags; 1090 1091 if (TDLS_IS_OFF_CHANNEL_ENABLED(tdls_feature_flags) && 1092 (TDLS_SUPPORT_EXP_TRIG_ONLY == tdls_soc->tdls_current_mode || 1093 TDLS_SUPPORT_IMP_MODE == tdls_soc->tdls_current_mode || 1094 TDLS_SUPPORT_EXT_CONTROL == tdls_soc->tdls_current_mode)) { 1095 if (offchannel < TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN || 1096 offchannel > TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX) { 1097 tdls_err("Invalid tdls off channel %u", offchannel); 1098 return -EINVAL; 1099 } 1100 } else { 1101 tdls_err("Either TDLS or TDLS Off-channel is not enabled"); 1102 return -ENOTSUPP; 1103 } 1104 tdls_notice("change tdls off channel from %d to %d", 1105 tdls_soc->tdls_off_channel, offchannel); 1106 tdls_soc->tdls_off_channel = offchannel; 1107 return 0; 1108 } 1109 1110 int tdls_set_tdls_secoffchanneloffset(struct tdls_soc_priv_obj *tdls_soc, 1111 int offchanoffset) 1112 { 1113 uint32_t tdls_feature_flags; 1114 1115 tdls_feature_flags = tdls_soc->tdls_configs.tdls_feature_flags; 1116 1117 if (!TDLS_IS_OFF_CHANNEL_ENABLED(tdls_feature_flags) || 1118 TDLS_SUPPORT_SUSPENDED >= tdls_soc->tdls_current_mode) { 1119 tdls_err("Either TDLS or TDLS Off-channel is not enabled"); 1120 return -ENOTSUPP; 1121 } 1122 1123 tdls_soc->tdls_channel_offset = BW_INVALID; 1124 1125 switch (offchanoffset) { 1126 case TDLS_SEC_OFFCHAN_OFFSET_0: 1127 tdls_soc->tdls_channel_offset = BW20; 1128 break; 1129 case TDLS_SEC_OFFCHAN_OFFSET_40PLUS: 1130 tdls_soc->tdls_channel_offset = BW40_HIGH_PRIMARY; 1131 break; 1132 case TDLS_SEC_OFFCHAN_OFFSET_40MINUS: 1133 tdls_soc->tdls_channel_offset = BW40_LOW_PRIMARY; 1134 break; 1135 case TDLS_SEC_OFFCHAN_OFFSET_80: 1136 tdls_soc->tdls_channel_offset = BW80; 1137 break; 1138 case TDLS_SEC_OFFCHAN_OFFSET_160: 1139 tdls_soc->tdls_channel_offset = BWALL; 1140 break; 1141 default: 1142 tdls_err("Invalid tdls secondary off channel offset %d", 1143 offchanoffset); 1144 return -EINVAL; 1145 } /* end switch */ 1146 1147 tdls_notice("change tdls secondary off channel offset to 0x%x", 1148 tdls_soc->tdls_channel_offset); 1149 return 0; 1150 } 1151 1152 static inline void 1153 tdls_update_opclass(struct wlan_objmgr_psoc *psoc, 1154 struct tdls_channel_switch_params *params) 1155 { 1156 params->oper_class = tdls_find_opclass(psoc, params->tdls_off_ch, 1157 params->tdls_off_ch_bw_offset); 1158 if (params->oper_class) 1159 return; 1160 1161 if (params->tdls_off_ch_bw_offset == BW40_HIGH_PRIMARY) 1162 params->oper_class = tdls_find_opclass(psoc, 1163 params->tdls_off_ch, 1164 BW40_LOW_PRIMARY); 1165 else if (params->tdls_off_ch_bw_offset == BW40_LOW_PRIMARY) 1166 params->oper_class = tdls_find_opclass(psoc, 1167 params->tdls_off_ch, 1168 BW40_HIGH_PRIMARY); 1169 } 1170 1171 #ifdef WLAN_FEATURE_TDLS_CONCURRENCIES 1172 static inline QDF_STATUS 1173 tdls_update_peer_off_channel_list(struct wlan_objmgr_pdev *pdev, 1174 struct tdls_soc_priv_obj *tdls_soc, 1175 struct wlan_objmgr_vdev *vdev, 1176 struct tdls_peer *peer, 1177 struct tdls_channel_switch_params *params) 1178 { 1179 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 1180 struct tdls_peer_update_state *peer_info; 1181 struct tdls_ch_params *off_channels = params->allowed_off_channels; 1182 uint16_t i; 1183 qdf_freq_t freq, peer_freq; 1184 1185 if (!wlan_psoc_nif_fw_ext2_cap_get(psoc, 1186 WLAN_TDLS_CONCURRENCIES_SUPPORT)) { 1187 tdls_debug("TDLS Concurrencies FW cap is not supported"); 1188 return QDF_STATUS_SUCCESS; 1189 } 1190 1191 if (!policy_mgr_get_allowed_tdls_offchannel_freq(psoc, vdev, &freq)) { 1192 tdls_debug("off channel not allowed for current concurrency"); 1193 return QDF_STATUS_E_NOSUPPORT; 1194 } 1195 1196 /* 1197 * Overwrite the preferred off channel freq in case of concurrency 1198 */ 1199 if (freq) { 1200 params->tdls_off_ch = wlan_reg_freq_to_chan(pdev, freq); 1201 params->tdls_off_chan_freq = freq; 1202 1203 /* 1204 * tdls_off_ch_bw_offset is already filled in the caller 1205 */ 1206 if (tdls_soc->tdls_off_channel && 1207 tdls_soc->tdls_channel_offset != BW_INVALID) { 1208 tdls_update_opclass(psoc, params); 1209 } else if (peer->off_channel_capable && 1210 peer->pref_off_chan_freq) { 1211 params->oper_class = 1212 tdls_get_opclass_from_bandwidth( 1213 vdev, params->tdls_off_chan_freq, 1214 peer->pref_off_chan_width, 1215 ¶ms->tdls_off_ch_bw_offset); 1216 } 1217 } 1218 1219 peer_info = qdf_mem_malloc(sizeof(*peer_info)); 1220 if (!peer_info) 1221 return QDF_STATUS_E_NOMEM; 1222 1223 tdls_extract_peer_state_param(peer_info, peer); 1224 params->num_off_channels = 0; 1225 1226 /* 1227 * If TDLS concurrency is supported and freq == 0, 1228 * then allow all the 5GHz and 6GHz peer supported frequencies for 1229 * off-channel operation. If particular frequency is provided based on 1230 * concurrency combination then only allow that channel for off-channel. 1231 */ 1232 for (i = 0; i < peer_info->peer_cap.peer_chanlen; i++) { 1233 peer_freq = peer_info->peer_cap.peer_chan[i].ch_freq; 1234 if ((!freq || freq == peer_freq) && 1235 (!wlan_reg_is_24ghz_ch_freq(peer_freq) || 1236 (wlan_reg_is_6ghz_chan_freq(peer_freq) && 1237 tdls_is_6g_freq_allowed(vdev, peer_freq)))) { 1238 off_channels[params->num_off_channels] = 1239 peer_info->peer_cap.peer_chan[i]; 1240 tdls_debug("allowd_chan:%d idx:%d", 1241 off_channels[params->num_off_channels].ch_freq, 1242 params->num_off_channels); 1243 params->num_off_channels++; 1244 } 1245 } 1246 tdls_debug("Num allowed off channels:%d freq:%u", 1247 params->num_off_channels, freq); 1248 qdf_mem_free(peer_info); 1249 1250 return QDF_STATUS_SUCCESS; 1251 } 1252 #else 1253 static inline QDF_STATUS 1254 tdls_update_peer_off_channel_list(struct wlan_objmgr_pdev *pdev, 1255 struct tdls_soc_priv_obj *tdls_soc, 1256 struct wlan_objmgr_vdev *vdev, 1257 struct tdls_peer *peer, 1258 struct tdls_channel_switch_params *params) 1259 { 1260 return QDF_STATUS_SUCCESS; 1261 } 1262 #endif 1263 1264 int tdls_set_tdls_offchannelmode(struct wlan_objmgr_vdev *vdev, 1265 int offchanmode) 1266 { 1267 struct tdls_peer *conn_peer = NULL; 1268 struct tdls_channel_switch_params *chan_switch_params; 1269 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1270 int ret_value = 0; 1271 struct tdls_vdev_priv_obj *tdls_vdev; 1272 struct tdls_soc_priv_obj *tdls_soc; 1273 uint32_t tdls_feature_flags; 1274 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 1275 1276 status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc); 1277 1278 if (status != QDF_STATUS_SUCCESS) 1279 return -EINVAL; 1280 1281 1282 if (offchanmode < ENABLE_CHANSWITCH || 1283 offchanmode > DISABLE_ACTIVE_CHANSWITCH) { 1284 tdls_err("Invalid tdls off channel mode %d", offchanmode); 1285 return -EINVAL; 1286 } 1287 1288 if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS) { 1289 tdls_err("tdls off channel req in not associated state %d", 1290 offchanmode); 1291 return -EPERM; 1292 } 1293 1294 tdls_feature_flags = tdls_soc->tdls_configs.tdls_feature_flags; 1295 if (!TDLS_IS_OFF_CHANNEL_ENABLED(tdls_feature_flags) || 1296 TDLS_SUPPORT_SUSPENDED >= tdls_soc->tdls_current_mode) { 1297 tdls_err("Either TDLS or TDLS Off-channel is not enabled"); 1298 return -ENOTSUPP; 1299 } 1300 1301 conn_peer = tdls_find_first_connected_peer(tdls_vdev); 1302 if (!conn_peer) { 1303 tdls_debug("No TDLS Connected Peer"); 1304 return -EPERM; 1305 } 1306 1307 tdls_notice("TDLS Channel Switch in off_chan_mode=%d tdls_off_channel %d offchanoffset %d", 1308 offchanmode, tdls_soc->tdls_off_channel, 1309 tdls_soc->tdls_channel_offset); 1310 1311 chan_switch_params = qdf_mem_malloc(sizeof(*chan_switch_params)); 1312 if (!chan_switch_params) 1313 return -ENOMEM; 1314 1315 switch (offchanmode) { 1316 case ENABLE_CHANSWITCH: 1317 if (tdls_soc->tdls_off_channel && 1318 tdls_soc->tdls_channel_offset != BW_INVALID) { 1319 chan_switch_params->tdls_off_ch = 1320 tdls_soc->tdls_off_channel; 1321 chan_switch_params->tdls_off_ch_bw_offset = 1322 tdls_soc->tdls_channel_offset; 1323 tdls_update_opclass(wlan_pdev_get_psoc(pdev), 1324 chan_switch_params); 1325 } else if (conn_peer->off_channel_capable && 1326 conn_peer->pref_off_chan_freq) { 1327 chan_switch_params->tdls_off_ch = 1328 wlan_reg_freq_to_chan(pdev, 1329 conn_peer->pref_off_chan_freq); 1330 chan_switch_params->oper_class = 1331 tdls_get_opclass_from_bandwidth( 1332 vdev, conn_peer->pref_off_chan_freq, 1333 conn_peer->pref_off_chan_width, 1334 &chan_switch_params->tdls_off_ch_bw_offset); 1335 chan_switch_params->tdls_off_chan_freq = 1336 conn_peer->pref_off_chan_freq; 1337 } else { 1338 tdls_err("TDLS off-channel parameters are not set yet!!!"); 1339 qdf_mem_free(chan_switch_params); 1340 return -EINVAL; 1341 1342 } 1343 1344 /* 1345 * Retain the connected peer preferred off-channel frequency 1346 * and opclass that was calculated during update peer caps and 1347 * don't overwrite it based on concurrency in 1348 * tdls_update_peer_off_channel_list(). 1349 */ 1350 conn_peer->pref_off_chan_freq = 1351 wlan_reg_chan_opclass_to_freq( 1352 chan_switch_params->tdls_off_ch, 1353 chan_switch_params->oper_class, false); 1354 conn_peer->op_class_for_pref_off_chan = 1355 chan_switch_params->oper_class; 1356 1357 /* 1358 * Don't enable TDLS off channel if concurrency is not allowed 1359 */ 1360 status = tdls_update_peer_off_channel_list(pdev, tdls_soc, vdev, 1361 conn_peer, 1362 chan_switch_params); 1363 if (QDF_IS_STATUS_ERROR(status)) { 1364 qdf_mem_free(chan_switch_params); 1365 return -EINVAL; 1366 } 1367 1368 break; 1369 case DISABLE_CHANSWITCH: 1370 case DISABLE_ACTIVE_CHANSWITCH: 1371 chan_switch_params->tdls_off_ch = 0; 1372 chan_switch_params->tdls_off_ch_bw_offset = 0; 1373 chan_switch_params->oper_class = 0; 1374 break; 1375 default: 1376 tdls_err("Incorrect Parameters mode: %d tdls_off_channel: %d offchanoffset: %d", 1377 offchanmode, tdls_soc->tdls_off_channel, 1378 tdls_soc->tdls_channel_offset); 1379 qdf_mem_free(chan_switch_params); 1380 return -EINVAL; 1381 } /* end switch */ 1382 1383 chan_switch_params->vdev_id = tdls_vdev->session_id; 1384 chan_switch_params->tdls_sw_mode = offchanmode; 1385 chan_switch_params->is_responder = conn_peer->is_responder; 1386 qdf_mem_copy(&chan_switch_params->peer_mac_addr, 1387 &conn_peer->peer_mac.bytes, QDF_MAC_ADDR_SIZE); 1388 tdls_notice("Peer " QDF_MAC_ADDR_FMT " vdevId: %d, off channel: %d, offset: %d, num_allowed_off_chan:%d mode: %d, is_responder: %d", 1389 QDF_MAC_ADDR_REF(chan_switch_params->peer_mac_addr), 1390 chan_switch_params->vdev_id, 1391 chan_switch_params->tdls_off_ch, 1392 chan_switch_params->tdls_off_ch_bw_offset, 1393 chan_switch_params->num_off_channels, 1394 chan_switch_params->tdls_sw_mode, 1395 chan_switch_params->is_responder); 1396 1397 status = tgt_tdls_set_offchan_mode(tdls_soc->soc, chan_switch_params); 1398 if (QDF_IS_STATUS_ERROR(status)) { 1399 qdf_mem_free(chan_switch_params); 1400 tdls_err("Failed to send channel switch request to wmi"); 1401 return -EINVAL; 1402 } 1403 1404 tdls_soc->tdls_fw_off_chan_mode = offchanmode; 1405 qdf_mem_free(chan_switch_params); 1406 1407 return ret_value; 1408 } 1409 1410 static QDF_STATUS tdls_delete_all_tdls_peers_flush_cb(struct scheduler_msg *msg) 1411 { 1412 if (msg && msg->bodyptr) { 1413 qdf_mem_free(msg->bodyptr); 1414 msg->bodyptr = NULL; 1415 } 1416 1417 return QDF_STATUS_SUCCESS; 1418 } 1419 /** 1420 * tdls_delete_all_tdls_peers(): send request to delete tdls peers 1421 * @vdev: vdev object 1422 * @tdls_soc: tdls soc object 1423 * 1424 * This function sends request to lim to delete tdls peers 1425 * 1426 * Return: QDF_STATUS 1427 */ 1428 QDF_STATUS tdls_delete_all_tdls_peers(struct wlan_objmgr_vdev *vdev, 1429 struct tdls_soc_priv_obj *tdls_soc) 1430 { 1431 struct wlan_objmgr_peer *peer; 1432 struct tdls_del_all_tdls_peers *del_msg; 1433 struct scheduler_msg msg = {0}; 1434 QDF_STATUS status; 1435 1436 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_SB_ID); 1437 if (!peer) { 1438 tdls_err("bss peer is null"); 1439 return QDF_STATUS_E_FAILURE; 1440 } 1441 1442 del_msg = qdf_mem_malloc(sizeof(*del_msg)); 1443 if (!del_msg) { 1444 wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID); 1445 return QDF_STATUS_E_FAILURE; 1446 } 1447 1448 qdf_mem_copy(del_msg->bssid.bytes, 1449 wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE); 1450 1451 wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID); 1452 1453 del_msg->msg_type = tdls_soc->tdls_del_all_peers; 1454 del_msg->msg_len = (uint16_t) sizeof(*del_msg); 1455 1456 /* Send the request to PE. */ 1457 qdf_mem_zero(&msg, sizeof(msg)); 1458 1459 tdls_debug("sending delete all peers req to PE "); 1460 1461 msg.type = del_msg->msg_type; 1462 msg.bodyptr = del_msg; 1463 msg.flush_callback = tdls_delete_all_tdls_peers_flush_cb; 1464 1465 status = scheduler_post_message(QDF_MODULE_ID_TDLS, 1466 QDF_MODULE_ID_PE, 1467 QDF_MODULE_ID_PE, &msg); 1468 if (QDF_IS_STATUS_ERROR(status)) { 1469 tdls_err("post delete all peer req failed, status %d", status); 1470 qdf_mem_free(del_msg); 1471 } 1472 1473 return status; 1474 } 1475 1476 void tdls_disable_offchan_and_teardown_links( 1477 struct wlan_objmgr_vdev *vdev) 1478 { 1479 uint16_t connected_tdls_peers = 0; 1480 uint8_t staidx; 1481 struct tdls_peer *curr_peer = NULL; 1482 struct tdls_vdev_priv_obj *tdls_vdev; 1483 struct tdls_soc_priv_obj *tdls_soc; 1484 QDF_STATUS status; 1485 uint8_t vdev_id; 1486 bool tdls_in_progress = false; 1487 bool is_mlo_vdev; 1488 1489 is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev); 1490 if (is_mlo_vdev) { 1491 tdls_debug("try to set vdev %d to unforce", 1492 wlan_vdev_get_id(vdev)); 1493 tdls_set_link_unforce(vdev); 1494 } 1495 1496 status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc); 1497 if (QDF_STATUS_SUCCESS != status) { 1498 tdls_err("tdls objects are NULL "); 1499 return; 1500 } 1501 1502 if (TDLS_SUPPORT_SUSPENDED >= tdls_soc->tdls_current_mode) { 1503 tdls_debug("TDLS mode %d is disabled OR not suspended now", 1504 tdls_soc->tdls_current_mode); 1505 return; 1506 } 1507 1508 connected_tdls_peers = tdls_soc->connected_peer_count; 1509 if (tdls_is_progress(tdls_vdev, NULL, 0)) 1510 tdls_in_progress = true; 1511 1512 if (!(connected_tdls_peers || tdls_in_progress)) { 1513 vdev_id = vdev->vdev_objmgr.vdev_id; 1514 tdls_debug("No TDLS connected/progress peers to delete Disable tdls for vdev id %d, " 1515 "FW as second interface is coming up", vdev_id); 1516 tdls_send_update_to_fw(tdls_vdev, tdls_soc, true, true, false, 1517 vdev_id); 1518 return; 1519 } 1520 1521 /* TDLS is not supported in case of concurrency. 1522 * Disable TDLS Offchannel in FW to avoid more 1523 * than two concurrent channels and generate TDLS 1524 * teardown indication to supplicant. 1525 * Below function Finds the first connected peer and 1526 * disables TDLS offchannel for that peer. 1527 * FW enables TDLS offchannel only when there is 1528 * one TDLS peer. When there are more than one TDLS peer, 1529 * there will not be TDLS offchannel in FW. 1530 * So to avoid sending multiple request to FW, for now, 1531 * just invoke offchannel mode functions only once 1532 */ 1533 tdls_set_tdls_offchannel(tdls_soc, 1534 tdls_soc->tdls_configs.tdls_pre_off_chan_num); 1535 tdls_set_tdls_secoffchanneloffset(tdls_soc, 1536 TDLS_SEC_OFFCHAN_OFFSET_40PLUS); 1537 tdls_set_tdls_offchannelmode(vdev, DISABLE_ACTIVE_CHANSWITCH); 1538 1539 /* Send Msg to PE for deleting all the TDLS peers */ 1540 tdls_delete_all_tdls_peers(vdev, tdls_soc); 1541 1542 for (staidx = 0; staidx < tdls_soc->max_num_tdls_sta; staidx++) { 1543 if (!tdls_soc->tdls_conn_info[staidx].valid_entry) 1544 continue; 1545 1546 curr_peer = tdls_find_all_peer(tdls_soc, 1547 tdls_soc->tdls_conn_info[staidx].peer_mac.bytes); 1548 if (!curr_peer) 1549 continue; 1550 1551 tdls_notice("indicate TDLS teardown "QDF_MAC_ADDR_FMT, 1552 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes)); 1553 1554 /* Indicate teardown to supplicant */ 1555 tdls_indicate_teardown(tdls_vdev, curr_peer, 1556 TDLS_TEARDOWN_PEER_UNSPEC_REASON); 1557 1558 /* 1559 * Del Sta happened already as part of tdls_delete_all_tdls_peers 1560 * Hence clear tdls vdev data structure. 1561 */ 1562 tdls_reset_peer(tdls_vdev, curr_peer->peer_mac.bytes); 1563 1564 tdls_decrement_peer_count(vdev, tdls_soc); 1565 tdls_soc->tdls_conn_info[staidx].valid_entry = false; 1566 tdls_soc->tdls_conn_info[staidx].session_id = 255; 1567 tdls_soc->tdls_conn_info[staidx].index = 1568 INVALID_TDLS_PEER_INDEX; 1569 1570 qdf_mem_zero(&tdls_soc->tdls_conn_info[staidx].peer_mac, 1571 sizeof(struct qdf_mac_addr)); 1572 } 1573 } 1574 1575 void tdls_teardown_connections(struct tdls_link_teardown *tdls_teardown) 1576 { 1577 struct tdls_vdev_priv_obj *tdls_vdev_obj; 1578 struct wlan_objmgr_vdev *tdls_vdev; 1579 1580 /* Get the tdls specific vdev and clear the links */ 1581 tdls_vdev = tdls_get_vdev(tdls_teardown->psoc, WLAN_TDLS_SB_ID); 1582 if (!tdls_vdev) { 1583 tdls_err("Unable get the vdev"); 1584 goto fail_vdev; 1585 } 1586 1587 tdls_vdev_obj = wlan_vdev_get_tdls_vdev_obj(tdls_vdev); 1588 if (!tdls_vdev_obj) { 1589 tdls_err("vdev priv is NULL"); 1590 goto fail_tdls_vdev; 1591 } 1592 1593 tdls_debug("tdls teardown connections"); 1594 wlan_vdev_mlme_feat_ext2_cap_clear(tdls_vdev, 1595 WLAN_VDEV_FEXT2_MLO_STA_TDLS); 1596 1597 tdls_disable_offchan_and_teardown_links(tdls_vdev); 1598 qdf_event_set(&tdls_vdev_obj->tdls_teardown_comp); 1599 fail_tdls_vdev: 1600 wlan_objmgr_vdev_release_ref(tdls_vdev, WLAN_TDLS_SB_ID); 1601 fail_vdev: 1602 wlan_objmgr_psoc_release_ref(tdls_teardown->psoc, WLAN_TDLS_SB_ID); 1603 qdf_mem_free(tdls_teardown); 1604 } 1605