1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2024 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_hdd_nan_datapath.c 22 * 23 * WLAN Host Device Driver nan datapath API implementation 24 */ 25 #include <wlan_hdd_includes.h> 26 #include <linux/if.h> 27 #include <linux/netdevice.h> 28 #include <linux/skbuff.h> 29 #include <linux/etherdevice.h> 30 #include "wlan_hdd_includes.h" 31 #include "wlan_hdd_p2p.h" 32 #include "osif_sync.h" 33 #include "wma_api.h" 34 #include "wlan_hdd_assoc.h" 35 #include "sme_nan_datapath.h" 36 #include "wlan_hdd_object_manager.h" 37 #include <qca_vendor.h> 38 #include "os_if_nan.h" 39 #include "wlan_nan_api.h" 40 #include "nan_public_structs.h" 41 #include "cfg_nan_api.h" 42 #include "wlan_mlme_ucfg_api.h" 43 #include "qdf_util.h" 44 #include "qdf_net_if.h" 45 #include <cdp_txrx_misc.h> 46 #include "wlan_fwol_ucfg_api.h" 47 #include "wlan_dp_ucfg_api.h" 48 #include "wlan_hdd_sysfs.h" 49 #include "wlan_hdd_stats.h" 50 51 /** 52 * hdd_nan_datapath_target_config() - Configure NAN datapath features 53 * @hdd_ctx: Pointer to HDD context 54 * @tgt_cfg: Pointer to target device capability information 55 * 56 * NAN datapath functionality is enabled if it is enabled in 57 * .ini file and also supported on target device. 58 * 59 * Return: None 60 */ 61 void hdd_nan_datapath_target_config(struct hdd_context *hdd_ctx, 62 struct wma_tgt_cfg *tgt_cfg) 63 { 64 hdd_ctx->nan_datapath_enabled = 65 cfg_nan_get_datapath_enable(hdd_ctx->psoc) && 66 tgt_cfg->nan_datapath_enabled; 67 hdd_debug("NAN Datapath Enable: %d (Host: %d FW: %d)", 68 hdd_ctx->nan_datapath_enabled, 69 cfg_nan_get_datapath_enable(hdd_ctx->psoc), 70 tgt_cfg->nan_datapath_enabled); 71 } 72 73 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) 74 /** 75 * hdd_close_ndi_adapter() - close the adapter 76 * @hdd_ctx: pointer to HDD context 77 * @adapter: adapter context 78 * @value: true or false 79 * 80 * Returns: void 81 */ 82 static void hdd_close_ndi_adapter(struct hdd_context *hdd_ctx, 83 struct hdd_adapter *adapter, bool value) 84 { 85 } 86 #else 87 static void hdd_close_ndi_adapter(struct hdd_context *hdd_ctx, 88 struct hdd_adapter *adapter, bool value) 89 { 90 hdd_close_adapter(hdd_ctx, adapter, value); 91 } 92 #endif 93 94 /** 95 * hdd_close_ndi() - close NAN Data interface 96 * @adapter: adapter context 97 * 98 * Close the adapter if start BSS fails 99 * 100 * Returns: 0 on success, negative error code otherwise 101 */ 102 static int hdd_close_ndi(struct hdd_adapter *adapter) 103 { 104 int errno; 105 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 106 107 hdd_enter(); 108 109 /* check if the adapter is in NAN Data mode */ 110 if (QDF_NDI_MODE != adapter->device_mode) { 111 hdd_err("Interface is not in NDI mode"); 112 return -EINVAL; 113 } 114 wlan_hdd_netif_queue_control(adapter, 115 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, 116 WLAN_CONTROL_PATH); 117 118 hdd_cancel_ip_notifier_work(adapter); 119 hdd_adapter_deregister_fc(adapter); 120 121 errno = hdd_vdev_destroy(adapter->deflink); 122 if (errno) 123 hdd_err("failed to destroy vdev: %d", errno); 124 125 adapter->is_virtual_iface = true; 126 /* We are good to close the adapter */ 127 hdd_close_ndi_adapter(hdd_ctx, adapter, true); 128 129 hdd_exit(); 130 return 0; 131 } 132 133 /** 134 * hdd_is_ndp_allowed() - Indicates if NDP is allowed 135 * @hdd_ctx: hdd context 136 * 137 * NDP is not allowed with any other role active except STA. 138 * 139 * Return: true if allowed, false otherwise 140 */ 141 #ifdef NDP_SAP_CONCURRENCY_ENABLE 142 static bool hdd_is_ndp_allowed(struct hdd_context *hdd_ctx) 143 { 144 struct hdd_adapter *adapter, *next_adapter = NULL; 145 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_IS_NDP_ALLOWED; 146 struct wlan_hdd_link_info *link_info; 147 148 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, 149 dbgid) { 150 hdd_adapter_for_each_active_link_info(adapter, link_info) { 151 switch (adapter->device_mode) { 152 case QDF_P2P_GO_MODE: 153 if (test_bit(SOFTAP_BSS_STARTED, 154 &link_info->link_flags)) { 155 hdd_adapter_dev_put_debug(adapter, 156 dbgid); 157 if (next_adapter) 158 hdd_adapter_dev_put_debug( 159 next_adapter, 160 dbgid); 161 return false; 162 } 163 break; 164 case QDF_P2P_CLIENT_MODE: 165 if (hdd_cm_is_vdev_associated(link_info) || 166 hdd_cm_is_connecting(link_info)) { 167 hdd_adapter_dev_put_debug(adapter, 168 dbgid); 169 if (next_adapter) 170 hdd_adapter_dev_put_debug( 171 next_adapter, 172 dbgid); 173 return false; 174 } 175 break; 176 default: 177 break; 178 } 179 } 180 hdd_adapter_dev_put_debug(adapter, dbgid); 181 } 182 183 return true; 184 } 185 #else 186 static bool hdd_is_ndp_allowed(struct hdd_context *hdd_ctx) 187 { 188 struct hdd_adapter *adapter, *next_adapter = NULL; 189 wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_IS_NDP_ALLOWED; 190 struct wlan_hdd_link_info *link_info; 191 192 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, 193 dbgid) { 194 hdd_adapter_for_each_active_link_info(adapter, link_info) { 195 switch (adapter->device_mode) { 196 case QDF_P2P_GO_MODE: 197 case QDF_SAP_MODE: 198 if (test_bit(SOFTAP_BSS_STARTED, 199 &link_info->link_flags)) { 200 hdd_adapter_dev_put_debug(adapter, 201 dbgid); 202 if (next_adapter) 203 hdd_adapter_dev_put_debug( 204 next_adapter, 205 dbgid); 206 return false; 207 } 208 break; 209 case QDF_P2P_CLIENT_MODE: 210 if (hdd_cm_is_vdev_associated(link_info) || 211 hdd_cm_is_connecting(link_info)) { 212 hdd_adapter_dev_put_debug(adapter, 213 dbgid); 214 if (next_adapter) 215 hdd_adapter_dev_put_debug( 216 next_adapter, 217 dbgid); 218 return false; 219 } 220 break; 221 default: 222 break; 223 } 224 } 225 hdd_adapter_dev_put_debug(adapter, dbgid); 226 } 227 228 return true; 229 } 230 #endif /* NDP_SAP_CONCURRENCY_ENABLE */ 231 232 /** 233 * hdd_ndi_select_valid_freq() - Find the valid freq for NDI start 234 * @hdd_ctx: hdd context 235 * @freq: pointer to freq, give preference to 5745, 5220 and 2437 to keep the 236 * legacy behavior intact 237 * 238 * Unlike traditional device modes, where the higher application 239 * layer initiates connect / join / start, the NAN data 240 * interface does not have any such formal requests. The NDI 241 * create request is responsible for starting the BSS as well. 242 * Use the 5GHz Band NAN Social channel for BSS start if target 243 * supports it, since a 2.4GHz channel will require a DBS HW mode change 244 * first on a DBS 2x2 MAC target. Use a 2.4 GHz Band NAN Social channel 245 * if the target is not 5GHz capable. If both of these channels are 246 * not available, pick the next available channel. This would be used just to 247 * start the NDI. Actual channel for NDP data transfer would be negotiated with 248 * peer later. 249 * 250 * Return: SUCCESS if valid channel is obtained 251 */ 252 static QDF_STATUS hdd_ndi_select_valid_freq(struct hdd_context *hdd_ctx, 253 uint32_t *freq) 254 { 255 static const qdf_freq_t valid_freq[] = {NAN_SOCIAL_FREQ_5GHZ_UPPER_BAND, 256 NAN_SOCIAL_FREQ_5GHZ_LOWER_BAND, 257 NAN_SOCIAL_FREQ_2_4GHZ}; 258 uint8_t i; 259 struct regulatory_channel *cur_chan_list; 260 QDF_STATUS status; 261 262 for (i = 0; i < ARRAY_SIZE(valid_freq); i++) { 263 if (wlan_reg_is_freq_enabled(hdd_ctx->pdev, valid_freq[i], 264 REG_CURRENT_PWR_MODE)) { 265 *freq = valid_freq[i]; 266 return QDF_STATUS_SUCCESS; 267 } 268 } 269 270 cur_chan_list = qdf_mem_malloc(sizeof(*cur_chan_list) * 271 (NUM_CHANNELS + 2)); 272 if (!cur_chan_list) 273 return QDF_STATUS_E_NOMEM; 274 275 status = ucfg_reg_get_current_chan_list(hdd_ctx->pdev, cur_chan_list); 276 if (QDF_IS_STATUS_ERROR(status)) { 277 hdd_err_rl("Failed to get the current channel list"); 278 qdf_mem_free(cur_chan_list); 279 return QDF_STATUS_E_IO; 280 } 281 282 for (i = 0; i < NUM_CHANNELS; i++) { 283 /* 284 * current channel list includes all channels. Exclude 285 * disabled channels 286 */ 287 if (cur_chan_list[i].chan_flags & REGULATORY_CHAN_DISABLED || 288 cur_chan_list[i].chan_flags & REGULATORY_CHAN_RADAR) 289 continue; 290 /* 291 * do not include 6 GHz channels for now as NAN would need 292 * 2.4 GHz and 5 GHz channels for discovery. 293 * <TODO> Need to consider the 6GHz channels when there is a 294 * case where all 2GHz and 5GHz channels are disabled and 295 * only 6GHz channels are enabled 296 */ 297 if (wlan_reg_is_6ghz_chan_freq(cur_chan_list[i].center_freq)) 298 continue; 299 300 /* extracting first valid channel from regulatory list */ 301 if (wlan_reg_is_freq_enabled(hdd_ctx->pdev, 302 cur_chan_list[i].center_freq, 303 REG_CURRENT_PWR_MODE)) { 304 *freq = cur_chan_list[i].center_freq; 305 qdf_mem_free(cur_chan_list); 306 return QDF_STATUS_SUCCESS; 307 } 308 } 309 310 qdf_mem_free(cur_chan_list); 311 312 return QDF_STATUS_E_FAILURE; 313 } 314 315 /** 316 * hdd_ndi_start_bss() - Start BSS on NAN data interface 317 * @adapter: adapter context 318 * 319 * Return: 0 on success, error value on failure 320 */ 321 static int hdd_ndi_start_bss(struct hdd_adapter *adapter) 322 { 323 QDF_STATUS status; 324 struct bss_dot11_config dot11_cfg = {0}; 325 struct start_bss_config ndi_bss_cfg = {0}; 326 qdf_freq_t valid_freq = 0; 327 mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter); 328 struct mac_context *mac = MAC_CONTEXT(mac_handle); 329 struct hdd_context *hdd_ctx; 330 331 hdd_enter(); 332 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 333 334 if (!mac) { 335 hdd_debug("mac ctx NULL"); 336 return -EINVAL; 337 } 338 339 status = hdd_ndi_select_valid_freq(hdd_ctx, &valid_freq); 340 if (!QDF_IS_STATUS_SUCCESS(status)) { 341 hdd_err("Unable to retrieve channel list for NAN"); 342 return -EINVAL; 343 } 344 345 dot11_cfg.vdev_id = adapter->deflink->vdev_id; 346 dot11_cfg.bss_op_ch_freq = valid_freq; 347 dot11_cfg.phy_mode = eCSR_DOT11_MODE_AUTO; 348 if (!wlan_vdev_id_is_open_cipher(mac->pdev, adapter->deflink->vdev_id)) 349 dot11_cfg.privacy = 1; 350 351 sme_get_network_params(mac, &dot11_cfg); 352 ndi_bss_cfg.vdev_id = adapter->deflink->vdev_id; 353 ndi_bss_cfg.oper_ch_freq = dot11_cfg.bss_op_ch_freq; 354 ndi_bss_cfg.nwType = dot11_cfg.nw_type; 355 ndi_bss_cfg.dot11mode = dot11_cfg.dot11_mode; 356 357 if (dot11_cfg.opr_rates.numRates) { 358 qdf_mem_copy(ndi_bss_cfg.operationalRateSet.rate, 359 dot11_cfg.opr_rates.rate, 360 dot11_cfg.opr_rates.numRates); 361 ndi_bss_cfg.operationalRateSet.numRates = 362 dot11_cfg.opr_rates.numRates; 363 } 364 365 if (dot11_cfg.ext_rates.numRates) { 366 qdf_mem_copy(ndi_bss_cfg.extendedRateSet.rate, 367 dot11_cfg.ext_rates.rate, 368 dot11_cfg.ext_rates.numRates); 369 ndi_bss_cfg.extendedRateSet.numRates = 370 dot11_cfg.ext_rates.numRates; 371 } 372 373 status = sme_start_bss(mac_handle, adapter->deflink->vdev_id, 374 &ndi_bss_cfg); 375 376 if (QDF_IS_STATUS_ERROR(status)) { 377 hdd_err("NDI sme_RoamConnect session %d failed with status %d -> NotConnected", 378 adapter->deflink->vdev_id, status); 379 /* change back to NotConnected */ 380 hdd_conn_set_connection_state(adapter, 381 eConnectionState_NotConnected); 382 } 383 384 hdd_exit(); 385 386 return 0; 387 } 388 389 /** 390 * hdd_get_random_nan_mac_addr() - generate random non pre-existent mac address 391 * @hdd_ctx: hdd context pointer 392 * @mac_addr: mac address buffer to populate 393 * 394 * Return: status of operation 395 */ 396 static int hdd_get_random_nan_mac_addr(struct hdd_context *hdd_ctx, 397 struct qdf_mac_addr *mac_addr) 398 { 399 struct hdd_adapter *adapter; 400 uint8_t pos, bit_pos, byte_pos, mask; 401 uint8_t i, attempts, max_attempt = 16; 402 bool found; 403 404 for (attempts = 0; attempts < max_attempt; attempts++) { 405 found = false; 406 /* if NDI is present next addr is required to be 1 bit apart */ 407 adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE); 408 if (adapter) { 409 hdd_debug("NDI already exists, deriving next mac"); 410 qdf_mem_copy(mac_addr, &adapter->mac_addr, 411 sizeof(*mac_addr)); 412 qdf_get_random_bytes(&pos, sizeof(pos)); 413 /* skipping byte 0, 5 leaves 8*4=32 positions */ 414 pos = pos % 32; 415 bit_pos = pos % 8; 416 byte_pos = pos / 8; 417 mask = 1 << bit_pos; 418 /* flip the required bit */ 419 mac_addr->bytes[byte_pos + 1] ^= mask; 420 } else { 421 qdf_get_random_bytes(mac_addr, sizeof(*mac_addr)); 422 /* 423 * Reset multicast bit (bit-0) and set 424 * locally-administered bit 425 */ 426 mac_addr->bytes[0] = 0x2; 427 428 /* 429 * to avoid potential conflict with FW's generated NMI 430 * mac addr, host sets LSB if 6th byte to 0 431 */ 432 mac_addr->bytes[5] &= 0xFE; 433 } 434 for (i = 0; i < hdd_ctx->num_provisioned_addr; i++) { 435 if ((!qdf_mem_cmp(hdd_ctx-> 436 provisioned_mac_addr[i].bytes, 437 mac_addr, sizeof(*mac_addr)))) { 438 found = true; 439 break; 440 } 441 } 442 443 if (found) 444 continue; 445 446 for (i = 0; i < hdd_ctx->num_derived_addr; i++) { 447 if ((!qdf_mem_cmp(hdd_ctx-> 448 derived_mac_addr[i].bytes, 449 mac_addr, sizeof(*mac_addr)))) { 450 found = true; 451 break; 452 } 453 } 454 if (found) 455 continue; 456 457 adapter = hdd_get_adapter_by_macaddr(hdd_ctx, mac_addr->bytes); 458 if (!adapter) 459 return 0; 460 } 461 462 hdd_err("unable to get non-pre-existing mac address in %d attempts", 463 max_attempt); 464 465 return -EINVAL; 466 } 467 468 void hdd_ndp_event_handler(struct wlan_hdd_link_info *link_info, 469 struct csr_roam_info *roam_info, 470 eRoamCmdStatus roam_status, 471 eCsrRoamResult roam_result) 472 { 473 bool success; 474 struct wlan_objmgr_psoc *psoc; 475 struct wlan_objmgr_vdev *vdev; 476 477 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_NAN_ID); 478 if (!vdev) { 479 hdd_err("vdev is NULL"); 480 return; 481 } 482 psoc = wlan_vdev_get_psoc(vdev); 483 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_NAN_ID); 484 485 if (roam_status == eCSR_ROAM_NDP_STATUS_UPDATE) { 486 switch (roam_result) { 487 case eCSR_ROAM_RESULT_NDI_CREATE_RSP: 488 success = (roam_info->ndp.ndi_create_params.status == 489 NAN_DATAPATH_RSP_STATUS_SUCCESS); 490 hdd_debug("posting ndi create status: %d (%s) to umac", 491 success, success ? "Success" : "Failure"); 492 os_if_nan_post_ndi_create_rsp(psoc, link_info->vdev_id, 493 success); 494 return; 495 case eCSR_ROAM_RESULT_NDI_DELETE_RSP: 496 success = (roam_info->ndp.ndi_create_params.status == 497 NAN_DATAPATH_RSP_STATUS_SUCCESS); 498 hdd_debug("posting ndi delete status: %d (%s) to umac", 499 success, success ? "Success" : "Failure"); 500 os_if_nan_post_ndi_delete_rsp(psoc, link_info->vdev_id, 501 success); 502 return; 503 default: 504 hdd_err("in correct roam_result: %d", roam_result); 505 return; 506 } 507 } else { 508 hdd_err("in correct roam_status: %d", roam_status); 509 return; 510 } 511 } 512 513 /** 514 * __wlan_hdd_cfg80211_process_ndp_cmd() - handle NDP request 515 * @wiphy: pointer to wireless wiphy structure. 516 * @wdev: pointer to wireless_dev structure. 517 * @data: Pointer to the data to be passed via vendor interface 518 * @data_len:Length of the data to be passed 519 * 520 * This function is invoked to handle vendor command 521 * 522 * Return: 0 on success, negative errno on failure 523 */ 524 static int __wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy, 525 struct wireless_dev *wdev, const void *data, int data_len) 526 { 527 int ret_val; 528 struct hdd_context *hdd_ctx = wiphy_priv(wiphy); 529 530 ret_val = wlan_hdd_validate_context(hdd_ctx); 531 if (ret_val) 532 return ret_val; 533 534 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { 535 hdd_err_rl("Command not allowed in FTM mode"); 536 return -EPERM; 537 } 538 539 if (!WLAN_HDD_IS_NDP_ENABLED(hdd_ctx)) { 540 hdd_debug_rl("NAN datapath is not enabled"); 541 return -EPERM; 542 } 543 544 return os_if_nan_process_ndp_cmd(hdd_ctx->psoc, data, data_len, 545 hdd_is_ndp_allowed(hdd_ctx), wdev); 546 } 547 548 /** 549 * wlan_hdd_cfg80211_process_ndp_cmd() - handle NDP request 550 * @wiphy: pointer to wireless wiphy structure. 551 * @wdev: pointer to wireless_dev structure. 552 * @data: Pointer to the data to be passed via vendor interface 553 * @data_len:Length of the data to be passed 554 * 555 * This function is called to send a NAN request to 556 * firmware. This is an SSR-protected wrapper function. 557 * 558 * Return: 0 on success, negative errno on failure 559 */ 560 int wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy, 561 struct wireless_dev *wdev, 562 const void *data, int data_len) 563 { 564 /* This call is intentionally not protected by op_start/op_stop, due to 565 * the various protection needs of the callbacks dispatched within. 566 */ 567 return __wlan_hdd_cfg80211_process_ndp_cmd(wiphy, wdev, 568 data, data_len); 569 } 570 571 static int update_ndi_state(struct hdd_adapter *adapter, uint32_t state) 572 { 573 struct wlan_objmgr_vdev *vdev; 574 QDF_STATUS status; 575 576 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_NAN_ID); 577 if (!vdev) { 578 hdd_err("vdev is NULL"); 579 return QDF_STATUS_E_NULL_VALUE; 580 } 581 status = os_if_nan_set_ndi_state(vdev, state); 582 583 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_NAN_ID); 584 return status; 585 } 586 587 /** 588 * hdd_init_nan_data_mode() - initialize nan data mode 589 * @adapter: adapter context 590 * 591 * Returns: 0 on success negative error code on error 592 */ 593 int hdd_init_nan_data_mode(struct hdd_adapter *adapter) 594 { 595 struct net_device *wlan_dev = adapter->dev; 596 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 597 QDF_STATUS status; 598 int32_t ret_val; 599 mac_handle_t mac_handle; 600 bool bval = false; 601 uint8_t enable_sifs_burst = 0; 602 struct wlan_objmgr_vdev *vdev; 603 uint16_t rts_profile = 0; 604 605 status = hdd_adapter_fill_link_address(adapter); 606 if (QDF_IS_STATUS_ERROR(status)) { 607 hdd_debug("Link address derive failed"); 608 return qdf_status_to_os_return(status); 609 } 610 611 status = hdd_adapter_check_duplicate_session(adapter); 612 if (QDF_IS_STATUS_ERROR(status)) { 613 hdd_err("Duplicate session is existing with same mac address"); 614 return qdf_status_to_os_return(status); 615 } 616 617 ret_val = hdd_vdev_create(adapter->deflink); 618 if (ret_val) { 619 hdd_err("failed to create vdev: %d", ret_val); 620 return ret_val; 621 } 622 623 mac_handle = hdd_ctx->mac_handle; 624 625 /* Configure self HT/VHT capabilities */ 626 status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval); 627 if (!QDF_IS_STATUS_SUCCESS(status)) 628 hdd_err("unable to get vht_enable2x2"); 629 630 sme_set_pdev_ht_vht_ies(mac_handle, bval); 631 sme_set_vdev_ies_per_band(mac_handle, adapter->deflink->vdev_id, 632 adapter->device_mode); 633 634 hdd_roam_profile_init(adapter->deflink); 635 hdd_register_wext(wlan_dev); 636 637 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID); 638 if (!vdev) { 639 ret_val = -EAGAIN; 640 goto wext_unregister; 641 } 642 643 status = hdd_wmm_adapter_init(adapter); 644 if (QDF_STATUS_SUCCESS != status) { 645 hdd_err("hdd_wmm_adapter_init() failed, status %d", status); 646 ret_val = -EAGAIN; 647 goto error_wmm_init; 648 } 649 650 set_bit(WMM_INIT_DONE, &adapter->event_flags); 651 652 /* ENABLE SIFS BURST */ 653 status = ucfg_get_enable_sifs_burst(hdd_ctx->psoc, &enable_sifs_burst); 654 if (!QDF_IS_STATUS_SUCCESS(status)) 655 hdd_err("Failed to get sifs burst value, use default"); 656 657 ret_val = wma_cli_set_command((int)adapter->deflink->vdev_id, 658 (int)wmi_pdev_param_burst_enable, 659 enable_sifs_burst, 660 PDEV_CMD); 661 if (0 != ret_val) 662 hdd_err("wmi_pdev_param_burst_enable set failed %d", ret_val); 663 664 /* RTS CTS PARAM */ 665 status = ucfg_fwol_get_rts_profile(hdd_ctx->psoc, &rts_profile); 666 if (QDF_IS_STATUS_ERROR(status)) 667 hdd_err("FAILED TO GET RTSCTS Profile status:%d", status); 668 669 ret_val = sme_cli_set_command(adapter->deflink->vdev_id, 670 wmi_vdev_param_enable_rtscts, rts_profile, 671 VDEV_CMD); 672 if (ret_val) 673 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret_val); 674 675 hdd_set_netdev_flags(adapter); 676 677 hdd_tsf_auto_report_init(adapter); 678 update_ndi_state(adapter, NAN_DATA_NDI_CREATING_STATE); 679 hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); 680 return ret_val; 681 682 error_wmm_init: 683 hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); 684 685 wext_unregister: 686 hdd_wext_unregister(wlan_dev, true); 687 QDF_BUG(!hdd_vdev_destroy(adapter->deflink)); 688 689 return ret_val; 690 } 691 692 /** 693 * hdd_is_max_ndi_count_reached() - Check the NDI max limit 694 * @hdd_ctx: Pointer to HDD context 695 * 696 * This function does not allow to create more than ndi_max_support 697 * 698 * Return: false if max value not reached otherwise true 699 */ 700 static bool hdd_is_max_ndi_count_reached(struct hdd_context *hdd_ctx) 701 { 702 struct hdd_adapter *adapter, *next_adapter = NULL; 703 uint8_t ndi_adapter_count = 0; 704 QDF_STATUS status; 705 uint32_t max_ndi; 706 707 if (!hdd_ctx) 708 return true; 709 710 hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, 711 NET_DEV_HOLD_NDI_OPEN) { 712 if (WLAN_HDD_IS_NDI(adapter)) 713 ndi_adapter_count++; 714 hdd_adapter_dev_put_debug(adapter, NET_DEV_HOLD_NDI_OPEN); 715 } 716 717 status = cfg_nan_get_max_ndi(hdd_ctx->psoc, &max_ndi); 718 if (QDF_IS_STATUS_ERROR(status)) { 719 hdd_err(" Unable to fetch Max NDI"); 720 return true; 721 } 722 723 if (ndi_adapter_count >= max_ndi) { 724 hdd_err("Can't allow more than %d NDI adapters", 725 max_ndi); 726 return true; 727 } 728 729 return false; 730 } 731 732 int hdd_ndi_open(const char *iface_name, bool is_add_virtual_iface) 733 { 734 struct hdd_adapter *adapter; 735 struct qdf_mac_addr random_ndi_mac; 736 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 737 uint8_t *ndi_mac_addr; 738 struct hdd_adapter_create_param params = {0}; 739 740 hdd_enter(); 741 742 if (hdd_is_max_ndi_count_reached(hdd_ctx)) 743 return -EINVAL; 744 745 params.is_add_virtual_iface = is_add_virtual_iface; 746 747 hdd_debug("is_add_virtual_iface %d", is_add_virtual_iface); 748 749 if (cfg_nan_get_ndi_mac_randomize(hdd_ctx->psoc)) { 750 if (hdd_get_random_nan_mac_addr(hdd_ctx, &random_ndi_mac)) { 751 hdd_err("get random mac address failed"); 752 return -EFAULT; 753 } 754 ndi_mac_addr = &random_ndi_mac.bytes[0]; 755 } else { 756 ndi_mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_NDI_MODE); 757 if (!ndi_mac_addr) { 758 hdd_err("get intf address failed"); 759 return -EFAULT; 760 } 761 } 762 763 params.is_add_virtual_iface = 1; 764 adapter = hdd_open_adapter(hdd_ctx, QDF_NDI_MODE, iface_name, 765 ndi_mac_addr, NET_NAME_UNKNOWN, true, 766 ¶ms); 767 if (!adapter) { 768 if (!cfg_nan_get_ndi_mac_randomize(hdd_ctx->psoc)) 769 wlan_hdd_release_intf_addr(hdd_ctx, ndi_mac_addr); 770 hdd_err("hdd_open_adapter failed"); 771 return -EINVAL; 772 } 773 774 hdd_exit(); 775 return 0; 776 } 777 778 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) 779 int hdd_ndi_set_mode(const char *iface_name) 780 { 781 struct hdd_adapter *adapter; 782 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 783 struct qdf_mac_addr random_ndi_mac; 784 uint8_t *ndi_mac_addr = NULL; 785 786 hdd_enter(); 787 if (hdd_is_max_ndi_count_reached(hdd_ctx)) 788 return -EINVAL; 789 790 adapter = hdd_get_adapter_by_iface_name(hdd_ctx, iface_name); 791 if (!adapter) { 792 hdd_err("adapter is null"); 793 return -EINVAL; 794 } 795 796 if (cfg_nan_get_ndi_mac_randomize(hdd_ctx->psoc)) { 797 if (hdd_get_random_nan_mac_addr(hdd_ctx, &random_ndi_mac)) { 798 hdd_err("get random mac address failed"); 799 return -EFAULT; 800 } 801 ndi_mac_addr = &random_ndi_mac.bytes[0]; 802 ucfg_dp_update_intf_mac(hdd_ctx->psoc, &adapter->mac_addr, 803 (struct qdf_mac_addr *)ndi_mac_addr, 804 adapter->deflink->vdev); 805 hdd_update_dynamic_mac(hdd_ctx, &adapter->mac_addr, 806 (struct qdf_mac_addr *)ndi_mac_addr); 807 qdf_mem_copy(&adapter->mac_addr, ndi_mac_addr, ETH_ALEN); 808 qdf_net_update_net_device_dev_addr(adapter->dev, 809 ndi_mac_addr, ETH_ALEN); 810 } 811 812 adapter->device_mode = QDF_NDI_MODE; 813 hdd_debug("Created NDI with device mode:%d and iface_name:%s", 814 adapter->device_mode, iface_name); 815 816 return 0; 817 } 818 #endif 819 820 int hdd_ndi_start(const char *iface_name, uint16_t transaction_id) 821 { 822 int ret; 823 QDF_STATUS status; 824 struct hdd_adapter *adapter; 825 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 826 struct wlan_objmgr_vdev *vdev; 827 828 hdd_enter(); 829 if (!hdd_ctx) 830 return -EINVAL; 831 832 adapter = hdd_get_adapter_by_iface_name(hdd_ctx, iface_name); 833 if (!adapter) { 834 hdd_err("adapter is null"); 835 return -EINVAL; 836 } 837 838 /* create nan vdev */ 839 status = hdd_init_nan_data_mode(adapter); 840 if (QDF_STATUS_SUCCESS != status) { 841 hdd_err("failed to init nan data intf, status :%d", status); 842 ret = -EFAULT; 843 goto err_handler; 844 } 845 846 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_NAN_ID); 847 if (!vdev) { 848 hdd_err("vdev is NULL"); 849 ret = -EINVAL; 850 goto err_handler; 851 } 852 853 hdd_cstats_log_ndi_create_req_evt(vdev, transaction_id); 854 /* 855 * Create transaction id is required to be saved since the firmware 856 * does not honor the transaction id for create request 857 */ 858 ucfg_nan_set_ndp_create_transaction_id(vdev, transaction_id); 859 ucfg_nan_set_ndi_state(vdev, NAN_DATA_NDI_CREATING_STATE); 860 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_NAN_ID); 861 862 if (hdd_ndi_start_bss(adapter)) { 863 hdd_err("NDI start bss failed"); 864 ret = -EFAULT; 865 goto err_handler; 866 } 867 868 hdd_create_adapter_sysfs_files(adapter); 869 hdd_exit(); 870 return 0; 871 872 err_handler: 873 874 /* Start BSS failed, delete the interface */ 875 hdd_close_ndi(adapter); 876 return ret; 877 } 878 879 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) 880 static int hdd_delete_ndi_intf(struct wiphy *wiphy, struct wireless_dev *wdev) 881 { 882 struct net_device *dev = wdev->netdev; 883 struct hdd_context *hdd_ctx = (struct hdd_context *)wiphy_priv(wiphy); 884 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 885 886 hdd_enter_dev(dev); 887 888 wlan_hdd_release_intf_addr(hdd_ctx, 889 adapter->mac_addr.bytes); 890 hdd_stop_adapter(hdd_ctx, adapter); 891 hdd_deinit_adapter(hdd_ctx, adapter, true); 892 893 hdd_exit(); 894 895 return 0; 896 } 897 #else 898 static int hdd_delete_ndi_intf(struct wiphy *wiphy, struct wireless_dev *wdev) 899 { 900 int ret; 901 902 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev); 903 904 if (ret) 905 hdd_err("NDI delete request failed"); 906 else 907 hdd_err("NDI delete request successfully issued"); 908 909 return ret; 910 } 911 #endif 912 913 int hdd_ndi_delete(uint8_t vdev_id, const char *iface_name, 914 uint16_t transaction_id) 915 { 916 int ret; 917 struct hdd_adapter *adapter; 918 struct wlan_hdd_link_info *link_info; 919 struct hdd_station_ctx *sta_ctx; 920 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 921 struct wlan_objmgr_vdev *vdev; 922 923 if (!hdd_ctx) 924 return -EINVAL; 925 926 /* check if adapter by vdev_id is valid NDI */ 927 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id); 928 if (!link_info || !WLAN_HDD_IS_NDI(link_info->adapter)) { 929 hdd_err("NAN data interface %s is not available", iface_name); 930 return -EINVAL; 931 } 932 933 adapter = link_info->adapter; 934 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info); 935 936 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_NAN_ID); 937 if (!vdev) { 938 hdd_err("vdev is NULL"); 939 return -EINVAL; 940 } 941 942 os_if_nan_set_ndp_delete_transaction_id(vdev, transaction_id); 943 os_if_nan_set_ndi_state(vdev, NAN_DATA_NDI_DELETING_STATE); 944 hdd_cstats_log_ndi_delete_req_evt(vdev, transaction_id); 945 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_NAN_ID); 946 947 /* Delete the interface */ 948 adapter->is_virtual_iface = true; 949 ret = hdd_delete_ndi_intf(hdd_ctx->wiphy, &adapter->wdev); 950 951 return ret; 952 } 953 954 #define MAX_VDEV_NDP_PARAMS 2 955 /* params being sent: 956 * wmi_vdev_param_ndp_inactivity_timeout 957 * wmi_vdev_param_ndp_keepalive_timeout 958 */ 959 960 void 961 hdd_ndi_drv_ndi_create_rsp_handler(uint8_t vdev_id, 962 struct nan_datapath_inf_create_rsp *ndi_rsp) 963 { 964 struct hdd_context *hdd_ctx; 965 struct hdd_adapter *adapter; 966 struct wlan_hdd_link_info *link_info; 967 struct hdd_station_ctx *sta_ctx; 968 struct csr_roam_info *roam_info; 969 uint16_t ndp_inactivity_timeout = 0; 970 uint16_t ndp_keep_alive_period; 971 struct qdf_mac_addr bc_mac_addr = QDF_MAC_ADDR_BCAST_INIT; 972 struct wlan_objmgr_vdev *vdev; 973 struct dev_set_param setparam[MAX_VDEV_NDP_PARAMS] = {}; 974 uint8_t index = 0; 975 QDF_STATUS status; 976 977 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 978 if (!hdd_ctx) 979 return; 980 981 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id); 982 if (!link_info) { 983 hdd_err("Invalid vdev"); 984 return; 985 } 986 987 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info); 988 adapter = link_info->adapter; 989 990 roam_info = qdf_mem_malloc(sizeof(*roam_info)); 991 if (!roam_info) 992 return; 993 994 if (ndi_rsp->status == QDF_STATUS_SUCCESS) { 995 hdd_alert("NDI interface successfully created"); 996 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_NAN_ID); 997 if (!vdev) { 998 qdf_mem_free(roam_info); 999 hdd_err("vdev is NULL"); 1000 return; 1001 } 1002 1003 os_if_nan_set_ndp_create_transaction_id(vdev, 0); 1004 os_if_nan_set_ndi_state(vdev, NAN_DATA_NDI_CREATED_STATE); 1005 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_NAN_ID); 1006 1007 wlan_hdd_netif_queue_control(adapter, 1008 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, 1009 WLAN_CONTROL_PATH); 1010 1011 if (QDF_IS_STATUS_ERROR(cfg_nan_get_ndp_inactivity_timeout( 1012 hdd_ctx->psoc, &ndp_inactivity_timeout))) 1013 hdd_err("Failed to fetch inactivity timeout value"); 1014 status = mlme_check_index_setparam( 1015 setparam, 1016 wmi_vdev_param_ndp_inactivity_timeout, 1017 ndp_inactivity_timeout, index++, 1018 MAX_VDEV_NDP_PARAMS); 1019 if (QDF_IS_STATUS_ERROR(status)) { 1020 hdd_err("failed at wmi_vdev_param_ndp_inactivity_timeout"); 1021 goto error; 1022 } 1023 1024 if (QDF_IS_STATUS_SUCCESS(cfg_nan_get_ndp_keepalive_period( 1025 hdd_ctx->psoc, 1026 &ndp_keep_alive_period))) { 1027 status = mlme_check_index_setparam( 1028 setparam, 1029 wmi_vdev_param_ndp_keepalive_timeout, 1030 ndp_keep_alive_period, index++, 1031 MAX_VDEV_NDP_PARAMS); 1032 if (QDF_IS_STATUS_ERROR(status)) { 1033 hdd_err("failed at wmi_vdev_param_ndp_keepalive_timeout"); 1034 goto error; 1035 } 1036 } 1037 status = sme_send_multi_pdev_vdev_set_params(MLME_VDEV_SETPARAM, 1038 link_info->vdev_id, 1039 setparam, index); 1040 if (QDF_IS_STATUS_ERROR(status)) 1041 hdd_err("failed to send vdev set params"); 1042 } else { 1043 hdd_alert("NDI interface creation failed with reason %d", 1044 ndi_rsp->reason /* create_reason */); 1045 } 1046 1047 hdd_cstats_log_ndi_create_resp_evt(link_info, ndi_rsp); 1048 1049 hdd_save_peer(sta_ctx, &bc_mac_addr); 1050 qdf_copy_macaddr(&roam_info->bssid, &bc_mac_addr); 1051 hdd_roam_register_sta(link_info, 1052 &roam_info->bssid, 1053 roam_info->fAuthRequired); 1054 1055 error: 1056 qdf_mem_free(roam_info); 1057 } 1058 1059 void hdd_ndi_close(uint8_t vdev_id) 1060 { 1061 struct hdd_context *hdd_ctx; 1062 struct wlan_hdd_link_info *link_info; 1063 1064 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 1065 if (!hdd_ctx) 1066 return; 1067 1068 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id); 1069 if (!link_info) { 1070 hdd_err("Invalid vdev"); 1071 return; 1072 } 1073 1074 link_info->adapter->is_virtual_iface = true; 1075 hdd_close_ndi(link_info->adapter); 1076 } 1077 1078 void hdd_ndi_drv_ndi_delete_rsp_handler(uint8_t vdev_id) 1079 { 1080 struct hdd_context *hdd_ctx; 1081 struct hdd_adapter *adapter; 1082 struct wlan_hdd_link_info *link_info; 1083 struct hdd_station_ctx *sta_ctx; 1084 struct qdf_mac_addr bc_mac_addr = QDF_MAC_ADDR_BCAST_INIT; 1085 1086 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 1087 if (!hdd_ctx) 1088 return; 1089 1090 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id); 1091 if (!link_info) { 1092 hdd_err("Invalid vdev"); 1093 return; 1094 } 1095 1096 adapter = link_info->adapter; 1097 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info); 1098 1099 hdd_delete_peer(sta_ctx, &bc_mac_addr); 1100 1101 wlan_hdd_netif_queue_control(adapter, 1102 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, 1103 WLAN_CONTROL_PATH); 1104 1105 /* 1106 * For NAN Data interface, the close session results in the final 1107 * indication to the userspace 1108 */ 1109 if (adapter->device_mode == QDF_NDI_MODE) 1110 hdd_ndp_session_end_handler(adapter); 1111 1112 complete(&adapter->disconnect_comp_var); 1113 } 1114 1115 void hdd_ndp_session_end_handler(struct hdd_adapter *adapter) 1116 { 1117 struct wlan_objmgr_vdev *vdev; 1118 1119 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_NAN_ID); 1120 if (!vdev) { 1121 hdd_err("vdev is NULL"); 1122 return; 1123 } 1124 1125 os_if_nan_ndi_session_end(vdev); 1126 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_NAN_ID); 1127 } 1128 1129 /** 1130 * hdd_send_obss_scan_req() - send OBSS scan request to SME layer. 1131 * @hdd_ctx: hdd context pointer 1132 * @val: true if new NDP peer is added and false when last peer NDP is deleted. 1133 * 1134 * Return: void 1135 */ 1136 static void hdd_send_obss_scan_req(struct hdd_context *hdd_ctx, bool val) 1137 { 1138 QDF_STATUS status; 1139 uint32_t sta_vdev_id = 0; 1140 1141 status = hdd_get_first_connected_sta_vdev_id(hdd_ctx, &sta_vdev_id); 1142 1143 if (QDF_IS_STATUS_SUCCESS(status)) { 1144 hdd_debug("reconfig OBSS scan param: %d", val); 1145 sme_reconfig_obss_scan_param(hdd_ctx->mac_handle, sta_vdev_id, 1146 val); 1147 } else { 1148 hdd_debug("Connected STA not found"); 1149 } 1150 } 1151 1152 int hdd_ndp_new_peer_handler(uint8_t vdev_id, uint16_t sta_id, 1153 struct qdf_mac_addr *peer_mac_addr, 1154 bool first_peer) 1155 { 1156 struct hdd_context *hdd_ctx; 1157 struct hdd_adapter *adapter; 1158 struct wlan_hdd_link_info *link_info; 1159 struct hdd_station_ctx *sta_ctx; 1160 struct csr_roam_info *roam_info; 1161 struct wlan_objmgr_vdev *vdev; 1162 1163 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 1164 if (!hdd_ctx) 1165 return -EINVAL; 1166 1167 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id); 1168 if (!link_info) { 1169 hdd_err("Invalid vdev"); 1170 return -EINVAL; 1171 } 1172 1173 adapter = link_info->adapter; 1174 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info); 1175 1176 /* save peer in ndp ctx */ 1177 if (!hdd_save_peer(sta_ctx, peer_mac_addr)) { 1178 hdd_err("Ndp peer table full. cannot save new peer"); 1179 return -EPERM; 1180 } 1181 1182 roam_info = qdf_mem_malloc(sizeof(*roam_info)); 1183 if (!roam_info) 1184 return -ENOMEM; 1185 qdf_copy_macaddr(&roam_info->bssid, peer_mac_addr); 1186 1187 /* this function is called for each new peer */ 1188 hdd_roam_register_sta(link_info, &roam_info->bssid, 1189 roam_info->fAuthRequired); 1190 1191 if (!first_peer) 1192 goto mem_free; 1193 1194 hdd_debug("Set ctx connection state to connected"); 1195 /* Disable LRO/GRO for NDI Mode */ 1196 if (ucfg_dp_is_ol_enabled(hdd_ctx->psoc) && 1197 !NAN_CONCURRENCY_SUPPORTED(hdd_ctx->psoc)) { 1198 hdd_debug("Disable LRO/GRO in NDI Mode"); 1199 hdd_disable_rx_ol_in_concurrency(true); 1200 } 1201 1202 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_DP_ID); 1203 if (vdev) { 1204 ucfg_dp_bus_bw_compute_prev_txrx_stats(vdev); 1205 hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); 1206 } 1207 1208 ucfg_dp_bus_bw_compute_timer_start(hdd_ctx->psoc); 1209 sta_ctx->conn_info.conn_state = eConnectionState_NdiConnected; 1210 hdd_wmm_connect(adapter, roam_info, eCSR_BSS_TYPE_NDI); 1211 wlan_hdd_netif_queue_control(adapter, 1212 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, 1213 WLAN_CONTROL_PATH); 1214 /* 1215 * This is called only for first peer. So, no.of NDP sessions 1216 * are always 1 1217 */ 1218 if (!NDI_CONCURRENCY_SUPPORTED(hdd_ctx->psoc)) 1219 hdd_indicate_active_ndp_cnt(hdd_ctx->psoc, vdev_id, 1); 1220 hdd_send_obss_scan_req(hdd_ctx, true); 1221 1222 mem_free: 1223 qdf_mem_free(roam_info); 1224 return 0; 1225 } 1226 1227 void hdd_cleanup_ndi(struct wlan_hdd_link_info *link_info) 1228 { 1229 struct hdd_station_ctx *sta_ctx; 1230 struct wlan_objmgr_vdev *vdev; 1231 struct hdd_adapter *adapter = link_info->adapter; 1232 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1233 1234 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info); 1235 if (sta_ctx->conn_info.conn_state != eConnectionState_NdiConnected) { 1236 hdd_debug("NDI has no NDPs"); 1237 return; 1238 } 1239 sta_ctx->conn_info.conn_state = eConnectionState_NdiDisconnected; 1240 hdd_conn_set_connection_state(adapter, 1241 eConnectionState_NdiDisconnected); 1242 hdd_debug("Stop netif tx queues."); 1243 wlan_hdd_netif_queue_control(adapter, 1244 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, 1245 WLAN_CONTROL_PATH); 1246 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_DP_ID); 1247 if (vdev) { 1248 ucfg_dp_bus_bw_compute_reset_prev_txrx_stats(vdev); 1249 hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID); 1250 } 1251 ucfg_dp_bus_bw_compute_timer_try_stop(hdd_ctx->psoc); 1252 if ((ucfg_dp_is_ol_enabled(hdd_ctx->psoc) && 1253 !NAN_CONCURRENCY_SUPPORTED(hdd_ctx->psoc)) && 1254 ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 0) || 1255 ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 1) && 1256 (policy_mgr_mode_specific_connection_count( 1257 hdd_ctx->psoc, 1258 PM_STA_MODE, 1259 NULL) == 1)))) { 1260 hdd_debug("Enable LRO/GRO"); 1261 ucfg_dp_rx_handle_concurrency(hdd_ctx->psoc, false); 1262 } 1263 } 1264 1265 void hdd_ndp_peer_departed_handler(uint8_t vdev_id, uint16_t sta_id, 1266 struct qdf_mac_addr *peer_mac_addr, bool last_peer) 1267 { 1268 struct hdd_context *hdd_ctx; 1269 struct hdd_adapter *adapter; 1270 struct wlan_hdd_link_info *link_info; 1271 struct hdd_station_ctx *sta_ctx; 1272 1273 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 1274 if (!hdd_ctx) 1275 return; 1276 1277 link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id); 1278 if (!link_info) { 1279 hdd_err("Invalid vdev"); 1280 return; 1281 } 1282 1283 adapter = link_info->adapter; 1284 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info); 1285 1286 hdd_delete_peer(sta_ctx, peer_mac_addr); 1287 1288 ucfg_nan_clear_peer_mc_list(hdd_ctx->psoc, link_info->vdev, 1289 peer_mac_addr); 1290 1291 if (last_peer) { 1292 hdd_debug("No more ndp peers."); 1293 hdd_cleanup_ndi(link_info); 1294 qdf_event_set(&adapter->peer_cleanup_done); 1295 /* 1296 * This is called only for last peer. So, no.of NDP sessions 1297 * are always 0 1298 */ 1299 if (!NDI_CONCURRENCY_SUPPORTED(hdd_ctx->psoc)) 1300 hdd_indicate_active_ndp_cnt(hdd_ctx->psoc, vdev_id, 0); 1301 hdd_send_obss_scan_req(hdd_ctx, false); 1302 } 1303 } 1304