1 /* 2 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. 3 * 4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc. 5 * 6 * 7 * Permission to use, copy, modify, and/or distribute this software for 8 * any purpose with or without fee is hereby granted, provided that the 9 * above copyright notice and this permission notice appear in all 10 * copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 19 * PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 /* 23 * This file was originally distributed by Qualcomm Atheros, Inc. 24 * under proprietary terms before Copyright ownership was assigned 25 * to the Linux Foundation. 26 */ 27 28 /** 29 * DOC: wlan_hdd_main.c 30 * 31 * WLAN Host Device Driver implementation 32 * 33 */ 34 35 /* denote that this file does not allow legacy hddLog */ 36 #define HDD_DISALLOW_LEGACY_HDDLOG 1 37 38 /* Include Files */ 39 #include <wlan_hdd_includes.h> 40 #include <cds_api.h> 41 #include <cds_sched.h> 42 #include <linux/cpu.h> 43 #include <linux/etherdevice.h> 44 #include <linux/firmware.h> 45 #include <wlan_hdd_tx_rx.h> 46 #include <wni_api.h> 47 #include <wlan_hdd_cfg.h> 48 #include <wlan_ptt_sock_svc.h> 49 #include <dbglog_host.h> 50 #include <wlan_logging_sock_svc.h> 51 #include <wlan_hdd_wowl.h> 52 #include <wlan_hdd_misc.h> 53 #include <wlan_hdd_wext.h> 54 #include "wlan_hdd_trace.h" 55 #include "wlan_hdd_ioctl.h" 56 #include "wlan_hdd_ftm.h" 57 #include "wlan_hdd_power.h" 58 #include "wlan_hdd_stats.h" 59 #include "wlan_hdd_scan.h" 60 #include "qdf_types.h" 61 #include "qdf_trace.h" 62 #include <cdp_txrx_peer_ops.h> 63 64 #include <net/addrconf.h> 65 #include <linux/wireless.h> 66 #include <net/cfg80211.h> 67 #include <linux/inetdevice.h> 68 #include <net/addrconf.h> 69 #include "wlan_hdd_cfg80211.h" 70 #include "wlan_hdd_ext_scan.h" 71 #include "wlan_hdd_p2p.h" 72 #include <linux/rtnetlink.h> 73 #include "sap_api.h" 74 #include <linux/semaphore.h> 75 #include <linux/ctype.h> 76 #include <linux/compat.h> 77 #ifdef MSM_PLATFORM 78 #include <soc/qcom/subsystem_restart.h> 79 #endif 80 #include <wlan_hdd_hostapd.h> 81 #include <wlan_hdd_softap_tx_rx.h> 82 #include "cfg_api.h" 83 #include "qwlan_version.h" 84 #include "wma_types.h" 85 #include "wlan_hdd_tdls.h" 86 #ifdef FEATURE_WLAN_CH_AVOID 87 #include "cds_regdomain.h" 88 #include "cdp_txrx_flow_ctrl_v2.h" 89 #endif /* FEATURE_WLAN_CH_AVOID */ 90 #include "pld_common.h" 91 #include "wlan_hdd_ocb.h" 92 #include "wlan_hdd_nan.h" 93 #include "wlan_hdd_debugfs.h" 94 #include "wlan_hdd_driver_ops.h" 95 #include "epping_main.h" 96 #include "wlan_hdd_memdump.h" 97 98 #include <wlan_hdd_ipa.h> 99 #include "hif.h" 100 #include "wma.h" 101 #include "cds_concurrency.h" 102 #include "wlan_hdd_tsf.h" 103 #include "wlan_hdd_green_ap.h" 104 #include "bmi.h" 105 #include <wlan_hdd_regulatory.h> 106 #include "ol_rx_fwd.h" 107 #include "wlan_hdd_lpass.h" 108 #include "nan_api.h" 109 #include <wlan_hdd_napi.h> 110 #include "wlan_hdd_disa.h" 111 #include <dispatcher_init_deinit.h> 112 113 #ifdef MODULE 114 #define WLAN_MODULE_NAME module_name(THIS_MODULE) 115 #else 116 #define WLAN_MODULE_NAME "wlan" 117 #endif 118 119 #ifdef TIMER_MANAGER 120 #define TIMER_MANAGER_STR " +TIMER_MANAGER" 121 #else 122 #define TIMER_MANAGER_STR "" 123 #endif 124 125 #ifdef MEMORY_DEBUG 126 #define MEMORY_DEBUG_STR " +MEMORY_DEBUG" 127 #else 128 #define MEMORY_DEBUG_STR "" 129 #endif 130 131 #ifndef MODULE 132 static struct gwlan_loader *wlan_loader; 133 static ssize_t wlan_boot_cb(struct kobject *kobj, 134 struct kobj_attribute *attr, 135 const char *buf, size_t count); 136 struct gwlan_loader { 137 bool loaded_state; 138 struct kobject *boot_wlan_obj; 139 struct attribute_group *attr_group; 140 }; 141 142 static struct kobj_attribute wlan_boot_attribute = 143 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb); 144 145 static struct attribute *attrs[] = { 146 &wlan_boot_attribute.attr, 147 NULL, 148 }; 149 150 #define MODULE_INITIALIZED 1 151 #endif 152 153 /* the Android framework expects this param even though we don't use it */ 154 #define BUF_LEN 20 155 static char fwpath_buffer[BUF_LEN]; 156 static struct kparam_string fwpath = { 157 .string = fwpath_buffer, 158 .maxlen = BUF_LEN, 159 }; 160 161 static char *country_code; 162 static int enable_11d = -1; 163 static int enable_dfs_chan_scan = -1; 164 165 /* 166 * spinlock for synchronizing asynchronous request/response 167 * (full description of use in wlan_hdd_main.h) 168 */ 169 DEFINE_SPINLOCK(hdd_context_lock); 170 171 #define WLAN_NLINK_CESIUM 30 172 173 static qdf_wake_lock_t wlan_wake_lock; 174 175 #define WOW_MAX_FILTER_LISTS 1 176 #define WOW_MAX_FILTERS_PER_LIST 4 177 #define WOW_MIN_PATTERN_SIZE 6 178 #define WOW_MAX_PATTERN_SIZE 64 179 180 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) 181 static const struct wiphy_wowlan_support wowlan_support_reg_init = { 182 .flags = WIPHY_WOWLAN_ANY | 183 WIPHY_WOWLAN_MAGIC_PKT | 184 WIPHY_WOWLAN_DISCONNECT | 185 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | 186 WIPHY_WOWLAN_GTK_REKEY_FAILURE | 187 WIPHY_WOWLAN_EAP_IDENTITY_REQ | 188 WIPHY_WOWLAN_4WAY_HANDSHAKE | 189 WIPHY_WOWLAN_RFKILL_RELEASE, 190 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST, 191 .pattern_min_len = WOW_MIN_PATTERN_SIZE, 192 .pattern_max_len = WOW_MAX_PATTERN_SIZE, 193 }; 194 #endif 195 196 /* internal function declaration */ 197 198 struct sock *cesium_nl_srv_sock; 199 200 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN 201 void wlan_hdd_auto_shutdown_cb(void); 202 #endif 203 204 /** 205 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces 206 * @hdd_ctx: pointer to hdd_context_t 207 * 208 * Return: none 209 */ 210 static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx) 211 { 212 hdd_adapter_t *adapter; 213 hdd_adapter_list_node_t *adapter_node, *next; 214 QDF_STATUS status = QDF_STATUS_SUCCESS; 215 216 status = hdd_get_front_adapter(hdd_ctx, &adapter_node); 217 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) { 218 adapter = adapter_node->pAdapter; 219 if (NULL != adapter) 220 hdd_send_rps_ind(adapter); 221 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); 222 adapter_node = next; 223 } 224 } 225 226 /** 227 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer 228 * @vdev_id: vdev_id 229 * @action: action type 230 * @reason: reason type 231 * 232 * Return: none 233 */ 234 void wlan_hdd_txrx_pause_cb(uint8_t vdev_id, 235 enum netif_action_type action, enum netif_reason_type reason) 236 { 237 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 238 hdd_adapter_t *adapter; 239 240 if (!hdd_ctx) { 241 hdd_err("hdd ctx is NULL"); 242 return; 243 } 244 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id); 245 246 wlan_hdd_netif_queue_control(adapter, action, reason); 247 return; 248 } 249 250 /* 251 * Store WLAN driver version info in a global variable such that crash debugger 252 * can extract it from driver debug symbol and crashdump for post processing 253 */ 254 uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR; 255 256 /** 257 * hdd_device_mode_to_string() - return string conversion of device mode 258 * @device_mode: device mode 259 * 260 * This utility function helps log string conversion of device mode. 261 * 262 * Return: string conversion of device mode, if match found; 263 * "Unknown" otherwise. 264 */ 265 const char *hdd_device_mode_to_string(uint8_t device_mode) 266 { 267 switch (device_mode) { 268 CASE_RETURN_STRING(QDF_STA_MODE); 269 CASE_RETURN_STRING(QDF_SAP_MODE); 270 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE); 271 CASE_RETURN_STRING(QDF_P2P_GO_MODE); 272 CASE_RETURN_STRING(QDF_FTM_MODE); 273 CASE_RETURN_STRING(QDF_IBSS_MODE); 274 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE); 275 CASE_RETURN_STRING(QDF_OCB_MODE); 276 CASE_RETURN_STRING(QDF_NDI_MODE); 277 default: 278 return "Unknown"; 279 } 280 } 281 282 /** 283 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo 284 * @adapter: HDD adapter 285 * @chan_number: Channel number 286 * @chan_bw: Bandwidth 287 * 288 * Checks if the given bandwidth is valid for the given channel number. 289 * 290 * Return: 0 for success, non-zero for failure 291 */ 292 int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter, 293 uint32_t chan_number, 294 enum phy_ch_width chan_bw) 295 { 296 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; 297 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i; 298 bool found = false; 299 tHalHandle hal; 300 301 hal = WLAN_HDD_GET_HAL_CTX(adapter); 302 if (!hal) { 303 hdd_err("Invalid HAL context"); 304 return -EINVAL; 305 } 306 307 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) { 308 hdd_err("No valid channel list"); 309 return -EOPNOTSUPP; 310 } 311 312 for (i = 0; i < len; i++) { 313 if (chan[i] == chan_number) { 314 found = true; 315 break; 316 } 317 } 318 319 if (found == false) { 320 hdd_err("Channel not in driver's valid channel list"); 321 return -EOPNOTSUPP; 322 } 323 324 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) && 325 (!CDS_IS_CHANNEL_5GHZ(chan_number))) { 326 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number); 327 return -EINVAL; 328 } 329 330 if (CDS_IS_CHANNEL_24GHZ(chan_number)) { 331 if (chan_bw == CH_WIDTH_80MHZ) { 332 hdd_err("BW80 not possible in 2.4GHz band"); 333 return -EINVAL; 334 } 335 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) && 336 (chan_bw != CH_WIDTH_MAX)) { 337 hdd_err("Only BW20 possible on channel 14"); 338 return -EINVAL; 339 } 340 } 341 342 if (CDS_IS_CHANNEL_5GHZ(chan_number)) { 343 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) && 344 (chan_bw != CH_WIDTH_MAX)) { 345 hdd_err("Only BW20 possible on channel 165"); 346 return -EINVAL; 347 } 348 } 349 350 return 0; 351 } 352 353 static int __hdd_netdev_notifier_call(struct notifier_block *nb, 354 unsigned long state, void *data) 355 { 356 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) 357 struct netdev_notifier_info *dev_notif_info = data; 358 struct net_device *dev = dev_notif_info->dev; 359 #else 360 struct net_device *dev = data; 361 #endif 362 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 363 hdd_context_t *hdd_ctx; 364 365 ENTER_DEV(dev); 366 367 /* Make sure that this callback corresponds to our device. */ 368 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3))) 369 return NOTIFY_DONE; 370 371 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) && 372 (adapter->dev != dev)) { 373 hdd_err("device adapter is not matching!!!"); 374 return NOTIFY_DONE; 375 } 376 377 if (!dev->ieee80211_ptr) { 378 hdd_err("ieee80211_ptr is NULL!!!"); 379 return NOTIFY_DONE; 380 } 381 382 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 383 if (NULL == hdd_ctx) { 384 hdd_alert("HDD Context Null Pointer"); 385 QDF_ASSERT(0); 386 return NOTIFY_DONE; 387 } 388 if (cds_is_driver_recovering()) 389 return NOTIFY_DONE; 390 391 hdd_notice("%s New Net Device State = %lu", 392 dev->name, state); 393 394 switch (state) { 395 case NETDEV_REGISTER: 396 break; 397 398 case NETDEV_UNREGISTER: 399 break; 400 401 case NETDEV_UP: 402 sme_ch_avoid_update_req(hdd_ctx->hHal); 403 break; 404 405 case NETDEV_DOWN: 406 break; 407 408 case NETDEV_CHANGE: 409 if (true == adapter->isLinkUpSvcNeeded) 410 complete(&adapter->linkup_event_var); 411 break; 412 413 case NETDEV_GOING_DOWN: 414 if (adapter->scan_info.mScanPending != false) { 415 unsigned long rc; 416 INIT_COMPLETION(adapter->scan_info. 417 abortscan_event_var); 418 hdd_abort_mac_scan(adapter->pHddCtx, 419 adapter->sessionId, 420 eCSR_SCAN_ABORT_DEFAULT); 421 rc = wait_for_completion_timeout( 422 &adapter->scan_info.abortscan_event_var, 423 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN)); 424 if (!rc) { 425 hdd_err("Timeout occurred while waiting for abortscan"); 426 } 427 } else { 428 hdd_notice("Scan is not Pending from user"); 429 } 430 break; 431 432 default: 433 break; 434 } 435 436 return NOTIFY_DONE; 437 } 438 439 /** 440 * hdd_netdev_notifier_call() - netdev notifier callback function 441 * @nb: pointer to notifier block 442 * @state: state 443 * @ndev: ndev pointer 444 * 445 * Return: 0 on success, error number otherwise. 446 */ 447 static int hdd_netdev_notifier_call(struct notifier_block *nb, 448 unsigned long state, 449 void *ndev) 450 { 451 int ret; 452 453 cds_ssr_protect(__func__); 454 ret = __hdd_netdev_notifier_call(nb, state, ndev); 455 cds_ssr_unprotect(__func__); 456 457 return ret; 458 } 459 460 struct notifier_block hdd_netdev_notifier = { 461 .notifier_call = hdd_netdev_notifier_call, 462 }; 463 464 /* variable to hold the insmod parameters */ 465 static int con_mode; 466 467 /* Variable to hold connection mode including module parameter con_mode */ 468 static int curr_con_mode; 469 470 /** 471 * hdd_map_nl_chan_width() - Map NL channel width to internal representation 472 * @ch_width: NL channel width 473 * 474 * Converts the NL channel width to the driver's internal representation 475 * 476 * Return: Converted channel width. In case of non matching NL channel width, 477 * CH_WIDTH_MAX will be returned. 478 */ 479 enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width) 480 { 481 switch (ch_width) { 482 case NL80211_CHAN_WIDTH_20_NOHT: 483 case NL80211_CHAN_WIDTH_20: 484 return CH_WIDTH_20MHZ; 485 case NL80211_CHAN_WIDTH_40: 486 return CH_WIDTH_40MHZ; 487 break; 488 case NL80211_CHAN_WIDTH_80: 489 return CH_WIDTH_80MHZ; 490 case NL80211_CHAN_WIDTH_80P80: 491 return CH_WIDTH_80P80MHZ; 492 case NL80211_CHAN_WIDTH_160: 493 return CH_WIDTH_160MHZ; 494 case NL80211_CHAN_WIDTH_5: 495 return CH_WIDTH_5MHZ; 496 case NL80211_CHAN_WIDTH_10: 497 return CH_WIDTH_10MHZ; 498 default: 499 hdd_err("Invalid channel width %d, setting to default", 500 ch_width); 501 return CH_WIDTH_INVALID; 502 } 503 } 504 505 /* wlan_hdd_find_opclass() - Find operating class for a channel 506 * @hal: handler to HAL 507 * @channel: channel id 508 * @bw_offset: bandwidth offset 509 * 510 * Function invokes sme api to find the operating class 511 * 512 * Return: operating class 513 */ 514 uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel, 515 uint8_t bw_offset) 516 { 517 uint8_t opclass = 0; 518 519 sme_get_opclass(hal, channel, bw_offset, &opclass); 520 return opclass; 521 } 522 523 /** 524 * hdd_qdf_trace_enable() - configure initial QDF Trace enable 525 * @moduleId: Module whose trace level is being configured 526 * @bitmask: Bitmask of log levels to be enabled 527 * 528 * Called immediately after the cfg.ini is read in order to configure 529 * the desired trace levels. 530 * 531 * Return: None 532 */ 533 static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask) 534 { 535 QDF_TRACE_LEVEL level; 536 537 /* 538 * if the bitmask is the default value, then a bitmask was not 539 * specified in cfg.ini, so leave the logging level alone (it 540 * will remain at the "compiled in" default value) 541 */ 542 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) { 543 return; 544 } 545 546 /* a mask was specified. start by disabling all logging */ 547 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0); 548 549 /* now cycle through the bitmask until all "set" bits are serviced */ 550 level = QDF_TRACE_LEVEL_FATAL; 551 while (0 != bitmask) { 552 if (bitmask & 1) { 553 qdf_trace_set_value(moduleId, level, 1); 554 } 555 level++; 556 bitmask >>= 1; 557 } 558 } 559 560 /** 561 * wlan_hdd_validate_context() - check the HDD context 562 * @hdd_ctx: HDD context pointer 563 * 564 * Return: 0 if the context is valid. Error code otherwise 565 */ 566 int wlan_hdd_validate_context(hdd_context_t *hdd_ctx) 567 { 568 if (NULL == hdd_ctx || NULL == hdd_ctx->config) { 569 hdd_err("%pS HDD context is Null", (void *)_RET_IP_); 570 return -ENODEV; 571 } 572 573 if (cds_is_driver_recovering()) { 574 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!", 575 (void *)_RET_IP_, cds_get_driver_state()); 576 return -EAGAIN; 577 } 578 579 if (cds_is_load_or_unload_in_progress()) { 580 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x", 581 (void *)_RET_IP_, cds_get_driver_state()); 582 return -EAGAIN; 583 } 584 585 if (hdd_ctx->start_modules_in_progress || 586 hdd_ctx->stop_modules_in_progress) { 587 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!", 588 (void *)_RET_IP_); 589 return -EAGAIN; 590 } 591 592 return 0; 593 } 594 595 /** 596 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA. 597 * @hdd_adapter_t Hdd adapter. 598 * 599 * This function sets the IBSS power save config parameters to WMA 600 * which will send it to firmware if FW supports IBSS power save 601 * before vdev start. 602 * 603 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE 604 * on failure. 605 */ 606 QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter) 607 { 608 int ret; 609 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 610 611 if (hdd_ctx == NULL) { 612 hdd_err("HDD context is null"); 613 return QDF_STATUS_E_FAILURE; 614 } 615 616 ret = wma_cli_set_command(adapter->sessionId, 617 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE, 618 hdd_ctx->config->ibssATIMWinSize, 619 VDEV_CMD); 620 if (0 != ret) { 621 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret); 622 return QDF_STATUS_E_FAILURE; 623 } 624 625 ret = wma_cli_set_command(adapter->sessionId, 626 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED, 627 hdd_ctx->config->isIbssPowerSaveAllowed, 628 VDEV_CMD); 629 if (0 != ret) { 630 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d", 631 ret); 632 return QDF_STATUS_E_FAILURE; 633 } 634 635 ret = wma_cli_set_command(adapter->sessionId, 636 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED, 637 hdd_ctx->config-> 638 isIbssPowerCollapseAllowed, VDEV_CMD); 639 if (0 != ret) { 640 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d", 641 ret); 642 return QDF_STATUS_E_FAILURE; 643 } 644 645 ret = wma_cli_set_command(adapter->sessionId, 646 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX, 647 hdd_ctx->config->isIbssAwakeOnTxRx, 648 VDEV_CMD); 649 if (0 != ret) { 650 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret); 651 return QDF_STATUS_E_FAILURE; 652 } 653 654 ret = wma_cli_set_command(adapter->sessionId, 655 WMA_VDEV_IBSS_SET_INACTIVITY_TIME, 656 hdd_ctx->config->ibssInactivityCount, 657 VDEV_CMD); 658 if (0 != ret) { 659 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret); 660 return QDF_STATUS_E_FAILURE; 661 } 662 663 ret = wma_cli_set_command(adapter->sessionId, 664 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME, 665 hdd_ctx->config->ibssTxSpEndInactivityTime, 666 VDEV_CMD); 667 if (0 != ret) { 668 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d", 669 ret); 670 return QDF_STATUS_E_FAILURE; 671 } 672 673 ret = wma_cli_set_command(adapter->sessionId, 674 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS, 675 hdd_ctx->config->ibssPsWarmupTime, 676 VDEV_CMD); 677 if (0 != ret) { 678 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d", 679 ret); 680 return QDF_STATUS_E_FAILURE; 681 } 682 683 ret = wma_cli_set_command(adapter->sessionId, 684 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW, 685 hdd_ctx->config->ibssPs1RxChainInAtimEnable, 686 VDEV_CMD); 687 if (0 != ret) { 688 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d", 689 ret); 690 return QDF_STATUS_E_FAILURE; 691 } 692 693 return QDF_STATUS_SUCCESS; 694 } 695 696 #define INTF_MACADDR_MASK 0x7 697 698 /** 699 * hdd_update_macaddr() - update mac address 700 * @config: hdd configuration 701 * @hw_macaddr: mac address 702 * 703 * Mac address for multiple virtual interface is found as following 704 * i) The mac address of the first interface is just the actual hw mac address. 705 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to 706 * define the mac address for the remaining interfaces and locally 707 * admistered bit is set. INTF_MACADDR_MASK is based on the number of 708 * supported virtual interfaces, right now this is 0x07 (meaning 8 709 * interface). 710 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1, 711 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc. 712 * 713 * Return: None 714 */ 715 void hdd_update_macaddr(struct hdd_config *config, 716 struct qdf_mac_addr hw_macaddr) 717 { 718 int8_t i; 719 uint8_t macaddr_b3, tmp_br3; 720 721 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes, 722 QDF_MAC_ADDR_SIZE); 723 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) { 724 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes, 725 QDF_MAC_ADDR_SIZE); 726 macaddr_b3 = config->intfMacAddr[i].bytes[3]; 727 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) & 728 INTF_MACADDR_MASK; 729 macaddr_b3 += tmp_br3; 730 731 /* XOR-ing bit-24 of the mac address. This will give enough 732 * mac address range before collision 733 */ 734 macaddr_b3 ^= (1 << 7); 735 736 /* Set locally administered bit */ 737 config->intfMacAddr[i].bytes[0] |= 0x02; 738 config->intfMacAddr[i].bytes[3] = macaddr_b3; 739 hdd_notice("config->intfMacAddr[%d]: " 740 MAC_ADDRESS_STR, i, 741 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes)); 742 } 743 } 744 745 static void hdd_update_tgt_services(hdd_context_t *hdd_ctx, 746 struct wma_tgt_services *cfg) 747 { 748 struct hdd_config *config = hdd_ctx->config; 749 750 /* Set up UAPSD */ 751 config->apUapsdEnabled &= cfg->uapsd; 752 753 /* 11AC mode support */ 754 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac || 755 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac) 756 config->dot11Mode = eHDD_DOT11_MODE_AUTO; 757 758 /* ARP offload: override user setting if invalid */ 759 config->fhostArpOffload &= cfg->arp_offload; 760 761 #ifdef FEATURE_WLAN_SCAN_PNO 762 /* PNO offload */ 763 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload); 764 if (cfg->pno_offload) 765 config->PnoOffload = true; 766 #endif 767 #ifdef FEATURE_WLAN_TDLS 768 config->fEnableTDLSSupport &= cfg->en_tdls; 769 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel && 770 cfg->en_tdls_offchan; 771 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta && 772 cfg->en_tdls_uapsd_buf_sta; 773 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) { 774 config->fEnableTDLSSleepSta = true; 775 } else { 776 config->fEnableTDLSSleepSta = false; 777 } 778 #endif 779 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 780 config->isRoamOffloadEnabled &= cfg->en_roam_offload; 781 #endif 782 sme_update_tgt_services(hdd_ctx->hHal, cfg); 783 784 } 785 786 /** 787 * hdd_update_vdev_nss() - sets the vdev nss 788 * @hdd_ctx: HDD context 789 * 790 * Sets the Nss per vdev type based on INI 791 * 792 * Return: None 793 */ 794 static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx) 795 { 796 struct hdd_config *cfg_ini = hdd_ctx->config; 797 uint8_t max_supp_nss = 1; 798 799 if (cfg_ini->enable2x2) 800 max_supp_nss = 2; 801 802 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss, 803 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24); 804 805 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss, 806 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G); 807 } 808 809 static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx, 810 struct wma_tgt_ht_cap *cfg) 811 { 812 QDF_STATUS status; 813 uint32_t value, val32; 814 uint16_t val16; 815 struct hdd_config *pconfig = hdd_ctx->config; 816 tSirMacHTCapabilityInfo *phtCapInfo; 817 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET]; 818 uint8_t enable_tx_stbc; 819 820 /* check and update RX STBC */ 821 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc) 822 pconfig->enableRxSTBC = cfg->ht_rx_stbc; 823 824 /* get the MPDU density */ 825 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value); 826 827 if (status != QDF_STATUS_SUCCESS) { 828 hdd_err("could not get MPDU DENSITY"); 829 value = 0; 830 } 831 832 /* 833 * MPDU density: 834 * override user's setting if value is larger 835 * than the one supported by target 836 */ 837 if (value > cfg->mpdu_density) { 838 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, 839 cfg->mpdu_density); 840 841 if (status == QDF_STATUS_E_FAILURE) 842 hdd_alert("could not set MPDU DENSITY to CCM"); 843 } 844 845 /* get the HT capability info */ 846 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32); 847 if (QDF_STATUS_SUCCESS != status) { 848 hdd_err("could not get HT capability info"); 849 return; 850 } 851 val16 = (uint16_t) val32; 852 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16; 853 854 /* Set the LDPC capability */ 855 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc; 856 857 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20) 858 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20; 859 860 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40) 861 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40; 862 863 hdd_ctx->num_rf_chains = cfg->num_rf_chains; 864 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc; 865 866 enable_tx_stbc = pconfig->enableTxSTBC; 867 868 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) { 869 pconfig->enable2x2 = 1; 870 } else { 871 pconfig->enable2x2 = 0; 872 enable_tx_stbc = 0; 873 874 /* 1x1 */ 875 /* Update Rx Highest Long GI data Rate */ 876 if (sme_cfg_set_int(hdd_ctx->hHal, 877 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE, 878 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1) 879 == QDF_STATUS_E_FAILURE) { 880 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM"); 881 } 882 883 /* Update Tx Highest Long GI data Rate */ 884 if (sme_cfg_set_int 885 (hdd_ctx->hHal, 886 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE, 887 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) == 888 QDF_STATUS_E_FAILURE) { 889 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail"); 890 } 891 } 892 if (!(cfg->ht_tx_stbc && pconfig->enable2x2)) 893 enable_tx_stbc = 0; 894 phtCapInfo->txSTBC = enable_tx_stbc; 895 896 val32 = val16; 897 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32); 898 if (status != QDF_STATUS_SUCCESS) 899 hdd_alert("could not set HT capability to CCM"); 900 #define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff 901 value = SIZE_OF_SUPPORTED_MCS_SET; 902 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set, 903 &value) == QDF_STATUS_SUCCESS) { 904 hdd_notice("Read MCS rate set"); 905 906 if (pconfig->enable2x2) { 907 for (value = 0; value < cfg->num_rf_chains; value++) 908 mcs_set[value] = 909 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES; 910 911 status = 912 sme_cfg_set_str(hdd_ctx->hHal, 913 WNI_CFG_SUPPORTED_MCS_SET, 914 mcs_set, 915 SIZE_OF_SUPPORTED_MCS_SET); 916 if (status == QDF_STATUS_E_FAILURE) 917 hdd_alert("could not set MCS SET to CCM"); 918 } 919 } 920 #undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 921 } 922 923 static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx, 924 struct wma_tgt_vht_cap *cfg) 925 { 926 QDF_STATUS status; 927 uint32_t value = 0; 928 struct hdd_config *pconfig = hdd_ctx->config; 929 struct wiphy *wiphy = hdd_ctx->wiphy; 930 struct ieee80211_supported_band *band_5g = 931 wiphy->bands[NL80211_BAND_5GHZ]; 932 uint32_t temp = 0; 933 934 if (!band_5g) { 935 hdd_info("5GHz band disabled, skipping capability population"); 936 return; 937 } 938 939 /* Get the current MPDU length */ 940 status = 941 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH, 942 &value); 943 944 if (status != QDF_STATUS_SUCCESS) { 945 hdd_err("could not get MPDU LENGTH"); 946 value = 0; 947 } 948 949 /* 950 * VHT max MPDU length: 951 * override if user configured value is too high 952 * that the target cannot support 953 */ 954 if (value > cfg->vht_max_mpdu) { 955 status = sme_cfg_set_int(hdd_ctx->hHal, 956 WNI_CFG_VHT_MAX_MPDU_LENGTH, 957 cfg->vht_max_mpdu); 958 959 if (status == QDF_STATUS_E_FAILURE) { 960 hdd_alert("could not set VHT MAX MPDU LENGTH"); 961 } 962 } 963 964 /* Get the current supported chan width */ 965 status = sme_cfg_get_int(hdd_ctx->hHal, 966 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET, 967 &value); 968 969 if (status != QDF_STATUS_SUCCESS) { 970 hdd_err("could not get MPDU LENGTH"); 971 value = 0; 972 } 973 974 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp); 975 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS; 976 977 if (pconfig->enable2x2) 978 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2); 979 980 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) == 981 QDF_STATUS_E_FAILURE) { 982 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM"); 983 } 984 985 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp); 986 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS; 987 if (pconfig->enable2x2) 988 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2); 989 990 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) == 991 QDF_STATUS_E_FAILURE) { 992 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM"); 993 } 994 995 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp); 996 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS; 997 if (pconfig->enable2x2) 998 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2); 999 1000 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d", 1001 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2); 1002 1003 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) == 1004 QDF_STATUS_E_FAILURE) { 1005 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM"); 1006 } 1007 /* Get the current RX LDPC setting */ 1008 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP, 1009 &value); 1010 1011 if (status != QDF_STATUS_SUCCESS) { 1012 hdd_err("could not get VHT LDPC CODING CAP"); 1013 value = 0; 1014 } 1015 1016 /* Set the LDPC capability */ 1017 if (value && !cfg->vht_rx_ldpc) { 1018 status = sme_cfg_set_int(hdd_ctx->hHal, 1019 WNI_CFG_VHT_LDPC_CODING_CAP, 1020 cfg->vht_rx_ldpc); 1021 1022 if (status == QDF_STATUS_E_FAILURE) { 1023 hdd_alert("could not set VHT LDPC CODING CAP to CCM"); 1024 } 1025 } 1026 1027 /* Get current GI 80 value */ 1028 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ, 1029 &value); 1030 1031 if (status != QDF_STATUS_SUCCESS) { 1032 hdd_err("could not get SHORT GI 80MHZ"); 1033 value = 0; 1034 } 1035 1036 /* set the Guard interval 80MHz */ 1037 if (value && !cfg->vht_short_gi_80) { 1038 status = sme_cfg_set_int(hdd_ctx->hHal, 1039 WNI_CFG_VHT_SHORT_GI_80MHZ, 1040 cfg->vht_short_gi_80); 1041 1042 if (status == QDF_STATUS_E_FAILURE) { 1043 hdd_alert("could not set SHORT GI 80MHZ to CCM"); 1044 } 1045 } 1046 1047 /* Get current GI 160 value */ 1048 status = sme_cfg_get_int(hdd_ctx->hHal, 1049 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ, 1050 &value); 1051 1052 if (status != QDF_STATUS_SUCCESS) { 1053 hdd_err("could not get SHORT GI 80 & 160"); 1054 value = 0; 1055 } 1056 1057 /* Get VHT TX STBC cap */ 1058 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value); 1059 1060 if (status != QDF_STATUS_SUCCESS) { 1061 hdd_err("could not get VHT TX STBC"); 1062 value = 0; 1063 } 1064 1065 /* VHT TX STBC cap */ 1066 if (value && !cfg->vht_tx_stbc) { 1067 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, 1068 cfg->vht_tx_stbc); 1069 1070 if (status == QDF_STATUS_E_FAILURE) { 1071 hdd_alert("could not set the VHT TX STBC to CCM"); 1072 } 1073 } 1074 1075 /* Get VHT RX STBC cap */ 1076 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value); 1077 1078 if (status != QDF_STATUS_SUCCESS) { 1079 hdd_err("could not get VHT RX STBC"); 1080 value = 0; 1081 } 1082 1083 /* VHT RX STBC cap */ 1084 if (value && !cfg->vht_rx_stbc) { 1085 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, 1086 cfg->vht_rx_stbc); 1087 1088 if (status == QDF_STATUS_E_FAILURE) { 1089 hdd_alert("could not set the VHT RX STBC to CCM"); 1090 } 1091 } 1092 1093 /* Get VHT SU Beamformer cap */ 1094 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP, 1095 &value); 1096 1097 if (status != QDF_STATUS_SUCCESS) { 1098 hdd_err("could not get VHT SU BEAMFORMER CAP"); 1099 value = 0; 1100 } 1101 1102 /* set VHT SU Beamformer cap */ 1103 if (value && !cfg->vht_su_bformer) { 1104 status = sme_cfg_set_int(hdd_ctx->hHal, 1105 WNI_CFG_VHT_SU_BEAMFORMER_CAP, 1106 cfg->vht_su_bformer); 1107 1108 if (status == QDF_STATUS_E_FAILURE) { 1109 hdd_alert("could not set VHT SU BEAMFORMER CAP"); 1110 } 1111 } 1112 1113 /* check and update SU BEAMFORMEE capabality */ 1114 if (pconfig->enableTxBF && !cfg->vht_su_bformee) 1115 pconfig->enableTxBF = cfg->vht_su_bformee; 1116 1117 status = sme_cfg_set_int(hdd_ctx->hHal, 1118 WNI_CFG_VHT_SU_BEAMFORMEE_CAP, 1119 pconfig->enableTxBF); 1120 1121 if (status == QDF_STATUS_E_FAILURE) { 1122 hdd_alert("could not set VHT SU BEAMFORMEE CAP"); 1123 } 1124 1125 /* Get VHT MU Beamformer cap */ 1126 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP, 1127 &value); 1128 1129 if (status != QDF_STATUS_SUCCESS) { 1130 hdd_err("could not get VHT MU BEAMFORMER CAP"); 1131 value = 0; 1132 } 1133 1134 /* set VHT MU Beamformer cap */ 1135 if (value && !cfg->vht_mu_bformer) { 1136 status = sme_cfg_set_int(hdd_ctx->hHal, 1137 WNI_CFG_VHT_MU_BEAMFORMER_CAP, 1138 cfg->vht_mu_bformer); 1139 1140 if (status == QDF_STATUS_E_FAILURE) { 1141 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM"); 1142 } 1143 } 1144 1145 /* Get VHT MU Beamformee cap */ 1146 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP, 1147 &value); 1148 1149 if (status != QDF_STATUS_SUCCESS) { 1150 hdd_err("could not get VHT MU BEAMFORMEE CAP"); 1151 value = 0; 1152 } 1153 1154 /* set VHT MU Beamformee cap */ 1155 if (value && !cfg->vht_mu_bformee) { 1156 status = sme_cfg_set_int(hdd_ctx->hHal, 1157 WNI_CFG_VHT_MU_BEAMFORMEE_CAP, 1158 cfg->vht_mu_bformee); 1159 1160 if (status == QDF_STATUS_E_FAILURE) { 1161 hdd_alert("could not set VHT MU BEAMFORMER CAP"); 1162 } 1163 } 1164 1165 /* Get VHT MAX AMPDU Len exp */ 1166 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, 1167 &value); 1168 1169 if (status != QDF_STATUS_SUCCESS) { 1170 hdd_err("could not get VHT AMPDU LEN"); 1171 value = 0; 1172 } 1173 1174 /* 1175 * VHT max AMPDU len exp: 1176 * override if user configured value is too high 1177 * that the target cannot support. 1178 * Even though Rome publish ampdu_len=7, it can 1179 * only support 4 because of some h/w bug. 1180 */ 1181 1182 if (value > cfg->vht_max_ampdu_len_exp) { 1183 status = sme_cfg_set_int(hdd_ctx->hHal, 1184 WNI_CFG_VHT_AMPDU_LEN_EXPONENT, 1185 cfg->vht_max_ampdu_len_exp); 1186 1187 if (status == QDF_STATUS_E_FAILURE) { 1188 hdd_alert("could not set the VHT AMPDU LEN EXP"); 1189 } 1190 } 1191 1192 /* Get VHT TXOP PS CAP */ 1193 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value); 1194 1195 if (status != QDF_STATUS_SUCCESS) { 1196 hdd_err("could not get VHT TXOP PS"); 1197 value = 0; 1198 } 1199 1200 /* set VHT TXOP PS cap */ 1201 if (value && !cfg->vht_txop_ps) { 1202 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, 1203 cfg->vht_txop_ps); 1204 1205 if (status == QDF_STATUS_E_FAILURE) { 1206 hdd_alert("could not set the VHT TXOP PS"); 1207 } 1208 } 1209 1210 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu) 1211 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; 1212 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu) 1213 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; 1214 else 1215 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; 1216 1217 1218 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) 1219 band_5g->vht_cap.cap |= 1220 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; 1221 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) 1222 band_5g->vht_cap.cap |= 1223 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; 1224 1225 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC) 1226 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; 1227 1228 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ) 1229 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; 1230 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ) 1231 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160; 1232 1233 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC) 1234 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC; 1235 1236 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS) 1237 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; 1238 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS) 1239 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2; 1240 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS) 1241 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3; 1242 1243 band_5g->vht_cap.cap |= 1244 (cfg->vht_max_ampdu_len_exp << 1245 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); 1246 1247 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER) 1248 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; 1249 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE) 1250 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; 1251 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER) 1252 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; 1253 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE) 1254 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; 1255 1256 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS) 1257 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS; 1258 1259 } 1260 1261 /** 1262 * hdd_generate_macaddr_auto() - Auto-generate mac address 1263 * @hdd_ctx: Pointer to the HDD context 1264 * 1265 * Auto-generate mac address using device serial number. 1266 * Keep the first 3 bytes of OUI as before and replace 1267 * the last 3 bytes with the lower 3 bytes of serial number. 1268 * 1269 * Return: 0 for success 1270 * Non zero failure code for errors 1271 */ 1272 static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx) 1273 { 1274 unsigned int serialno = 0; 1275 struct qdf_mac_addr mac_addr = { 1276 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00} 1277 }; 1278 1279 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev); 1280 if (serialno == 0) 1281 return -EINVAL; 1282 1283 serialno &= 0x00ffffff; 1284 1285 mac_addr.bytes[3] = (serialno >> 16) & 0xff; 1286 mac_addr.bytes[4] = (serialno >> 8) & 0xff; 1287 mac_addr.bytes[5] = serialno & 0xff; 1288 1289 hdd_update_macaddr(hdd_ctx->config, mac_addr); 1290 return 0; 1291 } 1292 1293 /** 1294 * hdd_update_ra_rate_limit() - Update RA rate limit from target 1295 * configuration to cfg_ini in HDD 1296 * @hdd_ctx: Pointer to hdd_ctx 1297 * @cfg: target configuration 1298 * 1299 * Return: None 1300 */ 1301 #ifdef FEATURE_WLAN_RA_FILTERING 1302 static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx, 1303 struct wma_tgt_cfg *cfg) 1304 { 1305 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled; 1306 } 1307 #else 1308 static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx, 1309 struct wma_tgt_cfg *cfg) 1310 { 1311 } 1312 #endif 1313 1314 void hdd_update_tgt_cfg(void *context, void *param) 1315 { 1316 hdd_context_t *hdd_ctx = (hdd_context_t *) context; 1317 struct wma_tgt_cfg *cfg = param; 1318 uint8_t temp_band_cap; 1319 struct cds_config_info *cds_cfg = cds_get_ini_config(); 1320 1321 if (cds_cfg) { 1322 if (hdd_ctx->config->enable_sub_20_channel_width != 1323 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) { 1324 hdd_err("User requested sub 20 MHz channel width but unsupported by FW."); 1325 cds_cfg->sub_20_channel_width = 1326 WLAN_SUB_20_CH_WIDTH_NONE; 1327 } else { 1328 cds_cfg->sub_20_channel_width = 1329 hdd_ctx->config->enable_sub_20_channel_width; 1330 } 1331 } 1332 1333 /* first store the INI band capability */ 1334 temp_band_cap = hdd_ctx->config->nBandCapability; 1335 1336 hdd_ctx->config->nBandCapability = cfg->band_cap; 1337 1338 /* now overwrite the target band capability with INI 1339 setting if INI setting is a subset */ 1340 1341 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) && 1342 (temp_band_cap != eCSR_BAND_ALL)) 1343 hdd_ctx->config->nBandCapability = temp_band_cap; 1344 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) && 1345 (temp_band_cap != eCSR_BAND_ALL) && 1346 (hdd_ctx->config->nBandCapability != temp_band_cap)) { 1347 hdd_warn("ini BandCapability not supported by the target"); 1348 } 1349 1350 if (!cds_is_driver_recovering()) { 1351 hdd_ctx->reg.reg_domain = cfg->reg_domain; 1352 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext; 1353 } 1354 1355 /* This can be extended to other configurations like ht, vht cap... */ 1356 1357 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) { 1358 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr); 1359 hdd_ctx->update_mac_addr_to_fw = false; 1360 } else { 1361 static struct qdf_mac_addr default_mac_addr = { 1362 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF} 1363 }; 1364 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0], 1365 &default_mac_addr)) { 1366 if (hdd_generate_macaddr_auto(hdd_ctx) != 0) 1367 hdd_err("Fail to auto-generate MAC, using MAC from ini file " 1368 MAC_ADDRESS_STR, 1369 MAC_ADDR_ARRAY(hdd_ctx->config-> 1370 intfMacAddr[0].bytes)); 1371 } else { 1372 hdd_err("Invalid MAC passed from target, using MAC from ini file " 1373 MAC_ADDRESS_STR, 1374 MAC_ADDR_ARRAY(hdd_ctx->config-> 1375 intfMacAddr[0].bytes)); 1376 } 1377 hdd_ctx->update_mac_addr_to_fw = true; 1378 } 1379 1380 hdd_ctx->target_fw_version = cfg->target_fw_version; 1381 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext; 1382 1383 hdd_ctx->max_intf_count = cfg->max_intf_count; 1384 1385 hdd_lpass_target_config(hdd_ctx, cfg); 1386 hdd_green_ap_target_config(hdd_ctx, cfg); 1387 1388 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support; 1389 hdd_update_tgt_services(hdd_ctx, &cfg->services); 1390 1391 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap); 1392 1393 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap); 1394 1395 hdd_update_vdev_nss(hdd_ctx); 1396 1397 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap; 1398 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap; 1399 hdd_info("fine_time_meas_cap: 0x%x", 1400 hdd_ctx->config->fine_time_meas_cap); 1401 1402 hdd_ctx->current_antenna_mode = 1403 (hdd_ctx->config->enable2x2 == 0x01) ? 1404 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1; 1405 hdd_info("Init current antenna mode: %d", 1406 hdd_ctx->current_antenna_mode); 1407 1408 hdd_info("Target BPF %d Host BPF %d", 1409 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable); 1410 hdd_ctx->bpf_enabled = (cfg->bpf_enabled && 1411 hdd_ctx->config->bpf_packet_filter_enable); 1412 hdd_update_ra_rate_limit(hdd_ctx, cfg); 1413 1414 /* 1415 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX 1416 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to 1417 * configure the STA mode wow pattern. 1418 */ 1419 if (hdd_ctx->bpf_enabled) 1420 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX; 1421 1422 hdd_ctx->wmi_max_len = cfg->wmi_max_len; 1423 1424 /* Configure NAN datapath features */ 1425 hdd_nan_datapath_target_config(hdd_ctx, cfg); 1426 } 1427 1428 /** 1429 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel 1430 * @context: HDD context pointer 1431 * @param: HDD radar indication pointer 1432 * 1433 * This function is invoked in atomic context when a radar 1434 * is found on the SAP current operating channel and Data Tx 1435 * from netif has to be stopped to honor the DFS regulations. 1436 * Actions: Stop the netif Tx queues,Indicate Radar present 1437 * in HDD context for future usage. 1438 * 1439 * Return: true to allow radar indication to host else false 1440 */ 1441 bool hdd_dfs_indicate_radar(void *context, void *param) 1442 { 1443 hdd_context_t *hdd_ctx = (hdd_context_t *) context; 1444 struct wma_dfs_radar_ind *hdd_radar_event = 1445 (struct wma_dfs_radar_ind *)param; 1446 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 1447 hdd_adapter_t *adapter; 1448 QDF_STATUS status; 1449 hdd_ap_ctx_t *ap_ctx; 1450 1451 if (!hdd_ctx || !hdd_radar_event || 1452 hdd_ctx->config->disableDFSChSwitch) 1453 return true; 1454 1455 if (true == hdd_radar_event->dfs_radar_status) { 1456 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) { 1457 /* 1458 * Application already triggered channel switch 1459 * on current channel, so return here. 1460 */ 1461 return false; 1462 } 1463 1464 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 1465 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 1466 adapter = adapterNode->pAdapter; 1467 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); 1468 if ((QDF_SAP_MODE == adapter->device_mode || 1469 QDF_P2P_GO_MODE == adapter->device_mode) && 1470 (CHANNEL_STATE_DFS == 1471 cds_get_channel_state(ap_ctx->operatingChannel))) { 1472 WLAN_HDD_GET_AP_CTX_PTR(adapter)-> 1473 dfs_cac_block_tx = true; 1474 hdd_info("tx blocked for session:%d", 1475 adapter->sessionId); 1476 } 1477 1478 status = hdd_get_next_adapter(hdd_ctx, 1479 adapterNode, 1480 &pNext); 1481 adapterNode = pNext; 1482 } 1483 } 1484 1485 return true; 1486 } 1487 1488 /** 1489 * hdd_is_valid_mac_address() - validate MAC address 1490 * @pMacAddr: Pointer to the input MAC address 1491 * 1492 * This function validates whether the given MAC address is valid or not 1493 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX 1494 * where X is the hexa decimal digit character and separated by ':' 1495 * This algorithm works even if MAC address is not separated by ':' 1496 * 1497 * This code checks given input string mac contains exactly 12 hexadecimal 1498 * digits and a separator colon : appears in the input string only after 1499 * an even number of hex digits. 1500 * 1501 * Return: 1 for valid and 0 for invalid 1502 */ 1503 bool hdd_is_valid_mac_address(const uint8_t *pMacAddr) 1504 { 1505 int xdigit = 0; 1506 int separator = 0; 1507 while (*pMacAddr) { 1508 if (isxdigit(*pMacAddr)) { 1509 xdigit++; 1510 } else if (':' == *pMacAddr) { 1511 if (0 == xdigit || ((xdigit / 2) - 1) != separator) 1512 break; 1513 1514 ++separator; 1515 } else { 1516 /* Invalid MAC found */ 1517 return 0; 1518 } 1519 ++pMacAddr; 1520 } 1521 return xdigit == 12 && (separator == 5 || separator == 0); 1522 } 1523 1524 /** 1525 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device. 1526 * @dev: Handle to struct net_device to be updated. 1527 * 1528 * Return: None 1529 */ 1530 static void hdd_mon_mode_ether_setup(struct net_device *dev) 1531 { 1532 dev->header_ops = NULL; 1533 dev->type = ARPHRD_IEEE80211_RADIOTAP; 1534 dev->hard_header_len = ETH_HLEN; 1535 dev->mtu = ETH_DATA_LEN; 1536 dev->addr_len = ETH_ALEN; 1537 dev->tx_queue_len = 1000; /* Ethernet wants good queues */ 1538 dev->flags = IFF_BROADCAST|IFF_MULTICAST; 1539 dev->priv_flags |= IFF_TX_SKB_SHARING; 1540 1541 memset(dev->broadcast, 0xFF, ETH_ALEN); 1542 } 1543 1544 /** 1545 * __hdd__mon_open() - HDD Open function 1546 * @dev: Pointer to net_device structure 1547 * 1548 * This is called in response to ifconfig up 1549 * 1550 * Return: 0 for success; non-zero for failure 1551 */ 1552 static int __hdd_mon_open(struct net_device *dev) 1553 { 1554 int ret; 1555 1556 ENTER_DEV(dev); 1557 hdd_mon_mode_ether_setup(dev); 1558 ret = hdd_set_mon_rx_cb(dev); 1559 return ret; 1560 } 1561 1562 /** 1563 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR 1564 * @dev: Pointer to net_device structure 1565 * 1566 * This is called in response to ifconfig up 1567 * 1568 * Return: 0 for success; non-zero for failure 1569 */ 1570 static int hdd_mon_open(struct net_device *dev) 1571 { 1572 int ret; 1573 1574 cds_ssr_protect(__func__); 1575 ret = __hdd_mon_open(dev); 1576 cds_ssr_unprotect(__func__); 1577 1578 return ret; 1579 } 1580 1581 /** 1582 * hdd_start_adapter() - Wrapper function for device specific adapter 1583 * @adapter: pointer to HDD adapter 1584 * 1585 * This function is called to start the device specific adapter for 1586 * the mode passed in the adapter's device_mode. 1587 * 1588 * Return: 0 for success; non-zero for failure 1589 */ 1590 int hdd_start_adapter(hdd_adapter_t *adapter) 1591 { 1592 1593 int ret; 1594 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode; 1595 1596 ENTER_DEV(adapter->dev); 1597 hdd_info("Start_adapter for mode : %d", adapter->device_mode); 1598 1599 switch (device_mode) { 1600 case QDF_P2P_CLIENT_MODE: 1601 case QDF_P2P_DEVICE_MODE: 1602 case QDF_OCB_MODE: 1603 case QDF_STA_MODE: 1604 case QDF_MONITOR_MODE: 1605 ret = hdd_start_station_adapter(adapter); 1606 if (ret) 1607 goto err_start_adapter; 1608 break; 1609 case QDF_P2P_GO_MODE: 1610 case QDF_SAP_MODE: 1611 ret = hdd_start_ap_adapter(adapter); 1612 if (ret) 1613 goto err_start_adapter; 1614 break; 1615 case QDF_IBSS_MODE: 1616 /* 1617 * For IBSS interface is initialized as part of 1618 * hdd_init_station_mode() 1619 */ 1620 return 0; 1621 case QDF_FTM_MODE: 1622 ret = hdd_start_ftm_adapter(adapter); 1623 if (ret) 1624 goto err_start_adapter; 1625 break; 1626 default: 1627 hdd_err("Invalid session type %d", device_mode); 1628 QDF_ASSERT(0); 1629 goto err_start_adapter; 1630 } 1631 if (hdd_set_fw_params(adapter)) 1632 hdd_err("Failed to set the FW params for the adapter!"); 1633 1634 /* 1635 * Action frame registered in one adapter which will 1636 * applicable to all interfaces 1637 */ 1638 wlan_hdd_cfg80211_register_frames(adapter); 1639 EXIT(); 1640 return 0; 1641 err_start_adapter: 1642 return -EINVAL; 1643 } 1644 1645 /** 1646 * hdd_enable_power_management() - API to Enable Power Management 1647 * 1648 * API invokes Bus Interface Layer power management functionality 1649 * 1650 * Return: None 1651 */ 1652 static void hdd_enable_power_management(void) 1653 { 1654 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 1655 1656 if (!hif_ctx) { 1657 hdd_err("Bus Interface Context is Invalid"); 1658 return; 1659 } 1660 1661 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled()); 1662 } 1663 1664 /** 1665 * hdd_disable_power_management() - API to disable Power Management 1666 * 1667 * API disable Bus Interface Layer Power management functionality 1668 * 1669 * Return: None 1670 */ 1671 static void hdd_disable_power_management(void) 1672 { 1673 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 1674 1675 if (!hif_ctx) { 1676 hdd_err("Bus Interface Context is Invalid"); 1677 return; 1678 } 1679 1680 hif_disable_power_management(hif_ctx); 1681 } 1682 1683 /** 1684 * hdd_wlan_start_modules() - Single driver state machine for starting modules 1685 * @hdd_ctx: HDD context 1686 * @adapter: HDD adapter 1687 * @reinit: flag to indicate from SSR or normal path 1688 * 1689 * This function maintains the driver state machine it will be invoked from 1690 * startup, reinit and change interface. Depending on the driver state shall 1691 * perform the opening of the modules. 1692 * 1693 * Return: 0 for success; non-zero for failure 1694 */ 1695 int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, 1696 bool reinit) 1697 { 1698 int ret; 1699 qdf_device_t qdf_dev; 1700 QDF_STATUS status; 1701 p_cds_contextType p_cds_context; 1702 bool unint = false; 1703 void *hif_ctx; 1704 1705 ENTER(); 1706 1707 p_cds_context = cds_get_global_context(); 1708 if (!p_cds_context) { 1709 hdd_err("Global Context is NULL"); 1710 QDF_ASSERT(0); 1711 return -EINVAL; 1712 } 1713 1714 hdd_info("start modules called in state! :%d reinit: %d", 1715 hdd_ctx->driver_status, reinit); 1716 1717 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 1718 if (!qdf_dev) { 1719 hdd_err("QDF Device Context is Invalid return"); 1720 return -EINVAL; 1721 } 1722 1723 mutex_lock(&hdd_ctx->iface_change_lock); 1724 hdd_ctx->start_modules_in_progress = true; 1725 1726 if (QDF_TIMER_STATE_RUNNING == 1727 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) { 1728 1729 hdd_set_idle_ps_config(hdd_ctx, false); 1730 hdd_info("Interface change Timer running Stop timer"); 1731 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer); 1732 } 1733 1734 switch (hdd_ctx->driver_status) { 1735 case DRIVER_MODULES_UNINITIALIZED: 1736 unint = true; 1737 /* Fall through dont add break here */ 1738 case DRIVER_MODULES_CLOSED: 1739 if (!reinit && !unint) { 1740 ret = pld_power_on(qdf_dev->dev); 1741 if (ret) { 1742 hdd_err("Failed to Powerup the device: %d", ret); 1743 goto release_lock; 1744 } 1745 } 1746 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid, 1747 qdf_dev->bus_type, 1748 (reinit == true) ? HIF_ENABLE_TYPE_REINIT : 1749 HIF_ENABLE_TYPE_PROBE); 1750 if (ret) { 1751 hdd_err("Failed to open hif: %d", ret); 1752 goto power_down; 1753 } 1754 1755 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 1756 if (!hif_ctx) { 1757 hdd_err("hif context is null!!"); 1758 goto power_down; 1759 } 1760 1761 status = ol_cds_init(qdf_dev, hif_ctx); 1762 if (status != QDF_STATUS_SUCCESS) { 1763 hdd_err("No Memory to Create BMI Context :%d", status); 1764 goto hif_close; 1765 } 1766 1767 ret = hdd_update_config(hdd_ctx); 1768 if (ret) { 1769 hdd_err("Failed to update configuration :%d", ret); 1770 goto ol_cds_free; 1771 } 1772 1773 status = cds_open(); 1774 if (!QDF_IS_STATUS_SUCCESS(status)) { 1775 hdd_err("Failed to Open CDS: %d", status); 1776 goto ol_cds_free; 1777 } 1778 1779 hdd_ctx->driver_status = DRIVER_MODULES_OPENED; 1780 1781 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME); 1782 1783 status = cds_pre_enable(hdd_ctx->pcds_context); 1784 if (!QDF_IS_STATUS_SUCCESS(status)) { 1785 hdd_err("Failed to pre-enable CDS: %d", status); 1786 goto close; 1787 } 1788 1789 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { 1790 sme_register_ftm_msg_processor(hdd_ctx->hHal, 1791 hdd_ftm_mc_process_msg); 1792 break; 1793 } 1794 if (unint) { 1795 hdd_info("In phase-1 initialization don't enable modules"); 1796 break; 1797 } 1798 /* Fall through dont add break here */ 1799 case DRIVER_MODULES_OPENED: 1800 if (!adapter) { 1801 hdd_alert("adapter is Null"); 1802 goto close; 1803 } 1804 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { 1805 hdd_err("in ftm mode, no need to configure cds modules"); 1806 break; 1807 } 1808 if (hdd_configure_cds(hdd_ctx, adapter)) { 1809 hdd_err("Failed to Enable cds modules"); 1810 goto close; 1811 } 1812 hdd_enable_power_management(); 1813 hdd_info("Driver Modules Successfully Enabled"); 1814 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED; 1815 break; 1816 case DRIVER_MODULES_ENABLED: 1817 hdd_info("Driver modules already Enabled"); 1818 break; 1819 default: 1820 hdd_err("WLAN start invoked in wrong state! :%d\n", 1821 hdd_ctx->driver_status); 1822 goto release_lock; 1823 } 1824 hdd_ctx->start_modules_in_progress = false; 1825 mutex_unlock(&hdd_ctx->iface_change_lock); 1826 EXIT(); 1827 return 0; 1828 1829 close: 1830 cds_close(p_cds_context); 1831 1832 ol_cds_free: 1833 ol_cds_free(); 1834 1835 hif_close: 1836 hdd_hif_close(p_cds_context->pHIFContext); 1837 power_down: 1838 if (!reinit && !unint) 1839 pld_power_off(qdf_dev->dev); 1840 release_lock: 1841 hdd_ctx->start_modules_in_progress = false; 1842 mutex_unlock(&hdd_ctx->iface_change_lock); 1843 EXIT(); 1844 return -EINVAL; 1845 } 1846 1847 /** 1848 * __hdd_open() - HDD Open function 1849 * @dev: Pointer to net_device structure 1850 * 1851 * This is called in response to ifconfig up 1852 * 1853 * Return: 0 for success; non-zero for failure 1854 */ 1855 static int __hdd_open(struct net_device *dev) 1856 { 1857 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 1858 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1859 int ret; 1860 1861 ENTER_DEV(dev); 1862 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST, 1863 adapter->sessionId, adapter->device_mode)); 1864 1865 ret = wlan_hdd_validate_context(hdd_ctx); 1866 if (ret) 1867 return ret; 1868 1869 1870 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false); 1871 if (ret) { 1872 hdd_err("Failed to start WLAN modules return"); 1873 return -ret; 1874 } 1875 1876 1877 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) { 1878 ret = hdd_start_adapter(adapter); 1879 if (ret) { 1880 hdd_err("Failed to start adapter :%d", 1881 adapter->device_mode); 1882 return ret; 1883 } 1884 } 1885 1886 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags); 1887 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { 1888 hdd_info("Enabling Tx Queues"); 1889 /* Enable TX queues only when we are connected */ 1890 wlan_hdd_netif_queue_control(adapter, 1891 WLAN_START_ALL_NETIF_QUEUE, 1892 WLAN_CONTROL_PATH); 1893 } 1894 1895 /* Enable carrier and transmit queues for NDI */ 1896 if (WLAN_HDD_IS_NDI(adapter)) { 1897 hdd_notice("Enabling Tx Queues"); 1898 wlan_hdd_netif_queue_control(adapter, 1899 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER, 1900 WLAN_CONTROL_PATH); 1901 } 1902 1903 return ret; 1904 } 1905 1906 1907 /** 1908 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR 1909 * @dev: Pointer to net_device structure 1910 * 1911 * This is called in response to ifconfig up 1912 * 1913 * Return: 0 for success; non-zero for failure 1914 */ 1915 static int hdd_open(struct net_device *dev) 1916 { 1917 int ret; 1918 1919 cds_ssr_protect(__func__); 1920 ret = __hdd_open(dev); 1921 cds_ssr_unprotect(__func__); 1922 1923 return ret; 1924 } 1925 1926 /** 1927 * __hdd_stop() - HDD stop function 1928 * @dev: Pointer to net_device structure 1929 * 1930 * This is called in response to ifconfig down 1931 * 1932 * Return: 0 for success; non-zero for failure 1933 */ 1934 static int __hdd_stop(struct net_device *dev) 1935 { 1936 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 1937 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 1938 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL; 1939 int ret; 1940 bool close_modules = true; 1941 QDF_STATUS status; 1942 1943 ENTER_DEV(dev); 1944 1945 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST, 1946 adapter->sessionId, adapter->device_mode)); 1947 1948 ret = wlan_hdd_validate_context(hdd_ctx); 1949 if (0 != ret) 1950 return ret; 1951 1952 /* Nothing to be done if the interface is not opened */ 1953 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) { 1954 hdd_err("NETDEV Interface is not OPENED"); 1955 return -ENODEV; 1956 } 1957 1958 /* Make sure the interface is marked as closed */ 1959 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags); 1960 hdd_notice("Disabling OS Tx queues"); 1961 1962 /* 1963 * Disable TX on the interface, after this hard_start_xmit() will not 1964 * be called on that interface 1965 */ 1966 hdd_notice("Disabling queues"); 1967 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER, 1968 WLAN_CONTROL_PATH); 1969 1970 /* 1971 * NAN data interface is different in some sense. The traffic on NDI is 1972 * bursty in nature and depends on the need to transfer. The service 1973 * layer may down the interface after the usage and up again when 1974 * required. In some sense, the NDI is expected to be available 1975 * (like SAP) iface until NDI delete request is issued by the service 1976 * layer. Skip BSS termination and adapter deletion for NAN Data 1977 * interface (NDI). 1978 */ 1979 if (WLAN_HDD_IS_NDI(adapter)) 1980 return 0; 1981 1982 /* 1983 * The interface is marked as down for outside world (aka kernel) 1984 * But the driver is pretty much alive inside. The driver needs to 1985 * tear down the existing connection on the netdev (session) 1986 * cleanup the data pipes and wait until the control plane is stabilized 1987 * for this interface. The call also needs to wait until the above 1988 * mentioned actions are completed before returning to the caller. 1989 * Notice that the hdd_stop_adapter is requested not to close the session 1990 * That is intentional to be able to scan if it is a STA/P2P interface 1991 */ 1992 hdd_stop_adapter(hdd_ctx, adapter, true); 1993 1994 /* DeInit the adapter. This ensures datapath cleanup as well */ 1995 hdd_deinit_adapter(hdd_ctx, adapter, true); 1996 1997 1998 /* 1999 * Find if any iface is up. If any iface is up then can't put device to 2000 * sleep/power save mode 2001 */ 2002 status = hdd_get_front_adapter(hdd_ctx, &adapternode); 2003 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) { 2004 if (test_bit(DEVICE_IFACE_OPENED, 2005 &adapternode->pAdapter->event_flags)) { 2006 hdd_info("Still other ifaces are up cannot close modules"); 2007 close_modules = false; 2008 break; 2009 } 2010 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next); 2011 adapternode = next; 2012 2013 } 2014 2015 if (close_modules) { 2016 hdd_info("Closing all modules from the hdd_stop"); 2017 qdf_mc_timer_start(&hdd_ctx->iface_change_timer, 2018 hdd_ctx->config->iface_change_wait_time 2019 * 50000); 2020 } 2021 2022 EXIT(); 2023 return 0; 2024 } 2025 2026 /** 2027 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR 2028 * @dev: pointer to net_device structure 2029 * 2030 * This is called in response to ifconfig down 2031 * 2032 * Return: 0 for success and error number for failure 2033 */ 2034 static int hdd_stop(struct net_device *dev) 2035 { 2036 int ret; 2037 2038 cds_ssr_protect(__func__); 2039 ret = __hdd_stop(dev); 2040 cds_ssr_unprotect(__func__); 2041 2042 return ret; 2043 } 2044 2045 /** 2046 * __hdd_uninit() - HDD uninit function 2047 * @dev: Pointer to net_device structure 2048 * 2049 * This is called during the netdev unregister to uninitialize all data 2050 * associated with the device 2051 * 2052 * Return: None 2053 */ 2054 static void __hdd_uninit(struct net_device *dev) 2055 { 2056 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 2057 2058 ENTER_DEV(dev); 2059 2060 do { 2061 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { 2062 hdd_alert("Invalid magic"); 2063 break; 2064 } 2065 2066 if (NULL == adapter->pHddCtx) { 2067 hdd_alert("NULL hdd_ctx"); 2068 break; 2069 } 2070 2071 if (dev != adapter->dev) { 2072 hdd_alert("Invalid device reference"); 2073 /* 2074 * we haven't validated all cases so let this go for 2075 * now 2076 */ 2077 } 2078 2079 hdd_deinit_adapter(adapter->pHddCtx, adapter, true); 2080 2081 /* after uninit our adapter structure will no longer be valid */ 2082 adapter->dev = NULL; 2083 adapter->magic = 0; 2084 } while (0); 2085 2086 EXIT(); 2087 } 2088 2089 /** 2090 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR 2091 * @dev: pointer to net_device structure 2092 * 2093 * This is called during the netdev unregister to uninitialize all data 2094 * associated with the device 2095 * 2096 * Return: none 2097 */ 2098 static void hdd_uninit(struct net_device *dev) 2099 { 2100 cds_ssr_protect(__func__); 2101 __hdd_uninit(dev); 2102 cds_ssr_unprotect(__func__); 2103 } 2104 2105 static int hdd_open_cesium_nl_sock(void) 2106 { 2107 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) 2108 struct netlink_kernel_cfg cfg = { 2109 .groups = WLAN_NLINK_MCAST_GRP_ID, 2110 .input = NULL 2111 }; 2112 #endif 2113 int ret = 0; 2114 2115 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) 2116 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM, 2117 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) 2118 THIS_MODULE, 2119 #endif 2120 &cfg); 2121 #else 2122 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM, 2123 WLAN_NLINK_MCAST_GRP_ID, 2124 NULL, NULL, THIS_MODULE); 2125 #endif 2126 2127 if (cesium_nl_srv_sock == NULL) { 2128 hdd_err("NLINK: cesium netlink_kernel_create failed"); 2129 ret = -ECONNREFUSED; 2130 } 2131 2132 return ret; 2133 } 2134 2135 static void hdd_close_cesium_nl_sock(void) 2136 { 2137 if (NULL != cesium_nl_srv_sock) { 2138 netlink_kernel_release(cesium_nl_srv_sock); 2139 cesium_nl_srv_sock = NULL; 2140 } 2141 } 2142 2143 /** 2144 * __hdd_set_mac_address() - set the user specified mac address 2145 * @dev: Pointer to the net device. 2146 * @addr: Pointer to the sockaddr. 2147 * 2148 * This function sets the user specified mac address using 2149 * the command ifconfig wlanX hw ether <mac adress>. 2150 * 2151 * Return: 0 for success, non zero for failure 2152 */ 2153 static int __hdd_set_mac_address(struct net_device *dev, void *addr) 2154 { 2155 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 2156 hdd_context_t *hdd_ctx; 2157 struct sockaddr *psta_mac_addr = addr; 2158 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; 2159 int ret; 2160 2161 ENTER_DEV(dev); 2162 2163 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 2164 ret = wlan_hdd_validate_context(hdd_ctx); 2165 if (0 != ret) 2166 return ret; 2167 2168 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN); 2169 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN); 2170 2171 EXIT(); 2172 return qdf_ret_status; 2173 } 2174 2175 /** 2176 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address() 2177 * function from SSR 2178 * @dev: pointer to net_device structure 2179 * @addr: Pointer to the sockaddr 2180 * 2181 * This function sets the user specified mac address using 2182 * the command ifconfig wlanX hw ether <mac adress>. 2183 * 2184 * Return: 0 for success. 2185 */ 2186 static int hdd_set_mac_address(struct net_device *dev, void *addr) 2187 { 2188 int ret; 2189 2190 cds_ssr_protect(__func__); 2191 ret = __hdd_set_mac_address(dev, addr); 2192 cds_ssr_unprotect(__func__); 2193 2194 return ret; 2195 } 2196 2197 uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx) 2198 { 2199 int i; 2200 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) { 2201 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i))) 2202 break; 2203 } 2204 2205 if (QDF_MAX_CONCURRENCY_PERSONA == i) 2206 return NULL; 2207 2208 hdd_ctx->config->intfAddrMask |= (1 << i); 2209 return &hdd_ctx->config->intfMacAddr[i].bytes[0]; 2210 } 2211 2212 void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr) 2213 { 2214 int i; 2215 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) { 2216 if (!memcmp(releaseAddr, 2217 &hdd_ctx->config->intfMacAddr[i].bytes[0], 2218 6)) { 2219 hdd_ctx->config->intfAddrMask &= ~(1 << i); 2220 break; 2221 } 2222 } 2223 return; 2224 } 2225 2226 #ifdef WLAN_FEATURE_PACKET_FILTERING 2227 /** 2228 * __hdd_set_multicast_list() - set the multicast address list 2229 * @dev: Pointer to the WLAN device. 2230 * @skb: Pointer to OS packet (sk_buff). 2231 * 2232 * This funciton sets the multicast address list. 2233 * 2234 * Return: None 2235 */ 2236 static void __hdd_set_multicast_list(struct net_device *dev) 2237 { 2238 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); 2239 int mc_count; 2240 int i = 0, status; 2241 struct netdev_hw_addr *ha; 2242 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 2243 static const uint8_t ipv6_router_solicitation[] 2244 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02}; 2245 2246 ENTER_DEV(dev); 2247 2248 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) 2249 return; 2250 2251 status = wlan_hdd_validate_context(hdd_ctx); 2252 if (0 != status) 2253 return; 2254 2255 if (dev->flags & IFF_ALLMULTI) { 2256 hdd_notice("allow all multicast frames"); 2257 adapter->mc_addr_list.mc_cnt = 0; 2258 } else { 2259 mc_count = netdev_mc_count(dev); 2260 hdd_notice("mc_count : %u", mc_count); 2261 2262 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) { 2263 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering", 2264 WLAN_HDD_MAX_MC_ADDR_LIST); 2265 wlan_hdd_set_mc_addr_list(adapter, false); 2266 adapter->mc_addr_list.mc_cnt = 0; 2267 return; 2268 } 2269 2270 adapter->mc_addr_list.mc_cnt = mc_count; 2271 2272 netdev_for_each_mc_addr(ha, dev) { 2273 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR, 2274 i, MAC_ADDR_ARRAY(ha->addr)); 2275 2276 if (i == mc_count) 2277 break; 2278 /* 2279 * Skip following addresses: 2280 * 1)IPv6 router solicitation address 2281 * 2)Any other address pattern if its set during 2282 * RXFILTER REMOVE driver command based on 2283 * addr_filter_pattern 2284 */ 2285 if ((!memcmp(ha->addr, ipv6_router_solicitation, 2286 ETH_ALEN)) || 2287 (adapter->addr_filter_pattern && (!memcmp(ha->addr, 2288 &adapter->addr_filter_pattern, 1)))) { 2289 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR, 2290 MAC_ADDR_ARRAY(ha->addr)); 2291 adapter->mc_addr_list.mc_cnt--; 2292 continue; 2293 } 2294 2295 memset(&(adapter->mc_addr_list.addr[i][0]), 0, 2296 ETH_ALEN); 2297 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr, 2298 ETH_ALEN); 2299 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i, 2300 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i])); 2301 i++; 2302 } 2303 } 2304 if (hdd_ctx->config->active_mode_offload) { 2305 hdd_info("enable mc filtering"); 2306 wlan_hdd_set_mc_addr_list(adapter, true); 2307 } else { 2308 hdd_info("skip mc filtering enable it during cfg80211 suspend"); 2309 } 2310 EXIT(); 2311 return; 2312 } 2313 2314 /** 2315 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list 2316 * @dev: pointer to net_device 2317 * 2318 * Return: none 2319 */ 2320 static void hdd_set_multicast_list(struct net_device *dev) 2321 { 2322 cds_ssr_protect(__func__); 2323 __hdd_set_multicast_list(dev); 2324 cds_ssr_unprotect(__func__); 2325 } 2326 #endif 2327 2328 /** 2329 * hdd_select_queue() - used by Linux OS to decide which queue to use first 2330 * @dev: Pointer to the WLAN device. 2331 * @skb: Pointer to OS packet (sk_buff). 2332 * 2333 * This function is registered with the Linux OS for network 2334 * core to decide which queue to use first. 2335 * 2336 * Return: ac, Queue Index/access category corresponding to UP in IP header 2337 */ 2338 static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb 2339 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) 2340 , void *accel_priv 2341 #endif 2342 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) 2343 , select_queue_fallback_t fallback 2344 #endif 2345 ) 2346 { 2347 return hdd_wmm_select_queue(dev, skb); 2348 } 2349 2350 static struct net_device_ops wlan_drv_ops = { 2351 .ndo_open = hdd_open, 2352 .ndo_stop = hdd_stop, 2353 .ndo_uninit = hdd_uninit, 2354 .ndo_start_xmit = hdd_hard_start_xmit, 2355 .ndo_tx_timeout = hdd_tx_timeout, 2356 .ndo_get_stats = hdd_get_stats, 2357 .ndo_do_ioctl = hdd_ioctl, 2358 .ndo_set_mac_address = hdd_set_mac_address, 2359 .ndo_select_queue = hdd_select_queue, 2360 #ifdef WLAN_FEATURE_PACKET_FILTERING 2361 .ndo_set_rx_mode = hdd_set_multicast_list, 2362 #endif 2363 }; 2364 2365 /* Monitor mode net_device_ops, doesnot Tx and most of operations. */ 2366 static struct net_device_ops wlan_mon_drv_ops = { 2367 .ndo_open = hdd_mon_open, 2368 .ndo_stop = hdd_stop, 2369 .ndo_get_stats = hdd_get_stats, 2370 }; 2371 2372 /** 2373 * hdd_set_station_ops() - update net_device ops for monitor mode 2374 * @pWlanDev: Handle to struct net_device to be updated. 2375 * Return: None 2376 */ 2377 void hdd_set_station_ops(struct net_device *pWlanDev) 2378 { 2379 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) 2380 pWlanDev->netdev_ops = &wlan_mon_drv_ops; 2381 else 2382 pWlanDev->netdev_ops = &wlan_drv_ops; 2383 } 2384 2385 #ifdef FEATURE_RUNTIME_PM 2386 /** 2387 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts 2388 * @hdd_ctx: HDD context 2389 * 2390 * Return: None 2391 */ 2392 static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) 2393 { 2394 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context; 2395 2396 ctx->scan = qdf_runtime_lock_init("scan"); 2397 ctx->roc = qdf_runtime_lock_init("roc"); 2398 ctx->dfs = qdf_runtime_lock_init("dfs"); 2399 } 2400 2401 /** 2402 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context 2403 * @hdd_ctx: HDD Context 2404 * 2405 * Return: None 2406 */ 2407 static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) 2408 { 2409 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context; 2410 2411 qdf_runtime_lock_deinit(ctx->scan); 2412 ctx->scan = NULL; 2413 qdf_runtime_lock_deinit(ctx->roc); 2414 ctx->roc = NULL; 2415 qdf_runtime_lock_deinit(ctx->dfs); 2416 ctx->dfs = NULL; 2417 } 2418 2419 static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) 2420 { 2421 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx; 2422 2423 ctx->connect = qdf_runtime_lock_init("connect"); 2424 } 2425 2426 static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) 2427 { 2428 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx; 2429 2430 qdf_runtime_lock_deinit(ctx->connect); 2431 ctx->connect = NULL; 2432 } 2433 #else /* FEATURE_RUNTIME_PM */ 2434 static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {} 2435 static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {} 2436 static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {} 2437 static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {} 2438 #endif /* FEATURE_RUNTIME_PM */ 2439 /** 2440 * hdd_alloc_station_adapter() - allocate the station hdd adapter 2441 * @hdd_ctx: global hdd context 2442 * @macAddr: mac address to assign to the interface 2443 * @name: User-visible name of the interface 2444 * 2445 * hdd adapter pointer would point to the netdev->priv space, this function 2446 * would retrive the pointer, and setup the hdd adapter configuration. 2447 * 2448 * Return: the pointer to hdd adapter, otherwise NULL 2449 */ 2450 static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx, 2451 tSirMacAddr macAddr, 2452 unsigned char name_assign_type, 2453 const char *name) 2454 { 2455 struct net_device *pWlanDev = NULL; 2456 hdd_adapter_t *adapter = NULL; 2457 /* 2458 * cfg80211 initialization and registration.... 2459 */ 2460 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name, 2461 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS) 2462 name_assign_type, 2463 #endif 2464 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ? 2465 hdd_mon_mode_ether_setup : ether_setup), 2466 NUM_TX_QUEUES); 2467 2468 if (pWlanDev != NULL) { 2469 2470 /* Save the pointer to the net_device in the HDD adapter */ 2471 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev); 2472 2473 qdf_mem_zero(adapter, sizeof(hdd_adapter_t)); 2474 2475 adapter->dev = pWlanDev; 2476 adapter->pHddCtx = hdd_ctx; 2477 adapter->magic = WLAN_HDD_ADAPTER_MAGIC; 2478 adapter->sessionId = HDD_SESSION_ID_INVALID; 2479 2480 init_completion(&adapter->session_open_comp_var); 2481 init_completion(&adapter->session_close_comp_var); 2482 init_completion(&adapter->disconnect_comp_var); 2483 init_completion(&adapter->linkup_event_var); 2484 init_completion(&adapter->cancel_rem_on_chan_var); 2485 init_completion(&adapter->rem_on_chan_ready_event); 2486 init_completion(&adapter->sta_authorized_event); 2487 init_completion(&adapter->offchannel_tx_event); 2488 init_completion(&adapter->tx_action_cnf_event); 2489 #ifdef FEATURE_WLAN_TDLS 2490 init_completion(&adapter->tdls_add_station_comp); 2491 init_completion(&adapter->tdls_del_station_comp); 2492 init_completion(&adapter->tdls_mgmt_comp); 2493 init_completion(&adapter->tdls_link_establish_req_comp); 2494 #endif 2495 init_completion(&adapter->ibss_peer_info_comp); 2496 init_completion(&adapter->change_country_code); 2497 2498 2499 init_completion(&adapter->scan_info.abortscan_event_var); 2500 2501 adapter->offloads_configured = false; 2502 adapter->isLinkUpSvcNeeded = false; 2503 adapter->higherDtimTransition = true; 2504 /* Init the net_device structure */ 2505 strlcpy(pWlanDev->name, name, IFNAMSIZ); 2506 2507 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr, 2508 sizeof(tSirMacAddr)); 2509 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr, 2510 sizeof(tSirMacAddr)); 2511 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT; 2512 2513 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload) 2514 pWlanDev->features |= 2515 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; 2516 pWlanDev->features |= NETIF_F_RXCSUM; 2517 2518 hdd_set_tso_flags(hdd_ctx, pWlanDev); 2519 2520 hdd_set_station_ops(adapter->dev); 2521 2522 pWlanDev->destructor = free_netdev; 2523 pWlanDev->ieee80211_ptr = &adapter->wdev; 2524 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN; 2525 adapter->wdev.wiphy = hdd_ctx->wiphy; 2526 adapter->wdev.netdev = pWlanDev; 2527 /* set pWlanDev's parent to underlying device */ 2528 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev); 2529 hdd_wmm_init(adapter); 2530 hdd_adapter_runtime_suspend_init(adapter); 2531 spin_lock_init(&adapter->pause_map_lock); 2532 adapter->start_time = adapter->last_time = qdf_system_ticks(); 2533 } 2534 2535 return adapter; 2536 } 2537 2538 static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter, 2539 bool rtnl_held) 2540 { 2541 struct net_device *pWlanDev = adapter->dev; 2542 2543 if (rtnl_held) { 2544 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) { 2545 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) { 2546 hdd_err("Failed:dev_alloc_name"); 2547 return QDF_STATUS_E_FAILURE; 2548 } 2549 } 2550 if (register_netdevice(pWlanDev)) { 2551 hdd_err("Failed:register_netdev"); 2552 return QDF_STATUS_E_FAILURE; 2553 } 2554 } else { 2555 if (register_netdev(pWlanDev)) { 2556 hdd_err("Failed:register_netdev"); 2557 return QDF_STATUS_E_FAILURE; 2558 } 2559 } 2560 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags); 2561 2562 return QDF_STATUS_SUCCESS; 2563 } 2564 2565 QDF_STATUS hdd_sme_close_session_callback(void *pContext) 2566 { 2567 hdd_adapter_t *adapter = pContext; 2568 2569 if (NULL == adapter) { 2570 hdd_alert("NULL adapter"); 2571 return QDF_STATUS_E_INVAL; 2572 } 2573 2574 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) { 2575 hdd_alert("Invalid magic"); 2576 return QDF_STATUS_NOT_INITIALIZED; 2577 } 2578 2579 /* 2580 * For NAN Data interface, the close session results in the final 2581 * indication to the userspace 2582 */ 2583 if (adapter->device_mode == QDF_NDI_MODE) 2584 hdd_ndp_session_end_handler(adapter); 2585 2586 clear_bit(SME_SESSION_OPENED, &adapter->event_flags); 2587 2588 /* 2589 * We can be blocked while waiting for scheduled work to be 2590 * flushed, and the adapter structure can potentially be freed, in 2591 * which case the magic will have been reset. So make sure the 2592 * magic is still good, and hence the adapter structure is still 2593 * valid, before signaling completion 2594 */ 2595 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic) 2596 complete(&adapter->session_close_comp_var); 2597 2598 return QDF_STATUS_SUCCESS; 2599 } 2600 2601 /** 2602 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode 2603 * @adapter: pointer to device adapter 2604 * @type: type of interface 2605 * 2606 * This routine will check the mode of adapter and if it is required then it 2607 * will initialize the TDLS operations 2608 * 2609 * Return: QDF_STATUS 2610 */ 2611 #ifdef FEATURE_WLAN_TDLS 2612 static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type) 2613 { 2614 if (QDF_IBSS_MODE != type) { 2615 if (0 != wlan_hdd_tdls_init(adapter)) { 2616 hdd_err("wlan_hdd_tdls_init failed"); 2617 return QDF_STATUS_E_FAILURE; 2618 } 2619 set_bit(TDLS_INIT_DONE, &adapter->event_flags); 2620 } 2621 return QDF_STATUS_SUCCESS; 2622 } 2623 #else 2624 static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type) 2625 { 2626 return QDF_STATUS_SUCCESS; 2627 } 2628 #endif 2629 2630 QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter) 2631 { 2632 struct net_device *pWlanDev = adapter->dev; 2633 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; 2634 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 2635 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; 2636 QDF_STATUS status = QDF_STATUS_E_FAILURE; 2637 uint32_t type, subType; 2638 unsigned long rc; 2639 int ret_val; 2640 2641 INIT_COMPLETION(adapter->session_open_comp_var); 2642 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode); 2643 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2); 2644 status = cds_get_vdev_types(adapter->device_mode, &type, &subType); 2645 if (QDF_STATUS_SUCCESS != status) { 2646 hdd_err("failed to get vdev type"); 2647 goto error_sme_open; 2648 } 2649 /* Open a SME session for future operation */ 2650 qdf_ret_status = 2651 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter, 2652 (uint8_t *) &adapter->macAddressCurrent, 2653 &adapter->sessionId, type, subType); 2654 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) { 2655 hdd_alert("sme_open_session() failed, status code %08d [x%08x]", 2656 qdf_ret_status, qdf_ret_status); 2657 status = QDF_STATUS_E_FAILURE; 2658 goto error_sme_open; 2659 } 2660 /* Block on a completion variable. Can't wait forever though. */ 2661 rc = wait_for_completion_timeout( 2662 &adapter->session_open_comp_var, 2663 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); 2664 if (!rc) { 2665 hdd_alert("Session is not opened within timeout period code %ld", 2666 rc); 2667 status = QDF_STATUS_E_FAILURE; 2668 goto error_sme_open; 2669 } 2670 2671 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId); 2672 /* Register wireless extensions */ 2673 qdf_ret_status = hdd_register_wext(pWlanDev); 2674 if (QDF_STATUS_SUCCESS != qdf_ret_status) { 2675 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]", 2676 qdf_ret_status, qdf_ret_status); 2677 status = QDF_STATUS_E_FAILURE; 2678 goto error_register_wext; 2679 } 2680 /* Set the Connection State to Not Connected */ 2681 hdd_notice("Set HDD connState to eConnectionState_NotConnected"); 2682 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; 2683 2684 /* Set the default operation channel */ 2685 pHddStaCtx->conn_info.operationChannel = 2686 hdd_ctx->config->OperatingChannel; 2687 2688 /* Make the default Auth Type as OPEN */ 2689 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; 2690 2691 status = hdd_init_tx_rx(adapter); 2692 if (QDF_STATUS_SUCCESS != status) { 2693 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]", 2694 status, status); 2695 goto error_init_txrx; 2696 } 2697 2698 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags); 2699 2700 status = hdd_wmm_adapter_init(adapter); 2701 if (QDF_STATUS_SUCCESS != status) { 2702 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]", 2703 status, status); 2704 goto error_wmm_init; 2705 } 2706 2707 set_bit(WMM_INIT_DONE, &adapter->event_flags); 2708 2709 ret_val = wma_cli_set_command(adapter->sessionId, 2710 WMI_PDEV_PARAM_BURST_ENABLE, 2711 hdd_ctx->config->enableSifsBurst, 2712 PDEV_CMD); 2713 2714 if (0 != ret_val) { 2715 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", 2716 ret_val); 2717 } 2718 status = hdd_check_and_init_tdls(adapter, type); 2719 if (status != QDF_STATUS_SUCCESS) 2720 goto error_tdls_init; 2721 2722 status = hdd_lro_enable(hdd_ctx, adapter); 2723 if (status != QDF_STATUS_SUCCESS) 2724 goto error_lro_enable; 2725 2726 return QDF_STATUS_SUCCESS; 2727 2728 error_lro_enable: 2729 wlan_hdd_tdls_exit(adapter); 2730 error_tdls_init: 2731 clear_bit(WMM_INIT_DONE, &adapter->event_flags); 2732 hdd_wmm_adapter_close(adapter); 2733 error_wmm_init: 2734 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags); 2735 hdd_deinit_tx_rx(adapter); 2736 error_init_txrx: 2737 hdd_unregister_wext(pWlanDev); 2738 error_register_wext: 2739 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) { 2740 INIT_COMPLETION(adapter->session_close_comp_var); 2741 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal, 2742 adapter->sessionId, 2743 hdd_sme_close_session_callback, 2744 adapter)) { 2745 unsigned long rc; 2746 2747 /* 2748 * Block on a completion variable. 2749 * Can't wait forever though. 2750 */ 2751 rc = wait_for_completion_timeout( 2752 &adapter->session_close_comp_var, 2753 msecs_to_jiffies 2754 (WLAN_WAIT_TIME_SESSIONOPENCLOSE)); 2755 if (rc <= 0) 2756 hdd_err("Session is not opened within timeout period code %ld", 2757 rc); 2758 } 2759 } 2760 error_sme_open: 2761 return status; 2762 } 2763 2764 void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) 2765 { 2766 hdd_cfg80211_state_t *cfgState; 2767 2768 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter); 2769 2770 if (NULL != cfgState->buf) { 2771 unsigned long rc; 2772 rc = wait_for_completion_timeout( 2773 &adapter->tx_action_cnf_event, 2774 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT)); 2775 if (!rc) { 2776 hdd_err("HDD Wait for Action Confirmation Failed!!"); 2777 /* 2778 * Inform tx status as FAILURE to upper layer and free 2779 * cfgState->buf 2780 */ 2781 hdd_send_action_cnf(adapter, false); 2782 } 2783 } 2784 return; 2785 } 2786 2787 /** 2788 * hdd_station_adapter_deinit() - De-initialize the station adapter 2789 * @hdd_ctx: global hdd context 2790 * @adapter: HDD adapter 2791 * @rtnl_held: Used to indicate whether or not the caller is holding 2792 * the kernel rtnl_mutex 2793 * 2794 * This function De-initializes the STA/P2P/OCB adapter. 2795 * 2796 * Return: None. 2797 */ 2798 static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx, 2799 hdd_adapter_t *adapter, 2800 bool rtnl_held) 2801 { 2802 ENTER_DEV(adapter->dev); 2803 2804 if (adapter->dev) { 2805 if (rtnl_held) 2806 adapter->dev->wireless_handlers = NULL; 2807 else { 2808 rtnl_lock(); 2809 adapter->dev->wireless_handlers = NULL; 2810 rtnl_unlock(); 2811 } 2812 } 2813 2814 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) { 2815 hdd_deinit_tx_rx(adapter); 2816 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags); 2817 } 2818 2819 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) { 2820 hdd_wmm_adapter_close(adapter); 2821 clear_bit(WMM_INIT_DONE, &adapter->event_flags); 2822 } 2823 2824 hdd_cleanup_actionframe(hdd_ctx, adapter); 2825 wlan_hdd_tdls_exit(adapter); 2826 2827 EXIT(); 2828 } 2829 2830 /** 2831 * hdd_ap_adapter_deinit() - De-initialize the ap adapter 2832 * @hdd_ctx: global hdd context 2833 * @adapter: HDD adapter 2834 * @rtnl_held: the rtnl lock hold flag 2835 * This function De-initializes the AP/P2PGo adapter. 2836 * 2837 * Return: None. 2838 */ 2839 static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx, 2840 hdd_adapter_t *adapter, 2841 bool rtnl_held) 2842 { 2843 ENTER_DEV(adapter->dev); 2844 2845 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) { 2846 hdd_wmm_adapter_close(adapter); 2847 clear_bit(WMM_INIT_DONE, &adapter->event_flags); 2848 } 2849 wlan_hdd_undo_acs(adapter); 2850 2851 hdd_cleanup_actionframe(hdd_ctx, adapter); 2852 2853 hdd_unregister_hostapd(adapter, rtnl_held); 2854 2855 EXIT(); 2856 } 2857 2858 void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, 2859 bool rtnl_held) 2860 { 2861 ENTER(); 2862 2863 switch (adapter->device_mode) { 2864 case QDF_STA_MODE: 2865 case QDF_P2P_CLIENT_MODE: 2866 case QDF_P2P_DEVICE_MODE: 2867 { 2868 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held); 2869 break; 2870 } 2871 2872 case QDF_SAP_MODE: 2873 case QDF_P2P_GO_MODE: 2874 { 2875 2876 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held); 2877 break; 2878 } 2879 2880 default: 2881 break; 2882 } 2883 2884 EXIT(); 2885 } 2886 2887 static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, 2888 bool rtnl_held) 2889 { 2890 struct net_device *pWlanDev = NULL; 2891 2892 if (adapter) 2893 pWlanDev = adapter->dev; 2894 else { 2895 hdd_err("adapter is Null"); 2896 return; 2897 } 2898 2899 hdd_debugfs_exit(adapter); 2900 2901 if (adapter->scan_info.default_scan_ies) { 2902 qdf_mem_free(adapter->scan_info.default_scan_ies); 2903 adapter->scan_info.default_scan_ies = NULL; 2904 } 2905 2906 hdd_adapter_runtime_suspend_denit(adapter); 2907 2908 /* 2909 * The adapter is marked as closed. When hdd_wlan_exit() call returns, 2910 * the driver is almost closed and cannot handle either control 2911 * messages or data. However, unregister_netdevice() call above will 2912 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts 2913 * to close the active connections (basically excites control path) which 2914 * is not right. Setting this flag helps hdd_stop() to recognize that 2915 * the interface is closed and restricts any operations on that 2916 */ 2917 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags); 2918 2919 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) { 2920 if (rtnl_held) { 2921 unregister_netdevice(pWlanDev); 2922 } else { 2923 unregister_netdev(pWlanDev); 2924 } 2925 /* 2926 * Note that the adapter is no longer valid at this point 2927 * since the memory has been reclaimed 2928 */ 2929 } 2930 } 2931 2932 static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx, 2933 tSirMacAddr macAddr) 2934 { 2935 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 2936 hdd_adapter_t *adapter; 2937 QDF_STATUS status; 2938 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 2939 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 2940 adapter = adapterNode->pAdapter; 2941 if (adapter 2942 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes, 2943 macAddr, sizeof(tSirMacAddr))) { 2944 return QDF_STATUS_E_FAILURE; 2945 } 2946 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 2947 adapterNode = pNext; 2948 } 2949 return QDF_STATUS_SUCCESS; 2950 } 2951 2952 #ifdef CONFIG_FW_LOGS_BASED_ON_INI 2953 /** 2954 * hdd_set_fw_log_params() - Set log parameters to FW 2955 * @hdd_ctx: HDD Context 2956 * @adapter: HDD Adapter 2957 * 2958 * This function set the FW Debug log level based on the INI. 2959 * 2960 * Return: None 2961 */ 2962 static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx, 2963 hdd_adapter_t *adapter) 2964 { 2965 uint8_t count = 0, numentries = 0, 2966 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH]; 2967 uint32_t value = 0; 2968 int ret; 2969 2970 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() || 2971 (!hdd_ctx->config->enable_fw_log)) { 2972 hdd_info("enable_fw_log not enabled in INI or in FTM mode return"); 2973 return; 2974 } 2975 2976 /* Enable FW logs based on INI configuration */ 2977 hdd_ctx->fw_log_settings.dl_type = 2978 hdd_ctx->config->enableFwLogType; 2979 ret = wma_cli_set_command(adapter->sessionId, 2980 WMI_DBGLOG_TYPE, 2981 hdd_ctx->config->enableFwLogType, 2982 DBG_CMD); 2983 if (ret != 0) 2984 hdd_err("Failed to enable FW log type ret %d", 2985 ret); 2986 2987 hdd_ctx->fw_log_settings.dl_loglevel = 2988 hdd_ctx->config->enableFwLogLevel; 2989 ret = wma_cli_set_command(adapter->sessionId, 2990 WMI_DBGLOG_LOG_LEVEL, 2991 hdd_ctx->config->enableFwLogLevel, 2992 DBG_CMD); 2993 if (ret != 0) 2994 hdd_err("Failed to enable FW log level ret %d", 2995 ret); 2996 2997 hdd_string_to_u8_array( 2998 hdd_ctx->config->enableFwModuleLogLevel, 2999 moduleloglevel, 3000 &numentries, 3001 FW_MODULE_LOG_LEVEL_STRING_LENGTH); 3002 3003 while (count < numentries) { 3004 /* 3005 * FW module log level input string looks like 3006 * below: 3007 * gFwDebugModuleLoglevel=<FW Module ID>, 3008 * <Log Level>,... 3009 * For example: 3010 * gFwDebugModuleLoglevel= 3011 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6 3012 * Above input string means : 3013 * For FW module ID 1 enable log level 0 3014 * For FW module ID 2 enable log level 1 3015 * For FW module ID 3 enable log level 2 3016 * For FW module ID 4 enable log level 3 3017 * For FW module ID 5 enable log level 4 3018 * For FW module ID 6 enable log level 5 3019 * For FW module ID 7 enable log level 6 3020 */ 3021 3022 /* FW expects WMI command value = 3023 * Module ID * 10 + Module Log level 3024 */ 3025 value = ((moduleloglevel[count] * 10) + 3026 moduleloglevel[count + 1]); 3027 ret = wma_cli_set_command(adapter->sessionId, 3028 WMI_DBGLOG_MOD_LOG_LEVEL, 3029 value, DBG_CMD); 3030 if (ret != 0) 3031 hdd_err("Failed to enable FW module log level %d ret %d", 3032 value, ret); 3033 3034 count += 2; 3035 } 3036 3037 } 3038 #else 3039 static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx, 3040 hdd_adapter_t *adapter) 3041 { 3042 } 3043 3044 #endif 3045 3046 /** 3047 * hdd_set_fw_params() - Set parameters to firmware 3048 * @adapter: HDD adapter 3049 * 3050 * This function Sets various parameters to fw once the 3051 * adapter is started. 3052 * 3053 * Return: 0 on success or errno on failure 3054 */ 3055 int hdd_set_fw_params(hdd_adapter_t *adapter) 3056 { 3057 int ret; 3058 hdd_context_t *hdd_ctx; 3059 3060 ENTER_DEV(adapter->dev); 3061 3062 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 3063 if (!hdd_ctx) 3064 return -EINVAL; 3065 3066 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) && 3067 (!hdd_ctx->config->enable2x2)) { 3068 #define HDD_DTIM_1CHAIN_RX_ID 0x5 3069 #define HDD_SMPS_PARAM_VALUE_S 29 3070 /* 3071 * Disable DTIM 1 chain Rx when in 1x1, 3072 * we are passing two value 3073 * as param_id << 29 | param_value. 3074 * Below param_value = 0(disable) 3075 */ 3076 ret = wma_cli_set_command(adapter->sessionId, 3077 WMI_STA_SMPS_PARAM_CMDID, 3078 HDD_DTIM_1CHAIN_RX_ID << 3079 HDD_SMPS_PARAM_VALUE_S, 3080 VDEV_CMD); 3081 if (ret) { 3082 hdd_err("DTIM 1 chain set failed %d", ret); 3083 goto error; 3084 } 3085 3086 ret = wma_cli_set_command(adapter->sessionId, 3087 WMI_PDEV_PARAM_TX_CHAIN_MASK, 3088 hdd_ctx->config->txchainmask1x1, 3089 PDEV_CMD); 3090 if (ret) { 3091 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d", 3092 ret); 3093 goto error; 3094 } 3095 3096 ret = wma_cli_set_command(adapter->sessionId, 3097 WMI_PDEV_PARAM_RX_CHAIN_MASK, 3098 hdd_ctx->config->rxchainmask1x1, 3099 PDEV_CMD); 3100 if (ret) { 3101 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d", 3102 ret); 3103 goto error; 3104 } 3105 #undef HDD_DTIM_1CHAIN_RX_ID 3106 #undef HDD_SMPS_PARAM_VALUE_S 3107 } else { 3108 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params"); 3109 } 3110 3111 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) { 3112 ret = wma_cli_set_command(adapter->sessionId, 3113 WMI_PDEV_PARAM_HYST_EN, 3114 hdd_ctx->config->enableMemDeepSleep, 3115 PDEV_CMD); 3116 3117 if (ret) { 3118 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d", 3119 ret); 3120 goto error; 3121 } 3122 3123 ret = wma_cli_set_command(adapter->sessionId, 3124 WMI_VDEV_PARAM_ENABLE_RTSCTS, 3125 hdd_ctx->config->rts_profile, 3126 VDEV_CMD); 3127 if (ret) { 3128 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret); 3129 goto error; 3130 } 3131 } 3132 3133 hdd_set_fw_log_params(hdd_ctx, adapter); 3134 3135 EXIT(); 3136 return 0; 3137 3138 error: 3139 return -EINVAL; 3140 } 3141 3142 /** 3143 * hdd_open_adapter() - open and setup the hdd adatper 3144 * @hdd_ctx: global hdd context 3145 * @session_type: type of the interface to be created 3146 * @iface_name: User-visible name of the interface 3147 * @macAddr: MAC address to assign to the interface 3148 * @name_assign_type: the name of assign type of the netdev 3149 * @rtnl_held: the rtnl lock hold flag 3150 * 3151 * This function open and setup the hdd adpater according to the device 3152 * type request, assign the name, the mac address assigned, and then prepared 3153 * the hdd related parameters, queue, lock and ready to start. 3154 * 3155 * Return: the pointer of hdd adapter, otherwise NULL. 3156 */ 3157 hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, 3158 const char *iface_name, tSirMacAddr macAddr, 3159 unsigned char name_assign_type, 3160 bool rtnl_held) 3161 { 3162 hdd_adapter_t *adapter = NULL; 3163 hdd_adapter_list_node_t *pHddAdapterNode = NULL; 3164 QDF_STATUS status = QDF_STATUS_E_FAILURE; 3165 hdd_cfg80211_state_t *cfgState; 3166 3167 hdd_info("iface(%s) type(%d)", iface_name, session_type); 3168 3169 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) { 3170 /* 3171 * Max limit reached on the number of vdevs configured by the 3172 * host. Return error 3173 */ 3174 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d", 3175 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count); 3176 return NULL; 3177 } 3178 3179 if (macAddr == NULL) { 3180 /* Not received valid macAddr */ 3181 hdd_err("Unable to add virtual intf: Not able to get valid mac address"); 3182 return NULL; 3183 } 3184 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr); 3185 if (QDF_STATUS_E_FAILURE == status) { 3186 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR 3187 " already exists", 3188 MAC_ADDR_ARRAY(macAddr)); 3189 return NULL; 3190 } 3191 3192 switch (session_type) { 3193 case QDF_STA_MODE: 3194 /* Reset locally administered bit if the device mode is STA */ 3195 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr); 3196 /* fall through */ 3197 case QDF_P2P_CLIENT_MODE: 3198 case QDF_P2P_DEVICE_MODE: 3199 case QDF_OCB_MODE: 3200 case QDF_NDI_MODE: 3201 case QDF_MONITOR_MODE: 3202 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr, 3203 name_assign_type, 3204 iface_name); 3205 3206 if (NULL == adapter) { 3207 hdd_err("failed to allocate adapter for session %d", 3208 session_type); 3209 return NULL; 3210 } 3211 3212 if (QDF_P2P_CLIENT_MODE == session_type) 3213 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; 3214 else if (QDF_P2P_DEVICE_MODE == session_type) 3215 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE; 3216 else if (QDF_MONITOR_MODE == session_type) 3217 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR; 3218 else 3219 adapter->wdev.iftype = NL80211_IFTYPE_STATION; 3220 3221 adapter->device_mode = session_type; 3222 3223 if (QDF_NDI_MODE == session_type) { 3224 status = hdd_init_nan_data_mode(adapter); 3225 if (QDF_STATUS_SUCCESS != status) 3226 goto err_free_netdev; 3227 } 3228 3229 /* 3230 * Workqueue which gets scheduled in IPv4 notification 3231 * callback 3232 */ 3233 INIT_WORK(&adapter->ipv4NotifierWorkQueue, 3234 hdd_ipv4_notifier_work_queue); 3235 3236 #ifdef WLAN_NS_OFFLOAD 3237 /* 3238 * Workqueue which gets scheduled in IPv6 3239 * notification callback. 3240 */ 3241 INIT_WORK(&adapter->ipv6NotifierWorkQueue, 3242 hdd_ipv6_notifier_work_queue); 3243 #endif 3244 status = hdd_register_interface(adapter, rtnl_held); 3245 if (QDF_STATUS_SUCCESS != status) { 3246 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held); 3247 goto err_free_netdev; 3248 } 3249 3250 /* Stop the Interface TX queue. */ 3251 hdd_info("Disabling queues"); 3252 wlan_hdd_netif_queue_control(adapter, 3253 WLAN_NETIF_TX_DISABLE_N_CARRIER, 3254 WLAN_CONTROL_PATH); 3255 break; 3256 3257 3258 case QDF_P2P_GO_MODE: 3259 case QDF_SAP_MODE: 3260 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr, 3261 name_assign_type, 3262 (uint8_t *) iface_name); 3263 if (NULL == adapter) { 3264 hdd_alert("failed to allocate adapter for session %d", 3265 session_type); 3266 return NULL; 3267 } 3268 3269 adapter->wdev.iftype = 3270 (session_type == 3271 QDF_SAP_MODE) ? NL80211_IFTYPE_AP : 3272 NL80211_IFTYPE_P2P_GO; 3273 adapter->device_mode = session_type; 3274 3275 status = hdd_register_hostapd(adapter, rtnl_held); 3276 if (QDF_STATUS_SUCCESS != status) { 3277 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held); 3278 goto err_free_netdev; 3279 } 3280 hdd_info("Disabling queues"); 3281 wlan_hdd_netif_queue_control(adapter, 3282 WLAN_NETIF_TX_DISABLE_N_CARRIER, 3283 WLAN_CONTROL_PATH); 3284 break; 3285 case QDF_FTM_MODE: 3286 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr, 3287 name_assign_type, 3288 "wlan0"); 3289 if (NULL == adapter) { 3290 hdd_err("Failed to allocate adapter for FTM mode"); 3291 return NULL; 3292 } 3293 adapter->wdev.iftype = NL80211_IFTYPE_STATION; 3294 adapter->device_mode = session_type; 3295 status = hdd_register_interface(adapter, rtnl_held); 3296 if (QDF_STATUS_SUCCESS != status) { 3297 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held); 3298 goto err_free_netdev; 3299 } 3300 /* Stop the Interface TX queue. */ 3301 hdd_info("Disabling queues"); 3302 wlan_hdd_netif_queue_control(adapter, 3303 WLAN_NETIF_TX_DISABLE_N_CARRIER, 3304 WLAN_CONTROL_PATH); 3305 break; 3306 default: 3307 hdd_alert("Invalid session type %d", session_type); 3308 QDF_ASSERT(0); 3309 return NULL; 3310 } 3311 3312 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter); 3313 mutex_init(&cfgState->remain_on_chan_ctx_lock); 3314 3315 if (QDF_STATUS_SUCCESS == status) { 3316 /* Add it to the hdd's session list. */ 3317 pHddAdapterNode = 3318 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t)); 3319 if (NULL == pHddAdapterNode) { 3320 status = QDF_STATUS_E_NOMEM; 3321 } else { 3322 pHddAdapterNode->pAdapter = adapter; 3323 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode); 3324 } 3325 } 3326 3327 if (QDF_STATUS_SUCCESS != status) { 3328 if (NULL != adapter) { 3329 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held); 3330 adapter = NULL; 3331 } 3332 if (NULL != pHddAdapterNode) { 3333 qdf_mem_free(pHddAdapterNode); 3334 } 3335 return NULL; 3336 } 3337 3338 if (QDF_STATUS_SUCCESS == status) { 3339 cds_set_concurrency_mode(session_type); 3340 3341 /* Initialize the WoWL service */ 3342 if (!hdd_init_wowl(adapter)) { 3343 hdd_alert("hdd_init_wowl failed"); 3344 goto err_close_adapter; 3345 } 3346 3347 /* Adapter successfully added. Increment the vdev count */ 3348 hdd_ctx->current_intf_count++; 3349 3350 hdd_debug("current_intf_count=%d", 3351 hdd_ctx->current_intf_count); 3352 3353 cds_check_and_restart_sap_with_non_dfs_acs(); 3354 } 3355 3356 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter)) 3357 hdd_err("Interface %s wow debug_fs init failed", iface_name); 3358 3359 return adapter; 3360 3361 err_close_adapter: 3362 hdd_close_adapter(hdd_ctx, adapter, rtnl_held); 3363 err_free_netdev: 3364 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes); 3365 free_netdev(adapter->dev); 3366 3367 return NULL; 3368 } 3369 3370 QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, 3371 bool rtnl_held) 3372 { 3373 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext; 3374 QDF_STATUS status; 3375 3376 status = hdd_get_front_adapter(hdd_ctx, &pCurrent); 3377 if (QDF_STATUS_SUCCESS != status) { 3378 hdd_warn("adapter list empty %d", 3379 status); 3380 return status; 3381 } 3382 3383 while (pCurrent->pAdapter != adapter) { 3384 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext); 3385 if (QDF_STATUS_SUCCESS != status) 3386 break; 3387 3388 pCurrent = pNext; 3389 } 3390 adapterNode = pCurrent; 3391 if (QDF_STATUS_SUCCESS == status) { 3392 cds_clear_concurrency_mode(adapter->device_mode); 3393 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held); 3394 3395 hdd_remove_adapter(hdd_ctx, adapterNode); 3396 qdf_mem_free(adapterNode); 3397 adapterNode = NULL; 3398 3399 /* Adapter removed. Decrement vdev count */ 3400 if (hdd_ctx->current_intf_count != 0) 3401 hdd_ctx->current_intf_count--; 3402 3403 /* Fw will take care incase of concurrency */ 3404 return QDF_STATUS_SUCCESS; 3405 } 3406 3407 return QDF_STATUS_E_FAILURE; 3408 } 3409 3410 /** 3411 * hdd_close_all_adapters - Close all open adapters 3412 * @hdd_ctx: Hdd context 3413 * rtnl_held: True if RTNL lock held 3414 * 3415 * Close all open adapters. 3416 * 3417 * Return: QDF status code 3418 */ 3419 QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held) 3420 { 3421 hdd_adapter_list_node_t *pHddAdapterNode; 3422 QDF_STATUS status; 3423 3424 ENTER(); 3425 3426 do { 3427 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode); 3428 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) { 3429 wlan_hdd_release_intf_addr(hdd_ctx, 3430 pHddAdapterNode->pAdapter->macAddressCurrent.bytes); 3431 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter, 3432 rtnl_held); 3433 qdf_mem_free(pHddAdapterNode); 3434 /* Adapter removed. Decrement vdev count */ 3435 if (hdd_ctx->current_intf_count != 0) 3436 hdd_ctx->current_intf_count--; 3437 } 3438 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status); 3439 3440 EXIT(); 3441 3442 return QDF_STATUS_SUCCESS; 3443 } 3444 3445 void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter) 3446 { 3447 struct qdf_mac_addr *bssid = NULL; 3448 tSirUpdateIE updateIE; 3449 switch (pHostapdAdapter->device_mode) { 3450 case QDF_STA_MODE: 3451 case QDF_P2P_CLIENT_MODE: 3452 { 3453 hdd_station_ctx_t *pHddStaCtx = 3454 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter); 3455 bssid = &pHddStaCtx->conn_info.bssId; 3456 break; 3457 } 3458 case QDF_SAP_MODE: 3459 case QDF_P2P_GO_MODE: 3460 case QDF_IBSS_MODE: 3461 { 3462 bssid = &pHostapdAdapter->macAddressCurrent; 3463 break; 3464 } 3465 case QDF_FTM_MODE: 3466 case QDF_P2P_DEVICE_MODE: 3467 default: 3468 /* 3469 * wlan_hdd_reset_prob_rspies should not have been called 3470 * for these kind of devices 3471 */ 3472 hdd_err("Unexpected request for the current device type %d", 3473 pHostapdAdapter->device_mode); 3474 return; 3475 } 3476 3477 qdf_copy_macaddr(&updateIE.bssid, bssid); 3478 updateIE.smeSessionId = pHostapdAdapter->sessionId; 3479 updateIE.ieBufferlength = 0; 3480 updateIE.pAdditionIEBuffer = NULL; 3481 updateIE.append = true; 3482 updateIE.notify = false; 3483 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter), 3484 &updateIE, 3485 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) { 3486 hdd_err("Could not pass on PROBE_RSP_BCN data to PE"); 3487 } 3488 } 3489 3490 /** 3491 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close 3492 * @hdd_ctx: HDD context which is already NULL validated 3493 * @adapter: HDD adapter which is already NULL validated 3494 * 3495 * Close the SME session and wait for its completion, if needed. 3496 * 3497 * Return: None 3498 */ 3499 static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx, 3500 hdd_adapter_t *adapter) 3501 { 3502 unsigned long rc; 3503 3504 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) { 3505 hdd_err("session is not opened:%d", adapter->sessionId); 3506 return; 3507 } 3508 3509 INIT_COMPLETION(adapter->session_close_comp_var); 3510 if (QDF_STATUS_SUCCESS == 3511 sme_close_session(hdd_ctx->hHal, adapter->sessionId, 3512 hdd_sme_close_session_callback, 3513 adapter)) { 3514 /* 3515 * Block on a completion variable. Can't wait 3516 * forever though. 3517 */ 3518 rc = wait_for_completion_timeout( 3519 &adapter->session_close_comp_var, 3520 msecs_to_jiffies 3521 (WLAN_WAIT_TIME_SESSIONOPENCLOSE)); 3522 if (!rc) { 3523 hdd_err("failure waiting for session_close_comp_var"); 3524 if (adapter->device_mode == QDF_NDI_MODE) 3525 hdd_ndp_session_end_handler(adapter); 3526 clear_bit(SME_SESSION_OPENED, &adapter->event_flags); 3527 return; 3528 } 3529 adapter->sessionId = HDD_SESSION_ID_INVALID; 3530 } 3531 } 3532 3533 QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter, 3534 const bool bCloseSession) 3535 { 3536 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; 3537 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter); 3538 union iwreq_data wrqu; 3539 tSirUpdateIE updateIE; 3540 unsigned long rc; 3541 hdd_scaninfo_t *scan_info = NULL; 3542 3543 ENTER(); 3544 3545 scan_info = &adapter->scan_info; 3546 hdd_notice("Disabling queues"); 3547 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER, 3548 WLAN_CONTROL_PATH); 3549 switch (adapter->device_mode) { 3550 case QDF_STA_MODE: 3551 case QDF_P2P_CLIENT_MODE: 3552 case QDF_IBSS_MODE: 3553 case QDF_P2P_DEVICE_MODE: 3554 case QDF_NDI_MODE: 3555 if ((QDF_NDI_MODE == adapter->device_mode) || 3556 hdd_conn_is_connected( 3557 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) || 3558 hdd_is_connecting( 3559 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) { 3560 INIT_COMPLETION(adapter->disconnect_comp_var); 3561 /* 3562 * For NDI do not use pWextState from sta_ctx, if needed 3563 * extract from ndi_ctx. 3564 */ 3565 if (QDF_NDI_MODE == adapter->device_mode) 3566 qdf_ret_status = sme_roam_disconnect( 3567 hdd_ctx->hHal, 3568 adapter->sessionId, 3569 eCSR_DISCONNECT_REASON_NDI_DELETE); 3570 else if (pWextState->roamProfile.BSSType == 3571 eCSR_BSS_TYPE_START_IBSS) 3572 qdf_ret_status = sme_roam_disconnect( 3573 hdd_ctx->hHal, 3574 adapter->sessionId, 3575 eCSR_DISCONNECT_REASON_IBSS_LEAVE); 3576 else 3577 qdf_ret_status = sme_roam_disconnect( 3578 hdd_ctx->hHal, 3579 adapter->sessionId, 3580 eCSR_DISCONNECT_REASON_UNSPECIFIED); 3581 /* success implies disconnect command got queued up successfully */ 3582 if (qdf_ret_status == QDF_STATUS_SUCCESS) { 3583 rc = wait_for_completion_timeout( 3584 &adapter->disconnect_comp_var, 3585 msecs_to_jiffies 3586 (WLAN_WAIT_TIME_DISCONNECT)); 3587 if (!rc) { 3588 hdd_err("wait on disconnect_comp_var failed"); 3589 } 3590 } else { 3591 hdd_err("failed to post disconnect event to SME"); 3592 } 3593 memset(&wrqu, '\0', sizeof(wrqu)); 3594 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 3595 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); 3596 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu, 3597 NULL); 3598 } 3599 if (scan_info != NULL && scan_info->mScanPending) { 3600 wlan_hdd_scan_abort(adapter); 3601 } 3602 hdd_lro_disable(hdd_ctx, adapter); 3603 wlan_hdd_cleanup_remain_on_channel_ctx(adapter); 3604 3605 #ifdef WLAN_OPEN_SOURCE 3606 cancel_work_sync(&adapter->ipv4NotifierWorkQueue); 3607 #endif 3608 3609 hdd_deregister_tx_flow_control(adapter); 3610 3611 #ifdef WLAN_NS_OFFLOAD 3612 #ifdef WLAN_OPEN_SOURCE 3613 cancel_work_sync(&adapter->ipv6NotifierWorkQueue); 3614 #endif 3615 #endif 3616 3617 /* 3618 * It is possible that the caller of this function does not 3619 * wish to close the session 3620 */ 3621 if (true == bCloseSession) 3622 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter); 3623 break; 3624 3625 case QDF_SAP_MODE: 3626 case QDF_P2P_GO_MODE: 3627 if (hdd_ctx->config->conc_custom_rule1 && 3628 (QDF_SAP_MODE == adapter->device_mode)) { 3629 /* 3630 * Before stopping the sap adapter, lets make sure there 3631 * is no sap restart work pending. 3632 */ 3633 cds_flush_work(&hdd_ctx->sap_start_work); 3634 hdd_info("Canceled the pending SAP restart work"); 3635 cds_change_sap_restart_required_status(false); 3636 } 3637 /* Any softap specific cleanup here... */ 3638 if (adapter->device_mode == QDF_P2P_GO_MODE) 3639 wlan_hdd_cleanup_remain_on_channel_ctx(adapter); 3640 3641 hdd_deregister_tx_flow_control(adapter); 3642 3643 mutex_lock(&hdd_ctx->sap_lock); 3644 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { 3645 QDF_STATUS status; 3646 QDF_STATUS qdf_status; 3647 3648 /* Stop Bss. */ 3649 status = wlansap_stop_bss( 3650 WLAN_HDD_GET_SAP_CTX_PTR(adapter)); 3651 3652 if (QDF_IS_STATUS_SUCCESS(status)) { 3653 hdd_hostapd_state_t *hostapd_state = 3654 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); 3655 qdf_event_reset(&hostapd_state-> 3656 qdf_stop_bss_event); 3657 qdf_status = 3658 qdf_wait_single_event(&hostapd_state-> 3659 qdf_stop_bss_event, 3660 BSS_WAIT_TIMEOUT); 3661 3662 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 3663 hdd_err("failure waiting for wlansap_stop_bss %d", 3664 qdf_status); 3665 } 3666 } else { 3667 hdd_err("failure in wlansap_stop_bss"); 3668 } 3669 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags); 3670 cds_decr_session_set_pcl( 3671 adapter->device_mode, 3672 adapter->sessionId); 3673 3674 qdf_copy_macaddr(&updateIE.bssid, 3675 &adapter->macAddressCurrent); 3676 updateIE.smeSessionId = adapter->sessionId; 3677 updateIE.ieBufferlength = 0; 3678 updateIE.pAdditionIEBuffer = NULL; 3679 updateIE.append = false; 3680 updateIE.notify = false; 3681 /* Probe bcn reset */ 3682 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter), 3683 &updateIE, eUPDATE_IE_PROBE_BCN) 3684 == QDF_STATUS_E_FAILURE) { 3685 hdd_err("Could not pass on PROBE_RSP_BCN data to PE"); 3686 } 3687 /* Assoc resp reset */ 3688 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter), 3689 &updateIE, 3690 eUPDATE_IE_ASSOC_RESP) == 3691 QDF_STATUS_E_FAILURE) { 3692 hdd_err("Could not pass on ASSOC_RSP data to PE"); 3693 } 3694 /* Reset WNI_CFG_PROBE_RSP Flags */ 3695 wlan_hdd_reset_prob_rspies(adapter); 3696 qdf_mem_free(adapter->sessionCtx.ap.beacon); 3697 adapter->sessionCtx.ap.beacon = NULL; 3698 } 3699 mutex_unlock(&hdd_ctx->sap_lock); 3700 if (true == bCloseSession) 3701 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter); 3702 break; 3703 case QDF_OCB_MODE: 3704 cdp_peer_clear(cds_get_context(QDF_MODULE_ID_SOC), 3705 cds_get_context(QDF_MODULE_ID_TXRX), 3706 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]); 3707 break; 3708 default: 3709 break; 3710 } 3711 3712 EXIT(); 3713 return QDF_STATUS_SUCCESS; 3714 } 3715 3716 /** 3717 * hdd_deinit_all_adapters - deinit all adapters 3718 * @hdd_ctx: HDD context 3719 * @rtnl_held: True if RTNL lock held 3720 * 3721 */ 3722 void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held) 3723 { 3724 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; 3725 QDF_STATUS status; 3726 hdd_adapter_t *adapter; 3727 3728 ENTER(); 3729 3730 status = hdd_get_front_adapter(hdd_ctx, &adapter_node); 3731 3732 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) { 3733 adapter = adapter_node->pAdapter; 3734 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held); 3735 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); 3736 adapter_node = next; 3737 } 3738 3739 EXIT(); 3740 } 3741 3742 QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx) 3743 { 3744 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 3745 QDF_STATUS status; 3746 hdd_adapter_t *adapter; 3747 3748 ENTER(); 3749 3750 cds_flush_work(&hdd_ctx->sap_pre_cac_work); 3751 3752 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 3753 3754 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 3755 adapter = adapterNode->pAdapter; 3756 hdd_stop_adapter(hdd_ctx, adapter, true); 3757 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 3758 adapterNode = pNext; 3759 } 3760 3761 EXIT(); 3762 3763 return QDF_STATUS_SUCCESS; 3764 } 3765 3766 QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx) 3767 { 3768 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 3769 QDF_STATUS status; 3770 hdd_adapter_t *adapter; 3771 3772 ENTER(); 3773 3774 cds_flush_work(&hdd_ctx->sap_pre_cac_work); 3775 3776 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 3777 3778 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 3779 adapter = adapterNode->pAdapter; 3780 hdd_notice("Disabling queues"); 3781 wlan_hdd_netif_queue_control(adapter, 3782 WLAN_NETIF_TX_DISABLE_N_CARRIER, 3783 WLAN_CONTROL_PATH); 3784 3785 adapter->sessionCtx.station.hdd_ReassocScenario = false; 3786 3787 hdd_deinit_tx_rx(adapter); 3788 cds_decr_session_set_pcl(adapter->device_mode, 3789 adapter->sessionId); 3790 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) { 3791 hdd_wmm_adapter_close(adapter); 3792 clear_bit(WMM_INIT_DONE, &adapter->event_flags); 3793 } 3794 3795 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 3796 adapterNode = pNext; 3797 } 3798 3799 EXIT(); 3800 3801 return QDF_STATUS_SUCCESS; 3802 } 3803 3804 /** 3805 * hdd_is_interface_up()- Checkfor interface up before ssr 3806 * @hdd_ctx: HDD context 3807 * 3808 * check if there are any wlan interfaces before SSR accordingly start 3809 * the interface. 3810 * 3811 * Return: 0 if interface was opened else false 3812 */ 3813 static bool hdd_is_interface_up(hdd_adapter_t *adapter) 3814 { 3815 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) 3816 return true; 3817 else 3818 return false; 3819 } 3820 3821 #if defined CFG80211_CONNECT_BSS 3822 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \ 3823 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY) 3824 static 3825 struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy, 3826 struct ieee80211_channel *channel, 3827 const u8 *bssid, const u8 *ssid, 3828 size_t ssid_len) 3829 { 3830 return cfg80211_get_bss(wiphy, channel, bssid, 3831 ssid, ssid_len, 3832 WLAN_CAPABILITY_ESS, 3833 WLAN_CAPABILITY_ESS); 3834 } 3835 #else 3836 static 3837 struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy, 3838 struct ieee80211_channel *channel, 3839 const u8 *bssid, const u8 *ssid, 3840 size_t ssid_len) 3841 { 3842 return cfg80211_get_bss(wiphy, channel, bssid, 3843 ssid, ssid_len, 3844 IEEE80211_BSS_TYPE_ESS, 3845 IEEE80211_PRIVACY_ANY); 3846 } 3847 #endif 3848 #endif 3849 3850 #if defined CFG80211_CONNECT_BSS 3851 /** 3852 * hdd_connect_bss() - API to send connection status to supplicant 3853 * @dev: network device 3854 * @bssid: bssid to which we want to associate 3855 * @req_ie: Request Information Element 3856 * @req_ie_len: len of the req IE 3857 * @resp_ie: Response IE 3858 * @resp_ie_len: len of ht response IE 3859 * @status: status 3860 * @gfp: Kernel Flag 3861 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp 3862 * 3863 * The API is a wrapper to send connection status to supplicant 3864 * 3865 * Return: Void 3866 */ 3867 #if defined CFG80211_CONNECT_TIMEOUT 3868 static void hdd_connect_bss(struct net_device *dev, const u8 *bssid, 3869 struct cfg80211_bss *bss, const u8 *req_ie, 3870 size_t req_ie_len, const u8 *resp_ie, 3871 size_t resp_ie_len, int status, gfp_t gfp, 3872 bool connect_timeout) 3873 { 3874 if (connect_timeout) 3875 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL); 3876 else 3877 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, 3878 resp_ie, resp_ie_len, status, gfp); 3879 } 3880 #else 3881 static void hdd_connect_bss(struct net_device *dev, const u8 *bssid, 3882 struct cfg80211_bss *bss, const u8 *req_ie, 3883 size_t req_ie_len, const u8 *resp_ie, 3884 size_t resp_ie_len, int status, gfp_t gfp, 3885 bool connect_timeout) 3886 { 3887 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, 3888 resp_ie, resp_ie_len, status, gfp); 3889 } 3890 #endif 3891 3892 /** 3893 * hdd_connect_result() - API to send connection status to supplicant 3894 * @dev: network device 3895 * @bssid: bssid to which we want to associate 3896 * @roam_info: information about connected bss 3897 * @req_ie: Request Information Element 3898 * @req_ie_len: len of the req IE 3899 * @resp_ie: Response IE 3900 * @resp_ie_len: len of ht response IE 3901 * @status: status 3902 * @gfp: Kernel Flag 3903 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp 3904 * 3905 * The API is a wrapper to send connection status to supplicant 3906 * and allow runtime suspend 3907 * 3908 * Return: Void 3909 */ 3910 void hdd_connect_result(struct net_device *dev, const u8 *bssid, 3911 tCsrRoamInfo *roam_info, const u8 *req_ie, 3912 size_t req_ie_len, const u8 *resp_ie, 3913 size_t resp_ie_len, u16 status, gfp_t gfp, 3914 bool connect_timeout) 3915 { 3916 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev); 3917 struct cfg80211_bss *bss = NULL; 3918 3919 if (WLAN_STATUS_SUCCESS == status) { 3920 struct ieee80211_channel *chan; 3921 int freq; 3922 int chan_no = roam_info->pBssDesc->channelId; 3923 3924 if (chan_no <= 14) 3925 freq = ieee80211_channel_to_frequency(chan_no, 3926 NL80211_BAND_2GHZ); 3927 else 3928 freq = ieee80211_channel_to_frequency(chan_no, 3929 NL80211_BAND_5GHZ); 3930 3931 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq); 3932 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid, 3933 roam_info->u.pConnectedProfile->SSID.ssId, 3934 roam_info->u.pConnectedProfile->SSID.length); 3935 } 3936 3937 hdd_connect_bss(dev, bssid, bss, req_ie, 3938 req_ie_len, resp_ie, resp_ie_len, 3939 status, gfp, connect_timeout); 3940 3941 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect); 3942 } 3943 #else 3944 void hdd_connect_result(struct net_device *dev, const u8 *bssid, 3945 tCsrRoamInfo *roam_info, const u8 *req_ie, 3946 size_t req_ie_len, const u8 *resp_ie, 3947 size_t resp_ie_len, u16 status, gfp_t gfp, 3948 bool connect_timeout) 3949 { 3950 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev); 3951 3952 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len, 3953 resp_ie, resp_ie_len, status, gfp); 3954 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect); 3955 } 3956 #endif 3957 3958 3959 QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx) 3960 { 3961 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 3962 QDF_STATUS status; 3963 hdd_adapter_t *adapter; 3964 #ifndef MSM_PLATFORM 3965 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER; 3966 #endif 3967 eConnectionState connState; 3968 3969 ENTER(); 3970 3971 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 3972 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 3973 adapter = adapterNode->pAdapter; 3974 3975 if (!hdd_is_interface_up(adapter)) 3976 goto get_adapter; 3977 3978 hdd_wmm_init(adapter); 3979 3980 switch (adapter->device_mode) { 3981 case QDF_STA_MODE: 3982 case QDF_P2P_CLIENT_MODE: 3983 case QDF_P2P_DEVICE_MODE: 3984 3985 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter)) 3986 ->conn_info.connState; 3987 3988 hdd_init_station_mode(adapter); 3989 /* Open the gates for HDD to receive Wext commands */ 3990 adapter->isLinkUpSvcNeeded = false; 3991 adapter->scan_info.mScanPending = false; 3992 3993 /* Indicate disconnect event to supplicant if associated previously */ 3994 if (eConnectionState_Associated == connState || 3995 eConnectionState_IbssConnected == connState || 3996 eConnectionState_NotConnected == connState || 3997 eConnectionState_IbssDisconnected == connState || 3998 eConnectionState_Disconnecting == connState) { 3999 union iwreq_data wrqu; 4000 memset(&wrqu, '\0', sizeof(wrqu)); 4001 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 4002 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); 4003 wireless_send_event(adapter->dev, SIOCGIWAP, 4004 &wrqu, NULL); 4005 adapter->sessionCtx.station. 4006 hdd_ReassocScenario = false; 4007 4008 /* indicate disconnected event to nl80211 */ 4009 wlan_hdd_cfg80211_indicate_disconnect( 4010 adapter->dev, false, 4011 WLAN_REASON_UNSPECIFIED); 4012 } else if (eConnectionState_Connecting == connState) { 4013 /* 4014 * Indicate connect failure to supplicant if we were in the 4015 * process of connecting 4016 */ 4017 hdd_connect_result(adapter->dev, NULL, NULL, 4018 NULL, 0, NULL, 0, 4019 WLAN_STATUS_ASSOC_DENIED_UNSPEC, 4020 GFP_KERNEL, false); 4021 } 4022 4023 hdd_register_tx_flow_control(adapter, 4024 hdd_tx_resume_timer_expired_handler, 4025 hdd_tx_resume_cb); 4026 4027 break; 4028 4029 case QDF_SAP_MODE: 4030 /* softAP can handle SSR */ 4031 break; 4032 4033 case QDF_P2P_GO_MODE: 4034 #ifdef MSM_PLATFORM 4035 hdd_err("[SSR] send stop ap to supplicant"); 4036 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL); 4037 #else 4038 hdd_err("[SSR] send restart supplicant"); 4039 /* event supplicant to restart */ 4040 cfg80211_del_sta(adapter->dev, 4041 (const u8 *)&bcastMac.bytes[0], 4042 GFP_KERNEL); 4043 #endif 4044 break; 4045 4046 default: 4047 break; 4048 } 4049 get_adapter: 4050 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 4051 adapterNode = pNext; 4052 } 4053 4054 EXIT(); 4055 4056 return QDF_STATUS_SUCCESS; 4057 } 4058 4059 QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx, 4060 hdd_adapter_list_node_t **padapterNode) 4061 { 4062 QDF_STATUS status; 4063 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock); 4064 status = qdf_list_peek_front(&hdd_ctx->hddAdapters, 4065 (qdf_list_node_t **) padapterNode); 4066 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock); 4067 return status; 4068 } 4069 4070 QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx, 4071 hdd_adapter_list_node_t *adapterNode, 4072 hdd_adapter_list_node_t **pNextAdapterNode) 4073 { 4074 QDF_STATUS status; 4075 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock); 4076 status = qdf_list_peek_next(&hdd_ctx->hddAdapters, 4077 (qdf_list_node_t *) adapterNode, 4078 (qdf_list_node_t **) pNextAdapterNode); 4079 4080 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock); 4081 return status; 4082 } 4083 4084 QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx, 4085 hdd_adapter_list_node_t *adapterNode) 4086 { 4087 QDF_STATUS status; 4088 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock); 4089 status = qdf_list_remove_node(&hdd_ctx->hddAdapters, 4090 &adapterNode->node); 4091 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock); 4092 return status; 4093 } 4094 4095 QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx, 4096 hdd_adapter_list_node_t **padapterNode) 4097 { 4098 QDF_STATUS status; 4099 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock); 4100 status = qdf_list_remove_front(&hdd_ctx->hddAdapters, 4101 (qdf_list_node_t **) padapterNode); 4102 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock); 4103 return status; 4104 } 4105 4106 QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx, 4107 hdd_adapter_list_node_t *adapterNode) 4108 { 4109 QDF_STATUS status; 4110 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock); 4111 status = qdf_list_insert_back(&hdd_ctx->hddAdapters, 4112 (qdf_list_node_t *) adapterNode); 4113 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock); 4114 return status; 4115 } 4116 4117 QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx, 4118 hdd_adapter_list_node_t *adapterNode) 4119 { 4120 QDF_STATUS status; 4121 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock); 4122 status = qdf_list_insert_front(&hdd_ctx->hddAdapters, 4123 (qdf_list_node_t *) adapterNode); 4124 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock); 4125 return status; 4126 } 4127 4128 hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx, 4129 tSirMacAddr macAddr) 4130 { 4131 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 4132 hdd_adapter_t *adapter; 4133 QDF_STATUS status; 4134 4135 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 4136 4137 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 4138 adapter = adapterNode->pAdapter; 4139 4140 if (adapter 4141 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes, 4142 macAddr, sizeof(tSirMacAddr))) { 4143 return adapter; 4144 } 4145 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 4146 adapterNode = pNext; 4147 } 4148 4149 return NULL; 4150 4151 } 4152 4153 hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx, 4154 uint32_t vdev_id) 4155 { 4156 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 4157 hdd_adapter_t *adapter; 4158 QDF_STATUS qdf_status; 4159 4160 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 4161 4162 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) { 4163 adapter = adapterNode->pAdapter; 4164 4165 if (adapter->sessionId == vdev_id) 4166 return adapter; 4167 4168 qdf_status = 4169 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 4170 adapterNode = pNext; 4171 } 4172 4173 hdd_err("vdev_id %d does not exist with host", vdev_id); 4174 4175 return NULL; 4176 } 4177 4178 /** 4179 * hdd_get_adapter_by_sme_session_id() - Return adapter with 4180 * the sessionid 4181 * @hdd_ctx: hdd context. 4182 * @sme_session_id: sme session is for the adapter to get. 4183 * 4184 * This function is used to get the adapter with provided session id 4185 * 4186 * Return: adapter pointer if found 4187 * 4188 */ 4189 hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx, 4190 uint32_t sme_session_id) 4191 { 4192 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; 4193 hdd_adapter_t *adapter; 4194 QDF_STATUS qdf_status; 4195 4196 4197 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node); 4198 4199 while ((NULL != adapter_node) && 4200 (QDF_STATUS_SUCCESS == qdf_status)) { 4201 adapter = adapter_node->pAdapter; 4202 4203 if (adapter && 4204 adapter->sessionId == sme_session_id) 4205 return adapter; 4206 4207 qdf_status = 4208 hdd_get_next_adapter(hdd_ctx, 4209 adapter_node, &next); 4210 adapter_node = next; 4211 } 4212 return NULL; 4213 } 4214 4215 /** 4216 * hdd_get_adapter() - to get adapter matching the mode 4217 * @hdd_ctx: hdd context 4218 * @mode: adapter mode 4219 * 4220 * This routine will return the pointer to adapter matching 4221 * with the passed mode. 4222 * 4223 * Return: pointer to adapter or null 4224 */ 4225 hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx, 4226 enum tQDF_ADAPTER_MODE mode) 4227 { 4228 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 4229 hdd_adapter_t *adapter; 4230 QDF_STATUS status; 4231 4232 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 4233 4234 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 4235 adapter = adapterNode->pAdapter; 4236 4237 if (adapter && (mode == adapter->device_mode)) 4238 return adapter; 4239 4240 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 4241 adapterNode = pNext; 4242 } 4243 4244 return NULL; 4245 4246 } 4247 4248 /** 4249 * hdd_get_operating_channel() - return operating channel of the device mode 4250 * @hdd_ctx: Pointer to the HDD context. 4251 * @mode: Device mode for which operating channel is required. 4252 * Suported modes: 4253 * QDF_STA_MODE, 4254 * QDF_P2P_CLIENT_MODE, 4255 * QDF_SAP_MODE, 4256 * QDF_P2P_GO_MODE. 4257 * 4258 * This API returns the operating channel of the requested device mode 4259 * 4260 * Return: channel number. "0" id the requested device is not found OR it is 4261 * not connected. 4262 */ 4263 uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx, 4264 enum tQDF_ADAPTER_MODE mode) 4265 { 4266 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 4267 QDF_STATUS status; 4268 hdd_adapter_t *adapter; 4269 uint8_t operatingChannel = 0; 4270 4271 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 4272 4273 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 4274 adapter = adapterNode->pAdapter; 4275 4276 if (mode == adapter->device_mode) { 4277 switch (adapter->device_mode) { 4278 case QDF_STA_MODE: 4279 case QDF_P2P_CLIENT_MODE: 4280 if (hdd_conn_is_connected 4281 (WLAN_HDD_GET_STATION_CTX_PTR 4282 (adapter))) { 4283 operatingChannel = 4284 (WLAN_HDD_GET_STATION_CTX_PTR 4285 (adapter))->conn_info. 4286 operationChannel; 4287 } 4288 break; 4289 case QDF_SAP_MODE: 4290 case QDF_P2P_GO_MODE: 4291 /* softap connection info */ 4292 if (test_bit 4293 (SOFTAP_BSS_STARTED, 4294 &adapter->event_flags)) 4295 operatingChannel = 4296 (WLAN_HDD_GET_AP_CTX_PTR 4297 (adapter))->operatingChannel; 4298 break; 4299 default: 4300 break; 4301 } 4302 4303 break; /* Found the device of interest. break the loop */ 4304 } 4305 4306 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 4307 adapterNode = pNext; 4308 } 4309 return operatingChannel; 4310 } 4311 4312 static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t * 4313 hdd_ctx) 4314 { 4315 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 4316 QDF_STATUS status; 4317 hdd_adapter_t *adapter; 4318 4319 ENTER(); 4320 4321 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 4322 4323 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 4324 adapter = adapterNode->pAdapter; 4325 if ((adapter->device_mode == QDF_STA_MODE) || 4326 (adapter->device_mode == QDF_P2P_CLIENT_MODE) || 4327 (adapter->device_mode == QDF_IBSS_MODE) || 4328 (adapter->device_mode == QDF_P2P_DEVICE_MODE) || 4329 (adapter->device_mode == QDF_SAP_MODE) || 4330 (adapter->device_mode == QDF_P2P_GO_MODE)) { 4331 wlan_hdd_cfg80211_deregister_frames(adapter); 4332 hdd_unregister_wext(adapter->dev); 4333 } 4334 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 4335 adapterNode = pNext; 4336 } 4337 4338 EXIT(); 4339 4340 return QDF_STATUS_SUCCESS; 4341 } 4342 4343 QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx) 4344 { 4345 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 4346 QDF_STATUS status; 4347 hdd_adapter_t *adapter; 4348 4349 ENTER(); 4350 4351 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 4352 4353 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 4354 adapter = adapterNode->pAdapter; 4355 if ((adapter->device_mode == QDF_STA_MODE) || 4356 (adapter->device_mode == QDF_P2P_CLIENT_MODE) || 4357 (adapter->device_mode == QDF_IBSS_MODE) || 4358 (adapter->device_mode == QDF_P2P_DEVICE_MODE) || 4359 (adapter->device_mode == QDF_SAP_MODE) || 4360 (adapter->device_mode == QDF_P2P_GO_MODE)) { 4361 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId, 4362 eCSR_SCAN_ABORT_DEFAULT); 4363 } 4364 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 4365 adapterNode = pNext; 4366 } 4367 4368 EXIT(); 4369 4370 return QDF_STATUS_SUCCESS; 4371 } 4372 4373 /** 4374 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all 4375 * adapters 4376 * @hdd_ctx: The HDD context containing the adapters to operate on 4377 * 4378 * return: QDF_STATUS_SUCCESS 4379 */ 4380 static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx) 4381 { 4382 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL; 4383 QDF_STATUS status; 4384 hdd_adapter_t *adapter; 4385 int err; 4386 4387 ENTER(); 4388 4389 status = hdd_get_front_adapter(hdd_ctx, &adapter_node); 4390 4391 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) { 4392 adapter = adapter_node->pAdapter; 4393 if ((adapter->device_mode == QDF_STA_MODE) || 4394 (adapter->device_mode == QDF_P2P_CLIENT_MODE) || 4395 (adapter->device_mode == QDF_IBSS_MODE) || 4396 (adapter->device_mode == QDF_P2P_DEVICE_MODE) || 4397 (adapter->device_mode == QDF_SAP_MODE) || 4398 (adapter->device_mode == QDF_P2P_GO_MODE)) { 4399 err = wlan_hdd_sched_scan_stop(adapter->dev); 4400 if (err) 4401 hdd_err("Unable to stop scheduled scan"); 4402 } 4403 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next_node); 4404 adapter_node = next_node; 4405 } 4406 4407 EXIT(); 4408 4409 return QDF_STATUS_SUCCESS; 4410 } 4411 4412 #ifdef WLAN_NS_OFFLOAD 4413 /** 4414 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier 4415 * @hdd_ctx: Pointer to hdd context 4416 * 4417 * Unregister for IPv6 address change notifications. 4418 * 4419 * Return: None 4420 */ 4421 static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx) 4422 { 4423 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier); 4424 4425 return; 4426 } 4427 4428 /** 4429 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier 4430 * @hdd_ctx: Pointer to hdd context 4431 * 4432 * Register for IPv6 address change notifications. 4433 * 4434 * Return: 0 on success and errno on failure. 4435 */ 4436 static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) 4437 { 4438 int ret; 4439 4440 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed; 4441 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier); 4442 if (ret) { 4443 hdd_err("Failed to register IPv6 notifier: %d", ret); 4444 goto out; 4445 } 4446 4447 hdd_info("Registered IPv6 notifier"); 4448 out: 4449 return ret; 4450 } 4451 #else 4452 /** 4453 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier 4454 * @hdd_ctx: Pointer to hdd context 4455 * 4456 * Unregister for IPv6 address change notifications. 4457 * 4458 * Return: None 4459 */ 4460 static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx) 4461 { 4462 } 4463 4464 /** 4465 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier 4466 * @hdd_ctx: Pointer to hdd context 4467 * 4468 * Register for IPv6 address change notifications. 4469 * 4470 * Return: None 4471 */ 4472 static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) 4473 { 4474 return 0; 4475 } 4476 #endif 4477 4478 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE 4479 /** 4480 * hdd_logging_sock_activate_svc() - Activate logging 4481 * @hdd_ctx: HDD context 4482 * 4483 * Activates the logging service 4484 * 4485 * Return: Zero in case of success, negative value otherwise 4486 */ 4487 static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx) 4488 { 4489 int ret; 4490 struct hdd_config *config = hdd_ctx->config; 4491 4492 if (!config->wlanLoggingEnable) 4493 return 0; 4494 4495 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole, 4496 config->wlanLoggingNumBuf); 4497 if (ret) 4498 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret); 4499 return ret; 4500 } 4501 4502 /** 4503 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging 4504 * @hdd_ctx: HDD context 4505 * 4506 * Deactivates the logging service 4507 * 4508 * Return: 0 on deactivating the logging service 4509 */ 4510 static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx) 4511 { 4512 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable) 4513 return wlan_logging_sock_deactivate_svc(); 4514 4515 return 0; 4516 } 4517 #else 4518 static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx) 4519 { 4520 return 0; 4521 } 4522 4523 static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx) 4524 { 4525 return 0; 4526 } 4527 #endif 4528 4529 /** 4530 * hdd_register_notifiers - Register netdev notifiers. 4531 * @hdd_ctx: HDD context 4532 * 4533 * Register netdev notifiers like IPv4 and IPv6. 4534 * 4535 * Return: 0 on success and errno on failure 4536 */ 4537 static int hdd_register_notifiers(hdd_context_t *hdd_ctx) 4538 { 4539 int ret; 4540 4541 ret = register_netdevice_notifier(&hdd_netdev_notifier); 4542 if (ret) { 4543 hdd_err("register_netdevice_notifier failed: %d", ret); 4544 goto out; 4545 } 4546 4547 ret = hdd_wlan_register_ip6_notifier(hdd_ctx); 4548 if (ret) 4549 goto unregister_notifier; 4550 4551 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed; 4552 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier); 4553 if (ret) { 4554 hdd_err("Failed to register IPv4 notifier: %d", ret); 4555 goto unregister_ip6_notifier; 4556 } 4557 4558 return 0; 4559 4560 unregister_ip6_notifier: 4561 hdd_wlan_unregister_ip6_notifier(hdd_ctx); 4562 unregister_notifier: 4563 unregister_netdevice_notifier(&hdd_netdev_notifier); 4564 out: 4565 return ret; 4566 4567 } 4568 4569 /** 4570 * hdd_unregister_notifiers - Unregister netdev notifiers. 4571 * @hdd_ctx: HDD context 4572 * 4573 * Unregister netdev notifiers like IPv4 and IPv6. 4574 * 4575 * Return: None. 4576 */ 4577 static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx) 4578 { 4579 hdd_wlan_unregister_ip6_notifier(hdd_ctx); 4580 4581 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier); 4582 4583 unregister_netdevice_notifier(&hdd_netdev_notifier); 4584 } 4585 4586 /** 4587 * hdd_exit_netlink_services - Exit netlink services 4588 * @hdd_ctx: HDD context 4589 * 4590 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and 4591 * nl service. 4592 * 4593 * Return: None. 4594 */ 4595 static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx) 4596 { 4597 hdd_close_cesium_nl_sock(); 4598 4599 ptt_sock_deactivate_svc(); 4600 4601 nl_srv_exit(); 4602 } 4603 4604 /** 4605 * hdd_init_netlink_services- Init netlink services 4606 * @hdd_ctx: HDD context 4607 * 4608 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and 4609 * nl service. 4610 * 4611 * Return: 0 on success and errno on failure. 4612 */ 4613 static int hdd_init_netlink_services(hdd_context_t *hdd_ctx) 4614 { 4615 int ret; 4616 4617 ret = wlan_hdd_nl_init(hdd_ctx); 4618 if (ret) { 4619 hdd_alert("nl_srv_init failed: %d", ret); 4620 goto out; 4621 } 4622 cds_set_radio_index(hdd_ctx->radio_index); 4623 4624 ret = oem_activate_service(hdd_ctx); 4625 if (ret) { 4626 hdd_alert("oem_activate_service failed: %d", ret); 4627 goto err_nl_srv; 4628 } 4629 4630 ret = ptt_sock_activate_svc(); 4631 if (ret) { 4632 hdd_alert("ptt_sock_activate_svc failed: %d", ret); 4633 goto err_nl_srv; 4634 } 4635 4636 ret = hdd_open_cesium_nl_sock(); 4637 if (ret) 4638 hdd_warn("hdd_open_cesium_nl_sock failed"); 4639 4640 ret = cnss_diag_activate_service(); 4641 if (ret) { 4642 hdd_alert("cnss_diag_activate_service failed: %d", ret); 4643 goto err_close_cesium; 4644 } 4645 4646 return 0; 4647 4648 err_close_cesium: 4649 hdd_close_cesium_nl_sock(); 4650 ptt_sock_deactivate_svc(); 4651 err_nl_srv: 4652 nl_srv_exit(); 4653 out: 4654 return ret; 4655 } 4656 4657 /** 4658 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock 4659 * @hdd_ctx: HDD context. 4660 * 4661 * Destroy RX wakelock. 4662 * 4663 * Return: None. 4664 */ 4665 static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) 4666 { 4667 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock); 4668 } 4669 4670 /** 4671 * hdd_rx_wake_lock_create() - Create RX wakelock 4672 * @hdd_ctx: HDD context. 4673 * 4674 * Create RX wakelock. 4675 * 4676 * Return: None. 4677 */ 4678 static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) 4679 { 4680 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock"); 4681 } 4682 4683 /** 4684 * hdd_roc_context_init() - Init ROC context 4685 * @hdd_ctx: HDD context. 4686 * 4687 * Initialize ROC context. 4688 * 4689 * Return: 0 on success and errno on failure. 4690 */ 4691 static int hdd_roc_context_init(hdd_context_t *hdd_ctx) 4692 { 4693 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock); 4694 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY); 4695 4696 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue); 4697 4698 return 0; 4699 } 4700 4701 /** 4702 * hdd_roc_context_destroy() - Destroy ROC context 4703 * @hdd_ctx: HDD context. 4704 * 4705 * Destroy roc list and flush the pending roc work. 4706 * 4707 * Return: None. 4708 */ 4709 static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx) 4710 { 4711 flush_delayed_work(&hdd_ctx->roc_req_work); 4712 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q); 4713 } 4714 4715 /** 4716 * hdd_context_deinit() - Deinitialize HDD context 4717 * @hdd_ctx: HDD context. 4718 * 4719 * Deinitialize HDD context along with all the feature specific contexts but 4720 * do not free hdd context itself. Caller of this API is supposed to free 4721 * HDD context. 4722 * 4723 * return: 0 on success and errno on failure. 4724 */ 4725 static int hdd_context_deinit(hdd_context_t *hdd_ctx) 4726 { 4727 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy); 4728 4729 hdd_roc_context_destroy(hdd_ctx); 4730 4731 hdd_sap_context_destroy(hdd_ctx); 4732 4733 hdd_rx_wake_lock_destroy(hdd_ctx); 4734 4735 hdd_tdls_context_destroy(hdd_ctx); 4736 4737 hdd_scan_context_destroy(hdd_ctx); 4738 4739 qdf_list_destroy(&hdd_ctx->hddAdapters); 4740 4741 return 0; 4742 } 4743 4744 /** 4745 * hdd_context_destroy() - Destroy HDD context 4746 * @hdd_ctx: HDD context to be destroyed. 4747 * 4748 * Free config and HDD context as well as destroy all the resources. 4749 * 4750 * Return: None 4751 */ 4752 static void hdd_context_destroy(hdd_context_t *hdd_ctx) 4753 { 4754 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) 4755 hdd_logging_sock_deactivate_svc(hdd_ctx); 4756 4757 hdd_context_deinit(hdd_ctx); 4758 4759 qdf_mem_free(hdd_ctx->config); 4760 hdd_ctx->config = NULL; 4761 4762 wiphy_free(hdd_ctx->wiphy); 4763 } 4764 4765 /** 4766 * hdd_wlan_exit() - HDD WLAN exit function 4767 * @hdd_ctx: Pointer to the HDD Context 4768 * 4769 * This is the driver exit point (invoked during rmmod) 4770 * 4771 * Return: None 4772 */ 4773 static void hdd_wlan_exit(hdd_context_t *hdd_ctx) 4774 { 4775 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context; 4776 QDF_STATUS qdf_status; 4777 struct wiphy *wiphy = hdd_ctx->wiphy; 4778 int driver_status; 4779 4780 ENTER(); 4781 4782 if (QDF_TIMER_STATE_RUNNING == 4783 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) { 4784 hdd_info("Stpp interface change timer"); 4785 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer); 4786 } 4787 4788 if (!QDF_IS_STATUS_SUCCESS 4789 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer))) 4790 hdd_err("Cannot delete interface change timer"); 4791 4792 4793 hdd_unregister_notifiers(hdd_ctx); 4794 4795 hdd_bus_bandwidth_destroy(hdd_ctx); 4796 4797 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE 4798 if (QDF_TIMER_STATE_RUNNING == 4799 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) { 4800 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer); 4801 } 4802 4803 if (!QDF_IS_STATUS_SUCCESS 4804 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) { 4805 hdd_err("Cannot deallocate ACS Skip timer"); 4806 } 4807 qdf_spin_lock(&hdd_ctx->acs_skip_lock); 4808 qdf_mem_free(hdd_ctx->last_acs_channel_list); 4809 hdd_ctx->last_acs_channel_list = NULL; 4810 hdd_ctx->num_of_channels = 0; 4811 qdf_spin_unlock(&hdd_ctx->acs_skip_lock); 4812 #endif 4813 4814 mutex_lock(&hdd_ctx->iface_change_lock); 4815 driver_status = hdd_ctx->driver_status; 4816 mutex_unlock(&hdd_ctx->iface_change_lock); 4817 4818 /* 4819 * Powersave Offload Case 4820 * Disable Idle Power Save Mode 4821 */ 4822 hdd_set_idle_ps_config(hdd_ctx, false); 4823 4824 if (driver_status != DRIVER_MODULES_CLOSED) { 4825 hdd_unregister_wext_all_adapters(hdd_ctx); 4826 /* 4827 * Cancel any outstanding scan requests. We are about to close 4828 * all of our adapters, but an adapter structure is what SME 4829 * passes back to our callback function. Hence if there 4830 * are any outstanding scan requests then there is a 4831 * race condition between when the adapter is closed and 4832 * when the callback is invoked. We try to resolve that 4833 * race condition here by canceling any outstanding scans 4834 * before we close the adapters. 4835 * Note that the scans may be cancelled in an asynchronous 4836 * manner, so ideally there needs to be some kind of 4837 * synchronization. Rather than introduce a new 4838 * synchronization here, we will utilize the fact that we are 4839 * about to Request Full Power, and since that is synchronized, 4840 * the expectation is that by the time Request Full Power has 4841 * completed, all scans will be cancelled 4842 */ 4843 hdd_abort_mac_scan_all_adapters(hdd_ctx); 4844 hdd_abort_sched_scan_all_adapters(hdd_ctx); 4845 hdd_stop_all_adapters(hdd_ctx); 4846 } 4847 4848 /* 4849 * Close the scheduler before calling cds_close to make sure no thread 4850 * is scheduled after the each module close is called i.e after all the 4851 * data structures are freed. 4852 */ 4853 qdf_status = cds_sched_close(p_cds_context); 4854 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 4855 hdd_alert("Failed to close CDS Scheduler"); 4856 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 4857 } 4858 4859 hdd_wlan_stop_modules(hdd_ctx); 4860 4861 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock); 4862 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock); 4863 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock); 4864 4865 /* 4866 * Close CDS 4867 * This frees pMac(HAL) context. There should not be any call 4868 * that requires pMac access after this. 4869 */ 4870 4871 hdd_green_ap_deinit(hdd_ctx); 4872 4873 hdd_runtime_suspend_context_deinit(hdd_ctx); 4874 hdd_close_all_adapters(hdd_ctx, false); 4875 4876 hdd_ipa_cleanup(hdd_ctx); 4877 4878 /* Free up RoC request queue and flush workqueue */ 4879 cds_flush_work(&hdd_ctx->roc_req_work); 4880 4881 wlansap_global_deinit(); 4882 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx); 4883 wiphy_unregister(wiphy); 4884 wlan_hdd_cfg80211_deinit(wiphy); 4885 4886 hdd_lpass_notify_stop(hdd_ctx); 4887 4888 hdd_exit_netlink_services(hdd_ctx); 4889 mutex_destroy(&hdd_ctx->iface_change_lock); 4890 hdd_context_destroy(hdd_ctx); 4891 } 4892 4893 void __hdd_wlan_exit(void) 4894 { 4895 hdd_context_t *hdd_ctx; 4896 4897 ENTER(); 4898 4899 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 4900 if (!hdd_ctx) { 4901 hdd_alert("Invalid HDD Context"); 4902 EXIT(); 4903 return; 4904 } 4905 4906 /* Check IPA HW Pipe shutdown */ 4907 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx); 4908 4909 memdump_deinit(); 4910 hdd_driver_memdump_deinit(); 4911 4912 /* Do all the cleanup before deregistering the driver */ 4913 hdd_wlan_exit(hdd_ctx); 4914 4915 EXIT(); 4916 } 4917 4918 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE 4919 /** 4920 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler 4921 * @data: pointer to hdd_context_t 4922 * 4923 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN. 4924 * Then new ACS request will do a fresh scan without reusing the cached 4925 * scan information. 4926 * 4927 * Return: void 4928 */ 4929 void hdd_skip_acs_scan_timer_handler(void *data) 4930 { 4931 hdd_context_t *hdd_ctx = (hdd_context_t *) data; 4932 4933 hdd_notice("ACS Scan result expired. Reset ACS scan skip"); 4934 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN; 4935 qdf_spin_lock(&hdd_ctx->acs_skip_lock); 4936 qdf_mem_free(hdd_ctx->last_acs_channel_list); 4937 hdd_ctx->last_acs_channel_list = NULL; 4938 hdd_ctx->num_of_channels = 0; 4939 qdf_spin_unlock(&hdd_ctx->acs_skip_lock); 4940 4941 if (!hdd_ctx->hHal) 4942 return; 4943 sme_scan_flush_result(hdd_ctx->hHal); 4944 } 4945 #endif 4946 4947 #ifdef QCA_HT_2040_COEX 4948 /** 4949 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode 4950 * @adapter: pointer to adapter 4951 * @staId: station id 4952 * @macAddrSTA: station MAC address 4953 * @channel_type: channel type 4954 * 4955 * This function notifies FW with HT20/HT40 mode 4956 * 4957 * Return: 0 if successful, error number otherwise 4958 */ 4959 int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId, 4960 struct qdf_mac_addr macAddrSTA, int channel_type) 4961 { 4962 int status; 4963 QDF_STATUS qdf_status; 4964 hdd_context_t *hdd_ctx = NULL; 4965 4966 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 4967 4968 status = wlan_hdd_validate_context(hdd_ctx); 4969 if (status) 4970 return status; 4971 4972 if (!hdd_ctx->hHal) 4973 return -EINVAL; 4974 4975 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA, 4976 adapter->sessionId, channel_type); 4977 if (QDF_STATUS_SUCCESS != qdf_status) { 4978 hdd_err("Fail to send notification with ht2040 mode"); 4979 return -EINVAL; 4980 } 4981 4982 return 0; 4983 } 4984 #endif 4985 4986 /** 4987 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status 4988 * @state: state 4989 * 4990 * This function notifies FW with modem power status 4991 * 4992 * Return: 0 if successful, error number otherwise 4993 */ 4994 int hdd_wlan_notify_modem_power_state(int state) 4995 { 4996 int status; 4997 QDF_STATUS qdf_status; 4998 hdd_context_t *hdd_ctx; 4999 5000 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 5001 status = wlan_hdd_validate_context(hdd_ctx); 5002 if (status) 5003 return status; 5004 5005 if (!hdd_ctx->hHal) 5006 return -EINVAL; 5007 5008 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state); 5009 if (QDF_STATUS_SUCCESS != qdf_status) { 5010 hdd_err("Fail to send notification with modem power state %d", 5011 state); 5012 return -EINVAL; 5013 } 5014 return 0; 5015 } 5016 5017 /** 5018 * 5019 * hdd_post_cds_enable_config() - HDD post cds start config helper 5020 * @adapter - Pointer to the HDD 5021 * 5022 * Return: None 5023 */ 5024 QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx) 5025 { 5026 QDF_STATUS qdf_ret_status; 5027 5028 /* 5029 * Send ready indication to the HDD. This will kick off the MAC 5030 * into a 'running' state and should kick off an initial scan. 5031 */ 5032 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal); 5033 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) { 5034 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]", 5035 qdf_ret_status, qdf_ret_status); 5036 return QDF_STATUS_E_FAILURE; 5037 } 5038 5039 return QDF_STATUS_SUCCESS; 5040 } 5041 5042 /* wake lock APIs for HDD */ 5043 void hdd_prevent_suspend(uint32_t reason) 5044 { 5045 qdf_wake_lock_acquire(&wlan_wake_lock, reason); 5046 } 5047 5048 void hdd_allow_suspend(uint32_t reason) 5049 { 5050 qdf_wake_lock_release(&wlan_wake_lock, reason); 5051 } 5052 5053 void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason) 5054 { 5055 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason); 5056 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout); 5057 } 5058 5059 /** 5060 * hdd_exchange_version_and_caps() - exchange version and capability with target 5061 * @hdd_ctx: Pointer to HDD context 5062 * 5063 * This is the HDD function to exchange version and capability information 5064 * between Host and Target 5065 * 5066 * This function gets reported version of FW. 5067 * It also finds the version of target headers used to compile the host; 5068 * It compares the above two and prints a warning if they are different; 5069 * It gets the SW and HW version string; 5070 * Finally, it exchanges capabilities between host and target i.e. host 5071 * and target exchange a msg indicating the features they support through a 5072 * bitmap 5073 * 5074 * Return: None 5075 */ 5076 void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx) 5077 { 5078 5079 tSirVersionType versionCompiled; 5080 tSirVersionType versionReported; 5081 tSirVersionString versionString; 5082 uint8_t fwFeatCapsMsgSupported = 0; 5083 QDF_STATUS vstatus; 5084 5085 memset(&versionCompiled, 0, sizeof(versionCompiled)); 5086 memset(&versionReported, 0, sizeof(versionReported)); 5087 5088 /* retrieve and display WCNSS version information */ 5089 do { 5090 5091 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal, 5092 &versionCompiled); 5093 if (!QDF_IS_STATUS_SUCCESS(vstatus)) { 5094 hdd_alert("unable to retrieve WCNSS WLAN compiled version"); 5095 break; 5096 } 5097 5098 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal, 5099 &versionReported); 5100 if (!QDF_IS_STATUS_SUCCESS(vstatus)) { 5101 hdd_alert("unable to retrieve WCNSS WLAN reported version"); 5102 break; 5103 } 5104 5105 if ((versionCompiled.major != versionReported.major) || 5106 (versionCompiled.minor != versionReported.minor) || 5107 (versionCompiled.version != versionReported.version) || 5108 (versionCompiled.revision != versionReported.revision)) { 5109 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, " 5110 "Host expected %u.%u.%u.%u\n", 5111 WLAN_MODULE_NAME, 5112 (int)versionReported.major, 5113 (int)versionReported.minor, 5114 (int)versionReported.version, 5115 (int)versionReported.revision, 5116 (int)versionCompiled.major, 5117 (int)versionCompiled.minor, 5118 (int)versionCompiled.version, 5119 (int)versionCompiled.revision); 5120 } else { 5121 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n", 5122 WLAN_MODULE_NAME, 5123 (int)versionReported.major, 5124 (int)versionReported.minor, 5125 (int)versionReported.version, 5126 (int)versionReported.revision); 5127 } 5128 5129 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal, 5130 versionString, 5131 sizeof(versionString)); 5132 if (!QDF_IS_STATUS_SUCCESS(vstatus)) { 5133 hdd_alert("unable to retrieve WCNSS software version string"); 5134 break; 5135 } 5136 5137 pr_info("%s: WCNSS software version %s\n", 5138 WLAN_MODULE_NAME, versionString); 5139 5140 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal, 5141 versionString, 5142 sizeof(versionString)); 5143 if (!QDF_IS_STATUS_SUCCESS(vstatus)) { 5144 hdd_alert("unable to retrieve WCNSS hardware version string"); 5145 break; 5146 } 5147 5148 pr_info("%s: WCNSS hardware version %s\n", 5149 WLAN_MODULE_NAME, versionString); 5150 5151 /* 5152 * 1.Check if FW version is greater than 0.1.1.0. Only then 5153 * send host-FW capability exchange message 5154 * 2.Host-FW capability exchange message is only present on 5155 * target 1.1 so send the message only if it the target is 1.1 5156 * minor numbers for different target branches: 5157 * 0 -> (1.0)Mainline Build 5158 * 1 -> (1.1)Mainline Build 5159 * 2->(1.04) Stability Build 5160 */ 5161 if (((versionReported.major > 0) || (versionReported.minor > 1) 5162 || ((versionReported.minor >= 1) 5163 && (versionReported.version >= 1))) 5164 && ((versionReported.major == 1) 5165 && (versionReported.minor >= 1))) 5166 fwFeatCapsMsgSupported = 1; 5167 5168 if (fwFeatCapsMsgSupported) { 5169 /* 5170 * Indicate if IBSS heartbeat monitoring needs to be 5171 * offloaded 5172 */ 5173 if (!hdd_ctx->config->enableIbssHeartBeatOffload) { 5174 sme_disable_feature_capablity 5175 (IBSS_HEARTBEAT_OFFLOAD); 5176 } 5177 5178 sme_feature_caps_exchange(hdd_ctx->hHal); 5179 } 5180 5181 } while (0); 5182 5183 } 5184 5185 /* Initialize channel list in sme based on the country code */ 5186 QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx) 5187 { 5188 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2, 5189 hdd_ctx->reg.cc_src); 5190 } 5191 5192 /** 5193 * hdd_is_5g_supported() - check if hardware supports 5GHz 5194 * @hdd_ctx: Pointer to the hdd context 5195 * 5196 * HDD function to know if hardware supports 5GHz 5197 * 5198 * Return: true if hardware supports 5GHz 5199 */ 5200 bool hdd_is_5g_supported(hdd_context_t *hdd_ctx) 5201 { 5202 if (!hdd_ctx || !hdd_ctx->config) 5203 return true; 5204 5205 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24) 5206 return true; 5207 else 5208 return false; 5209 } 5210 5211 static int hdd_wiphy_init(hdd_context_t *hdd_ctx) 5212 { 5213 struct wiphy *wiphy; 5214 int ret_val; 5215 5216 wiphy = hdd_ctx->wiphy; 5217 5218 /* 5219 * The channel information in 5220 * wiphy needs to be initialized before wiphy registration 5221 */ 5222 ret_val = hdd_regulatory_init(hdd_ctx, wiphy); 5223 if (ret_val) { 5224 hdd_alert("regulatory init failed"); 5225 return ret_val; 5226 } 5227 5228 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) 5229 wiphy->wowlan = &wowlan_support_reg_init; 5230 #else 5231 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | 5232 WIPHY_WOWLAN_MAGIC_PKT | 5233 WIPHY_WOWLAN_DISCONNECT | 5234 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | 5235 WIPHY_WOWLAN_GTK_REKEY_FAILURE | 5236 WIPHY_WOWLAN_EAP_IDENTITY_REQ | 5237 WIPHY_WOWLAN_4WAY_HANDSHAKE | 5238 WIPHY_WOWLAN_RFKILL_RELEASE; 5239 5240 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS * 5241 WOW_MAX_FILTERS_PER_LIST); 5242 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE; 5243 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE; 5244 #endif 5245 5246 /* registration of wiphy dev with cfg80211 */ 5247 ret_val = wlan_hdd_cfg80211_register(wiphy); 5248 if (0 > ret_val) 5249 hdd_err("wiphy registration failed"); 5250 5251 return ret_val; 5252 } 5253 5254 /** 5255 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth 5256 * @hdd_ctx - handle to hdd context 5257 * @tx_packets - transmit packet count 5258 * @rx_packets - receive packet count 5259 * 5260 * The function controls the bus bandwidth and dynamic control of 5261 * tcp delayed ack configuration 5262 * 5263 * Returns: None 5264 */ 5265 #ifdef MSM_PLATFORM 5266 static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx, 5267 const uint64_t tx_packets, 5268 const uint64_t rx_packets) 5269 { 5270 uint64_t total = tx_packets + rx_packets; 5271 uint64_t temp_rx = 0; 5272 uint64_t temp_tx = 0; 5273 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE; 5274 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE; 5275 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE; 5276 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count; 5277 5278 if (total > hdd_ctx->config->busBandwidthHighThreshold) 5279 next_vote_level = PLD_BUS_WIDTH_HIGH; 5280 else if (total > hdd_ctx->config->busBandwidthMediumThreshold) 5281 next_vote_level = PLD_BUS_WIDTH_MEDIUM; 5282 else if (total > hdd_ctx->config->busBandwidthLowThreshold) 5283 next_vote_level = PLD_BUS_WIDTH_LOW; 5284 else 5285 next_vote_level = PLD_BUS_WIDTH_NONE; 5286 5287 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level = 5288 next_vote_level; 5289 5290 if (hdd_ctx->cur_vote_level != next_vote_level) { 5291 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld", 5292 next_vote_level, tx_packets, rx_packets); 5293 hdd_ctx->cur_vote_level = next_vote_level; 5294 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level); 5295 if (next_vote_level == PLD_BUS_WIDTH_LOW) { 5296 if (hdd_ctx->hbw_requested) { 5297 pld_remove_pm_qos(hdd_ctx->parent_dev); 5298 hdd_ctx->hbw_requested = false; 5299 } 5300 if (cds_sched_handle_throughput_req(false)) 5301 hdd_err("low bandwidth set rx affinity fail"); 5302 } else { 5303 if (!hdd_ctx->hbw_requested) { 5304 pld_request_pm_qos(hdd_ctx->parent_dev, 1); 5305 hdd_ctx->hbw_requested = true; 5306 } 5307 5308 if (cds_sched_handle_throughput_req(true)) 5309 hdd_err("high bandwidth set rx affinity fail"); 5310 } 5311 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets); 5312 } 5313 5314 /* fine-tuning parameters for RX Flows */ 5315 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2; 5316 5317 hdd_ctx->prev_rx = rx_packets; 5318 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) { 5319 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) && 5320 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) { 5321 next_rx_level = WLAN_SVC_TP_HIGH; 5322 } 5323 } else { 5324 next_rx_level = WLAN_SVC_TP_LOW; 5325 hdd_ctx->rx_high_ind_cnt = 0; 5326 } 5327 5328 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level = 5329 next_rx_level; 5330 5331 if (hdd_ctx->cur_rx_level != next_rx_level) { 5332 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu", 5333 next_rx_level, temp_rx); 5334 hdd_ctx->cur_rx_level = next_rx_level; 5335 /* Send throughput indication only if it is enabled. 5336 * Disabling tcp_del_ack will revert the tcp stack behavior 5337 * to default delayed ack. Note that this will disable the 5338 * dynamic delayed ack mechanism across the system 5339 */ 5340 if (hdd_ctx->config->enable_tcp_delack) 5341 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index, 5342 WLAN_SVC_WLAN_TP_IND, 5343 &next_rx_level, 5344 sizeof(next_rx_level)); 5345 } 5346 5347 /* fine-tuning parameters for TX Flows */ 5348 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2; 5349 hdd_ctx->prev_tx = tx_packets; 5350 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres) 5351 next_tx_level = WLAN_SVC_TP_HIGH; 5352 else 5353 next_tx_level = WLAN_SVC_TP_LOW; 5354 5355 if (hdd_ctx->cur_tx_level != next_tx_level) { 5356 hdd_debug("change TCP TX trigger level %d, average_tx: %llu", 5357 next_tx_level, temp_tx); 5358 hdd_ctx->cur_tx_level = next_tx_level; 5359 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index, 5360 WLAN_SVC_WLAN_TP_TX_IND, 5361 &next_tx_level, 5362 sizeof(next_tx_level)); 5363 } 5364 5365 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level = 5366 next_tx_level; 5367 hdd_ctx->hdd_txrx_hist_idx++; 5368 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK; 5369 } 5370 5371 #define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1) 5372 static void hdd_bus_bw_compute_cbk(void *priv) 5373 { 5374 hdd_context_t *hdd_ctx = (hdd_context_t *) priv; 5375 hdd_adapter_t *adapter = NULL; 5376 uint64_t tx_packets = 0, rx_packets = 0; 5377 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0; 5378 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0; 5379 uint64_t total_tx = 0, total_rx = 0; 5380 hdd_adapter_list_node_t *adapterNode = NULL; 5381 QDF_STATUS status = 0; 5382 A_STATUS ret; 5383 bool connected = false; 5384 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0; 5385 5386 if (wlan_hdd_validate_context(hdd_ctx)) 5387 return; 5388 5389 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 5390 NULL != adapterNode && QDF_STATUS_SUCCESS == status; 5391 status = 5392 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) { 5393 5394 if (adapterNode->pAdapter == NULL) 5395 continue; 5396 adapter = adapterNode->pAdapter; 5397 /* 5398 * Validate magic so we don't end up accessing 5399 * an invalid adapter. 5400 */ 5401 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) 5402 continue; 5403 5404 if ((adapter->device_mode == QDF_STA_MODE || 5405 adapter->device_mode == QDF_P2P_CLIENT_MODE) && 5406 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState 5407 != eConnectionState_Associated) { 5408 5409 continue; 5410 } 5411 5412 if ((adapter->device_mode == QDF_SAP_MODE || 5413 adapter->device_mode == QDF_P2P_GO_MODE) && 5414 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) { 5415 5416 continue; 5417 } 5418 5419 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets, 5420 adapter->prev_tx_packets); 5421 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets, 5422 adapter->prev_rx_packets); 5423 5424 if (adapter->device_mode == QDF_SAP_MODE || 5425 adapter->device_mode == QDF_P2P_GO_MODE || 5426 adapter->device_mode == QDF_IBSS_MODE) { 5427 5428 ret = ol_get_intra_bss_fwd_pkts_count( 5429 adapter->sessionId, 5430 &fwd_tx_packets, &fwd_rx_packets); 5431 if (ret == A_OK) { 5432 fwd_tx_packets_diff += HDD_BW_GET_DIFF( 5433 fwd_tx_packets, 5434 adapter->prev_fwd_tx_packets); 5435 fwd_rx_packets_diff += HDD_BW_GET_DIFF( 5436 fwd_tx_packets, 5437 adapter->prev_fwd_rx_packets); 5438 } 5439 } 5440 5441 total_rx += adapter->stats.rx_packets; 5442 total_tx += adapter->stats.tx_packets; 5443 5444 spin_lock_bh(&hdd_ctx->bus_bw_lock); 5445 adapter->prev_tx_packets = adapter->stats.tx_packets; 5446 adapter->prev_rx_packets = adapter->stats.rx_packets; 5447 adapter->prev_fwd_tx_packets = fwd_tx_packets; 5448 adapter->prev_fwd_rx_packets = fwd_rx_packets; 5449 spin_unlock_bh(&hdd_ctx->bus_bw_lock); 5450 connected = true; 5451 } 5452 5453 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx; 5454 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx; 5455 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx = 5456 rx_packets; 5457 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx = 5458 tx_packets; 5459 5460 /* add intra bss forwarded tx and rx packets */ 5461 tx_packets += fwd_tx_packets_diff; 5462 rx_packets += fwd_rx_packets_diff; 5463 5464 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets); 5465 tx_packets += (uint64_t)ipa_tx_packets; 5466 rx_packets += (uint64_t)ipa_rx_packets; 5467 5468 if (!connected) { 5469 hdd_err("bus bandwidth timer running in disconnected state"); 5470 return; 5471 } 5472 5473 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets); 5474 5475 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets); 5476 hdd_ipa_uc_stat_request(adapter, 2); 5477 5478 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer, 5479 hdd_ctx->config->busBandwidthComputeInterval); 5480 } 5481 5482 int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx) 5483 { 5484 spin_lock_init(&hdd_ctx->bus_bw_lock); 5485 5486 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer, 5487 QDF_TIMER_TYPE_SW, 5488 hdd_bus_bw_compute_cbk, (void *)hdd_ctx); 5489 5490 return 0; 5491 } 5492 5493 void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx) 5494 { 5495 if (qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer) == 5496 QDF_TIMER_STATE_RUNNING) 5497 hdd_reset_tcp_delack(hdd_ctx); 5498 5499 qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer); 5500 } 5501 #endif 5502 5503 /** 5504 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats 5505 * @hdd_ctx: hdd context 5506 * 5507 * Return: 0 for success or error code 5508 */ 5509 static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx) 5510 { 5511 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc( 5512 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM)); 5513 if (hdd_ctx->hdd_txrx_hist == NULL) { 5514 hdd_err("Failed malloc for hdd_txrx_hist"); 5515 return -ENOMEM; 5516 } 5517 return 0; 5518 } 5519 5520 /** 5521 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats 5522 * @hdd_ctx: hdd context 5523 * 5524 * Return: none 5525 */ 5526 void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx) 5527 { 5528 if (hdd_ctx->hdd_txrx_hist) { 5529 qdf_mem_free(hdd_ctx->hdd_txrx_hist); 5530 hdd_ctx->hdd_txrx_hist = NULL; 5531 } 5532 } 5533 5534 static uint8_t *convert_level_to_string(uint32_t level) 5535 { 5536 switch (level) { 5537 /* initialize the wlan sub system */ 5538 case WLAN_SVC_TP_NONE: 5539 return "NONE"; 5540 case WLAN_SVC_TP_LOW: 5541 return "LOW"; 5542 case WLAN_SVC_TP_MEDIUM: 5543 return "MED"; 5544 case WLAN_SVC_TP_HIGH: 5545 return "HIGH"; 5546 default: 5547 return "INVAL"; 5548 } 5549 } 5550 5551 5552 /** 5553 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram 5554 * @hdd_ctx: hdd context 5555 * 5556 * Return: none 5557 */ 5558 void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx) 5559 { 5560 int i; 5561 5562 #ifdef MSM_PLATFORM 5563 hdd_err("BW compute Interval: %dms", 5564 hdd_ctx->config->busBandwidthComputeInterval); 5565 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d", 5566 hdd_ctx->config->busBandwidthHighThreshold, 5567 hdd_ctx->config->busBandwidthMediumThreshold, 5568 hdd_ctx->config->busBandwidthLowThreshold); 5569 hdd_err("Enable TCP DEL ACK: %d", 5570 hdd_ctx->config->enable_tcp_delack); 5571 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d", 5572 hdd_ctx->config->tcpDelackThresholdHigh, 5573 hdd_ctx->config->tcpDelackThresholdLow); 5574 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)", 5575 hdd_ctx->config->tcp_tx_high_tput_thres); 5576 #endif 5577 5578 hdd_err("Total entries: %d Current index: %d", 5579 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx); 5580 5581 hdd_err("index, total_rx, interval_rx, total_tx, interval_tx, bus_bw_level, RX TP Level, TX TP Level"); 5582 5583 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) { 5584 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s", 5585 i, hdd_ctx->hdd_txrx_hist[i].total_rx, 5586 hdd_ctx->hdd_txrx_hist[i].interval_rx, 5587 hdd_ctx->hdd_txrx_hist[i].total_tx, 5588 hdd_ctx->hdd_txrx_hist[i].interval_tx, 5589 convert_level_to_string( 5590 hdd_ctx->hdd_txrx_hist[i].next_vote_level), 5591 convert_level_to_string( 5592 hdd_ctx->hdd_txrx_hist[i].next_rx_level), 5593 convert_level_to_string( 5594 hdd_ctx->hdd_txrx_hist[i].next_tx_level)); 5595 } 5596 return; 5597 } 5598 5599 /** 5600 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram 5601 * @hdd_ctx: hdd context 5602 * 5603 * Return: none 5604 */ 5605 void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx) 5606 { 5607 hdd_ctx->hdd_txrx_hist_idx = 0; 5608 qdf_mem_zero(hdd_ctx->hdd_txrx_hist, 5609 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM)); 5610 } 5611 5612 /** 5613 * wlan_hdd_display_netif_queue_history() - display netif queue operation history 5614 * @pHddCtx: hdd context 5615 * 5616 * Return: none 5617 */ 5618 void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx) 5619 { 5620 5621 hdd_adapter_t *adapter = NULL; 5622 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; 5623 QDF_STATUS status; 5624 int i; 5625 qdf_time_t total, pause, unpause, curr_time, delta; 5626 5627 status = hdd_get_front_adapter(hdd_ctx, &adapter_node); 5628 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) { 5629 adapter = adapter_node->pAdapter; 5630 5631 hdd_err("\nNetif queue operation statistics:"); 5632 hdd_err("Session_id %d device mode %d", 5633 adapter->sessionId, adapter->device_mode); 5634 hdd_err("Current pause_map value %x", adapter->pause_map); 5635 curr_time = qdf_system_ticks(); 5636 total = curr_time - adapter->start_time; 5637 delta = curr_time - adapter->last_time; 5638 if (adapter->pause_map) { 5639 pause = adapter->total_pause_time + delta; 5640 unpause = adapter->total_unpause_time; 5641 } else { 5642 unpause = adapter->total_unpause_time + delta; 5643 pause = adapter->total_pause_time; 5644 } 5645 hdd_err("Total: %ums Pause: %ums Unpause: %ums", 5646 qdf_system_ticks_to_msecs(total), 5647 qdf_system_ticks_to_msecs(pause), 5648 qdf_system_ticks_to_msecs(unpause)); 5649 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time"); 5650 5651 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) { 5652 qdf_time_t pause_delta = 0; 5653 5654 if (adapter->pause_map & (1 << i)) 5655 pause_delta = delta; 5656 5657 hdd_err("%s: %d: %d: %ums", 5658 hdd_reason_type_to_string(i), 5659 adapter->queue_oper_stats[i].pause_count, 5660 adapter->queue_oper_stats[i].unpause_count, 5661 qdf_system_ticks_to_msecs( 5662 adapter->queue_oper_stats[i].total_pause_time + 5663 pause_delta)); 5664 } 5665 5666 hdd_err("\nNetif queue operation history:"); 5667 hdd_err("Total entries: %d current index %d", 5668 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index); 5669 5670 hdd_err("index: time: action_type: reason_type: pause_map"); 5671 5672 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) { 5673 hdd_err("%d: %u: %s: %s: %x", 5674 i, qdf_system_ticks_to_msecs( 5675 adapter->queue_oper_history[i].time), 5676 hdd_action_type_to_string( 5677 adapter->queue_oper_history[i].netif_action), 5678 hdd_reason_type_to_string( 5679 adapter->queue_oper_history[i].netif_reason), 5680 adapter->queue_oper_history[i].pause_map); 5681 } 5682 5683 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); 5684 adapter_node = next; 5685 } 5686 5687 5688 } 5689 5690 /** 5691 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history 5692 * @hdd_ctx: hdd context 5693 * 5694 * Return: none 5695 */ 5696 void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx) 5697 { 5698 hdd_adapter_t *adapter = NULL; 5699 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; 5700 QDF_STATUS status; 5701 5702 status = hdd_get_front_adapter(hdd_ctx, &adapter_node); 5703 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) { 5704 adapter = adapter_node->pAdapter; 5705 5706 qdf_mem_zero(adapter->queue_oper_stats, 5707 sizeof(adapter->queue_oper_stats)); 5708 qdf_mem_zero(adapter->queue_oper_history, 5709 sizeof(adapter->queue_oper_history)); 5710 adapter->history_index = 0; 5711 adapter->start_time = adapter->last_time = qdf_system_ticks(); 5712 adapter->total_pause_time = 0; 5713 adapter->total_unpause_time = 0; 5714 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); 5715 adapter_node = next; 5716 } 5717 } 5718 5719 /** 5720 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results 5721 * @halHandle: Hal handle 5722 * @pContext: Pointer to the context 5723 * @sessionId: Session ID 5724 * @scanId: Scan ID 5725 * @status: Status 5726 * 5727 * This is the callback to be executed when 11d scan is completed to flush out 5728 * the scan results 5729 * 5730 * 11d scan is done during driver load and is a passive scan on all 5731 * channels supported by the device, 11d scans may find some APs on 5732 * frequencies which are forbidden to be used in the regulatory domain 5733 * the device is operating in. If these APs are notified to the supplicant 5734 * it may try to connect to these APs, thus flush out all the scan results 5735 * which are present in SME after 11d scan is done. 5736 * 5737 * Return: QDF_STATUS_SUCCESS 5738 */ 5739 static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext, 5740 uint8_t sessionId, uint32_t scanId, 5741 eCsrScanStatus status) 5742 { 5743 ENTER(); 5744 5745 sme_scan_flush_result(halHandle); 5746 5747 EXIT(); 5748 5749 return QDF_STATUS_SUCCESS; 5750 } 5751 5752 #ifdef WLAN_FEATURE_OFFLOAD_PACKETS 5753 /** 5754 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context 5755 * @hdd_ctx: hdd global context 5756 * 5757 * Return: none 5758 */ 5759 static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx) 5760 { 5761 uint8_t i; 5762 5763 mutex_init(&hdd_ctx->op_ctx.op_lock); 5764 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) { 5765 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID; 5766 hdd_ctx->op_ctx.op_table[i].pattern_id = i; 5767 } 5768 } 5769 #else 5770 static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx) 5771 { 5772 } 5773 #endif 5774 5775 #ifdef WLAN_FEATURE_FASTPATH 5776 /** 5777 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI 5778 * @hdd_cfg: hdd config 5779 * @context: lower layer context 5780 * 5781 * Return: none 5782 */ 5783 void hdd_enable_fastpath(struct hdd_config *hdd_cfg, 5784 void *context) 5785 { 5786 if (hdd_cfg->fastpath_enable) 5787 hif_enable_fastpath(context); 5788 } 5789 #endif 5790 5791 #if defined(FEATURE_WLAN_CH_AVOID) 5792 /** 5793 * hdd_set_thermal_level_cb() - set thermal level callback function 5794 * @context: hdd context pointer 5795 * @level: thermal level 5796 * 5797 * Change IPA data path to SW path when the thermal throttle level greater 5798 * than 0, and restore the original data path when throttle level is 0 5799 * 5800 * Return: none 5801 */ 5802 static void hdd_set_thermal_level_cb(void *context, u_int8_t level) 5803 { 5804 hdd_context_t *hdd_ctx = context; 5805 5806 /* Change IPA to SW path when throttle level greater than 0 */ 5807 if (level > THROTTLE_LEVEL_0) 5808 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true); 5809 else 5810 /* restore original concurrency mode */ 5811 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode); 5812 } 5813 5814 /** 5815 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP 5816 * restart 5817 * @adapter: AP adapter, which should be checked for NULL 5818 * 5819 * Get a safe channel to restart SAP. PCL already takes into account the 5820 * unsafe channels. So, the PCL is validated with the ACS range to provide 5821 * a safe channel for the SAP to restart. 5822 * 5823 * Return: Channel number to restart SAP in case of success. In case of any 5824 * failure, the channel number returned is zero. 5825 */ 5826 static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range( 5827 hdd_adapter_t *adapter) 5828 { 5829 struct sir_pcl_list pcl; 5830 QDF_STATUS status; 5831 uint32_t i, j; 5832 tHalHandle *hal_handle; 5833 hdd_context_t *hdd_ctx; 5834 bool found = false; 5835 5836 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 5837 if (!hdd_ctx) { 5838 hdd_err("invalid HDD context"); 5839 return INVALID_CHANNEL_ID; 5840 } 5841 5842 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter); 5843 if (!hal_handle) { 5844 hdd_err("invalid HAL handle"); 5845 return INVALID_CHANNEL_ID; 5846 } 5847 5848 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE, 5849 pcl.pcl_list, &pcl.pcl_len, 5850 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list)); 5851 if (QDF_IS_STATUS_ERROR(status)) { 5852 hdd_err("Get PCL failed"); 5853 return INVALID_CHANNEL_ID; 5854 } 5855 5856 if (!pcl.pcl_len) { 5857 hdd_alert("pcl length is zero. this is not expected"); 5858 return INVALID_CHANNEL_ID; 5859 } 5860 5861 hdd_info("start:%d end:%d", 5862 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch, 5863 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch); 5864 5865 /* PCL already takes unsafe channel into account */ 5866 for (i = 0; i < pcl.pcl_len; i++) { 5867 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]); 5868 if ((pcl.pcl_list[i] >= 5869 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) && 5870 (pcl.pcl_list[i] <= 5871 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) { 5872 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]); 5873 return pcl.pcl_list[i]; 5874 } 5875 } 5876 5877 hdd_info("no safe channel from PCL found in ACS range"); 5878 5879 /* Try for safe channel from all valid channel */ 5880 pcl.pcl_len = MAX_NUM_CHAN; 5881 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list, 5882 &pcl.pcl_len); 5883 if (QDF_IS_STATUS_ERROR(status)) { 5884 hdd_err("error in getting valid channel list"); 5885 return INVALID_CHANNEL_ID; 5886 } 5887 5888 for (i = 0; i < pcl.pcl_len; i++) { 5889 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]); 5890 found = false; 5891 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) { 5892 if (pcl.pcl_list[i] == 5893 hdd_ctx->unsafe_channel_list[j]) { 5894 hdd_info("unsafe chan:%d", pcl.pcl_list[i]); 5895 found = true; 5896 break; 5897 } 5898 } 5899 5900 if (found) 5901 continue; 5902 5903 if ((pcl.pcl_list[i] >= 5904 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) && 5905 (pcl.pcl_list[i] <= 5906 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) { 5907 hdd_info("found safe chan:%d", pcl.pcl_list[i]); 5908 return pcl.pcl_list[i]; 5909 } 5910 } 5911 5912 return INVALID_CHANNEL_ID; 5913 } 5914 5915 /** 5916 * hdd_restart_sap() - Restarts SAP on the given channel 5917 * @adapter: AP adapter 5918 * @channel: Channel 5919 * 5920 * Restarts the SAP interface by invoking the function which executes the 5921 * callback to perform channel switch using (E)CSA. 5922 * 5923 * Return: None 5924 */ 5925 static void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel) 5926 { 5927 hdd_ap_ctx_t *hdd_ap_ctx; 5928 tHalHandle *hal_handle; 5929 5930 if (!adapter) { 5931 hdd_err("invalid adapter"); 5932 return; 5933 } 5934 5935 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); 5936 5937 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter); 5938 if (!hal_handle) { 5939 hdd_err("invalid HAL handle"); 5940 return; 5941 } 5942 5943 hdd_ap_ctx->sapConfig.channel = channel; 5944 hdd_ap_ctx->sapConfig.ch_params.ch_width = 5945 hdd_ap_ctx->sapConfig.ch_width_orig; 5946 5947 hdd_info("chan:%d width:%d", 5948 channel, hdd_ap_ctx->sapConfig.ch_width_orig); 5949 5950 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel, 5951 hdd_ap_ctx->sapConfig.sec_ch, 5952 &hdd_ap_ctx->sapConfig.ch_params); 5953 5954 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx); 5955 } 5956 /** 5957 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel 5958 * @hdd_ctx: hdd context pointer 5959 * 5960 * hdd_unsafe_channel_restart_sap check all unsafe channel list 5961 * and if ACS is enabled, driver will ask userspace to restart the 5962 * sap. User space on LTE coex indication restart driver. 5963 * 5964 * Return - none 5965 */ 5966 void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt) 5967 { 5968 QDF_STATUS status; 5969 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; 5970 hdd_adapter_t *adapter_temp; 5971 uint32_t i; 5972 bool found = false; 5973 uint8_t restart_chan; 5974 5975 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node); 5976 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) { 5977 adapter_temp = adapter_node->pAdapter; 5978 5979 if (!adapter_temp) { 5980 hdd_err("adapter is NULL, moving to next one"); 5981 goto next_adapater; 5982 } 5983 5984 if (!((adapter_temp->device_mode == QDF_SAP_MODE) && 5985 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) { 5986 hdd_info("skip device mode:%d acs:%d", 5987 adapter_temp->device_mode, 5988 adapter_temp->sessionCtx.ap.sapConfig. 5989 acs_cfg.acs_mode); 5990 goto next_adapater; 5991 } 5992 5993 found = false; 5994 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) { 5995 if (adapter_temp->sessionCtx.ap.operatingChannel == 5996 hdd_ctxt->unsafe_channel_list[i]) { 5997 found = true; 5998 hdd_info("operating ch:%d is unsafe", 5999 adapter_temp->sessionCtx.ap.operatingChannel); 6000 break; 6001 } 6002 } 6003 6004 if (!found) { 6005 hdd_info("ch:%d is safe. no need to change channel", 6006 adapter_temp->sessionCtx.ap.operatingChannel); 6007 goto next_adapater; 6008 } 6009 6010 restart_chan = 6011 hdd_get_safe_channel_from_pcl_and_acs_range( 6012 adapter_temp); 6013 if (!restart_chan) { 6014 hdd_alert("fail to restart SAP"); 6015 } else { 6016 /* SAP restart due to unsafe channel. While restarting 6017 * the SAP, make sure to clear acs_channel, channel to 6018 * reset to 0. Otherwise these settings will override 6019 * the ACS while restart. 6020 */ 6021 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT; 6022 adapter_temp->sessionCtx.ap.sapConfig.channel = 6023 AUTO_CHANNEL_SELECT; 6024 hdd_info("sending coex indication"); 6025 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index, 6026 WLAN_SVC_LTE_COEX_IND, NULL, 0); 6027 hdd_restart_sap(adapter_temp, restart_chan); 6028 } 6029 6030 next_adapater: 6031 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next); 6032 adapter_node = next; 6033 } 6034 } 6035 /** 6036 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler 6037 * @adapter: HDD adapter pointer 6038 * @indParam: Channel avoid notification parameter 6039 * 6040 * Avoid channel notification from FW handler. 6041 * FW will send un-safe channel list to avoid over wrapping. 6042 * hostapd should not use notified channel 6043 * 6044 * Return: None 6045 */ 6046 void hdd_ch_avoid_cb(void *hdd_context, void *indi_param) 6047 { 6048 hdd_context_t *hdd_ctxt; 6049 tSirChAvoidIndType *ch_avoid_indi; 6050 uint8_t range_loop; 6051 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL, 6052 end_channel_idx = INVALID_CHANNEL; 6053 uint16_t start_channel; 6054 uint16_t end_channel; 6055 v_CONTEXT_t cds_context; 6056 tHddAvoidFreqList hdd_avoid_freq_list; 6057 uint32_t i; 6058 6059 /* Basic sanity */ 6060 if (!hdd_context || !indi_param) { 6061 hdd_err("Invalid arguments"); 6062 return; 6063 } 6064 6065 hdd_ctxt = (hdd_context_t *) hdd_context; 6066 ch_avoid_indi = (tSirChAvoidIndType *) indi_param; 6067 cds_context = hdd_ctxt->pcds_context; 6068 6069 /* Make unsafe channel list */ 6070 hdd_notice("band count %d", 6071 ch_avoid_indi->avoid_range_count); 6072 6073 /* generate vendor specific event */ 6074 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList)); 6075 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) { 6076 hdd_avoid_freq_list.avoidFreqRange[i].startFreq = 6077 ch_avoid_indi->avoid_freq_range[i].start_freq; 6078 hdd_avoid_freq_list.avoidFreqRange[i].endFreq = 6079 ch_avoid_indi->avoid_freq_range[i].end_freq; 6080 } 6081 hdd_avoid_freq_list.avoidFreqRangeCount = 6082 ch_avoid_indi->avoid_range_count; 6083 6084 /* clear existing unsafe channel cache */ 6085 hdd_ctxt->unsafe_channel_count = 0; 6086 qdf_mem_zero(hdd_ctxt->unsafe_channel_list, 6087 sizeof(hdd_ctxt->unsafe_channel_list)); 6088 6089 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count; 6090 range_loop++) { 6091 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) { 6092 hdd_warn("LTE Coex unsafe channel list full"); 6093 break; 6094 } 6095 6096 start_channel = ieee80211_frequency_to_channel( 6097 ch_avoid_indi->avoid_freq_range[range_loop].start_freq); 6098 end_channel = ieee80211_frequency_to_channel( 6099 ch_avoid_indi->avoid_freq_range[range_loop].end_freq); 6100 hdd_notice("start %d : %d, end %d : %d", 6101 ch_avoid_indi->avoid_freq_range[range_loop].start_freq, 6102 start_channel, 6103 ch_avoid_indi->avoid_freq_range[range_loop].end_freq, 6104 end_channel); 6105 6106 /* do not process frequency bands that are not mapped to 6107 * predefined channels 6108 */ 6109 if (start_channel == 0 || end_channel == 0) 6110 continue; 6111 6112 for (channel_loop = CHAN_ENUM_1; channel_loop <= 6113 CHAN_ENUM_184; channel_loop++) { 6114 if (CDS_CHANNEL_FREQ(channel_loop) >= 6115 ch_avoid_indi->avoid_freq_range[ 6116 range_loop].start_freq) { 6117 start_channel_idx = channel_loop; 6118 break; 6119 } 6120 } 6121 for (channel_loop = CHAN_ENUM_1; channel_loop <= 6122 CHAN_ENUM_184; channel_loop++) { 6123 if (CDS_CHANNEL_FREQ(channel_loop) >= 6124 ch_avoid_indi->avoid_freq_range[ 6125 range_loop].end_freq) { 6126 end_channel_idx = channel_loop; 6127 if (CDS_CHANNEL_FREQ(channel_loop) > 6128 ch_avoid_indi->avoid_freq_range[ 6129 range_loop].end_freq) 6130 end_channel_idx--; 6131 break; 6132 } 6133 } 6134 6135 if (start_channel_idx == INVALID_CHANNEL || 6136 end_channel_idx == INVALID_CHANNEL) 6137 continue; 6138 6139 for (channel_loop = start_channel_idx; channel_loop <= 6140 end_channel_idx; channel_loop++) { 6141 hdd_ctxt->unsafe_channel_list[ 6142 hdd_ctxt->unsafe_channel_count++] = 6143 CDS_CHANNEL_NUM(channel_loop); 6144 if (hdd_ctxt->unsafe_channel_count >= 6145 NUM_CHANNELS) { 6146 hdd_warn("LTECoex unsafe ch list full"); 6147 break; 6148 } 6149 } 6150 } 6151 6152 hdd_notice("number of unsafe channels is %d ", 6153 hdd_ctxt->unsafe_channel_count); 6154 6155 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev, 6156 hdd_ctxt->unsafe_channel_list, 6157 hdd_ctxt->unsafe_channel_count)) { 6158 hdd_err("Failed to set unsafe channel"); 6159 6160 /* clear existing unsafe channel cache */ 6161 hdd_ctxt->unsafe_channel_count = 0; 6162 qdf_mem_zero(hdd_ctxt->unsafe_channel_list, 6163 sizeof(hdd_ctxt->unsafe_channel_list)); 6164 6165 return; 6166 } 6167 6168 for (channel_loop = 0; 6169 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) { 6170 hdd_notice("channel %d is not safe ", 6171 hdd_ctxt->unsafe_channel_list[channel_loop]); 6172 } 6173 6174 /* 6175 * first update the unsafe channel list to the platform driver and 6176 * send the avoid freq event to the application 6177 */ 6178 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list); 6179 6180 if (!hdd_ctxt->unsafe_channel_count) { 6181 hdd_info("no unsafe channels - not restarting SAP"); 6182 return; 6183 } 6184 hdd_unsafe_channel_restart_sap(hdd_ctxt); 6185 return; 6186 } 6187 6188 /** 6189 * hdd_init_channel_avoidance() - Initialize channel avoidance 6190 * @hdd_ctx: HDD global context 6191 * 6192 * Initialize the channel avoidance logic by retrieving the unsafe 6193 * channel list from the platform driver and plumbing the data 6194 * down to the lower layers. Then subscribe to subsequent channel 6195 * avoidance events. 6196 * 6197 * Return: None 6198 */ 6199 static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx) 6200 { 6201 uint16_t unsafe_channel_count; 6202 int index; 6203 6204 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev, 6205 hdd_ctx->unsafe_channel_list, 6206 &(hdd_ctx->unsafe_channel_count), 6207 sizeof(uint16_t) * NUM_CHANNELS); 6208 6209 hdd_notice("num of unsafe channels is %d", 6210 hdd_ctx->unsafe_channel_count); 6211 6212 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count, 6213 (uint16_t)NUM_CHANNELS); 6214 6215 for (index = 0; index < unsafe_channel_count; index++) { 6216 hdd_notice("channel %d is not safe", 6217 hdd_ctx->unsafe_channel_list[index]); 6218 6219 } 6220 6221 /* Plug in avoid channel notification callback */ 6222 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb); 6223 } 6224 #else 6225 static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx) 6226 { 6227 } 6228 static void hdd_set_thermal_level_cb(void *context, u_int8_t level) 6229 { 6230 } 6231 #endif /* defined(FEATURE_WLAN_CH_AVOID) */ 6232 6233 /** 6234 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to 6235 * user space 6236 * @frame_ind: Management frame data to be informed. 6237 * 6238 * This function is used to indicate management frame to 6239 * user space 6240 * 6241 * Return: None 6242 * 6243 */ 6244 void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind) 6245 { 6246 hdd_context_t *hdd_ctx = NULL; 6247 hdd_adapter_t *adapter = NULL; 6248 void *cds_context = NULL; 6249 int i; 6250 6251 /* Get the global VOSS context.*/ 6252 cds_context = cds_get_global_context(); 6253 if (!cds_context) { 6254 hdd_err("Global CDS context is Null"); 6255 return; 6256 } 6257 /* Get the HDD context.*/ 6258 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD); 6259 6260 if (0 != wlan_hdd_validate_context(hdd_ctx)) 6261 return; 6262 6263 if (SME_SESSION_ID_ANY == frame_ind->sessionId) { 6264 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) { 6265 adapter = 6266 hdd_get_adapter_by_sme_session_id(hdd_ctx, i); 6267 if (adapter) 6268 break; 6269 } 6270 } else { 6271 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx, 6272 frame_ind->sessionId); 6273 } 6274 6275 if ((NULL != adapter) && 6276 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)) 6277 __hdd_indicate_mgmt_frame(adapter, 6278 frame_ind->frame_len, 6279 frame_ind->frameBuf, 6280 frame_ind->frameType, 6281 frame_ind->rxChan, 6282 frame_ind->rxRssi); 6283 return; 6284 } 6285 6286 /** 6287 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features 6288 * @hdd_ctx: HDD context 6289 * 6290 * Disables all the dual mac features like DBS, Agile DFS etc. 6291 * 6292 * Return: QDF_STATUS_SUCCESS on success 6293 */ 6294 static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx) 6295 { 6296 struct sir_dual_mac_config cfg; 6297 QDF_STATUS status; 6298 6299 if (!hdd_ctx) { 6300 hdd_err("HDD context is NULL"); 6301 return QDF_STATUS_E_FAILURE; 6302 } 6303 6304 cfg.scan_config = 0; 6305 cfg.fw_mode_config = 0; 6306 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb; 6307 6308 hdd_debug("Disabling all dual mac features..."); 6309 6310 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg); 6311 if (status != QDF_STATUS_SUCCESS) { 6312 hdd_err("sme_soc_set_dual_mac_config failed %d", status); 6313 return status; 6314 } 6315 6316 return QDF_STATUS_SUCCESS; 6317 } 6318 6319 /** 6320 * hdd_override_ini_config - Override INI config 6321 * @hdd_ctx: HDD context 6322 * 6323 * Override INI config based on module parameter. 6324 * 6325 * Return: None 6326 */ 6327 static void hdd_override_ini_config(hdd_context_t *hdd_ctx) 6328 { 6329 6330 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) { 6331 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan; 6332 hdd_notice("Module enable_dfs_chan_scan set to %d", 6333 enable_dfs_chan_scan); 6334 } 6335 if (0 == enable_11d || 1 == enable_11d) { 6336 hdd_ctx->config->Is11dSupportEnabled = enable_11d; 6337 hdd_notice("Module enable_11d set to %d", enable_11d); 6338 } 6339 6340 if (!hdd_ipa_is_present(hdd_ctx)) 6341 hdd_ctx->config->IpaConfig = 0; 6342 } 6343 6344 /** 6345 * hdd_set_trace_level_for_each - Set trace level for each INI config 6346 * @hdd_ctx - HDD context 6347 * 6348 * Set trace level for each module based on INI config. 6349 * 6350 * Return: None 6351 */ 6352 static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx) 6353 { 6354 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI, 6355 hdd_ctx->config->qdf_trace_enable_wdi); 6356 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD, 6357 hdd_ctx->config->qdf_trace_enable_hdd); 6358 hdd_qdf_trace_enable(QDF_MODULE_ID_SME, 6359 hdd_ctx->config->qdf_trace_enable_sme); 6360 hdd_qdf_trace_enable(QDF_MODULE_ID_PE, 6361 hdd_ctx->config->qdf_trace_enable_pe); 6362 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA, 6363 hdd_ctx->config->qdf_trace_enable_wma); 6364 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS, 6365 hdd_ctx->config->qdf_trace_enable_sys); 6366 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF, 6367 hdd_ctx->config->qdf_trace_enable_qdf); 6368 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP, 6369 hdd_ctx->config->qdf_trace_enable_sap); 6370 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP, 6371 hdd_ctx->config->qdf_trace_enable_hdd_sap); 6372 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI, 6373 hdd_ctx->config->qdf_trace_enable_bmi); 6374 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG, 6375 hdd_ctx->config->qdf_trace_enable_cfg); 6376 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING, 6377 hdd_ctx->config->qdf_trace_enable_epping); 6378 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE, 6379 hdd_ctx->config->qdf_trace_enable_qdf_devices); 6380 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX, 6381 hdd_ctx->config->cfd_trace_enable_txrx); 6382 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC, 6383 hdd_ctx->config->qdf_trace_enable_htc); 6384 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF, 6385 hdd_ctx->config->qdf_trace_enable_hif); 6386 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA, 6387 hdd_ctx->config->qdf_trace_enable_hdd_sap_data); 6388 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA, 6389 hdd_ctx->config->qdf_trace_enable_hdd_data); 6390 6391 hdd_cfg_print(hdd_ctx); 6392 } 6393 6394 /** 6395 * hdd_context_init() - Initialize HDD context 6396 * @hdd_ctx: HDD context. 6397 * 6398 * Initialize HDD context along with all the feature specific contexts. 6399 * 6400 * return: 0 on success and errno on failure. 6401 */ 6402 static int hdd_context_init(hdd_context_t *hdd_ctx) 6403 { 6404 int ret; 6405 6406 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; 6407 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX; 6408 6409 hdd_init_ll_stats_ctx(); 6410 6411 init_completion(&hdd_ctx->mc_sus_event_var); 6412 init_completion(&hdd_ctx->ready_to_suspend); 6413 6414 hdd_init_bpf_completion(); 6415 6416 qdf_spinlock_create(&hdd_ctx->connection_status_lock); 6417 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock); 6418 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock); 6419 6420 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS); 6421 6422 init_completion(&hdd_ctx->set_antenna_mode_cmpl); 6423 6424 ret = hdd_scan_context_init(hdd_ctx); 6425 if (ret) 6426 goto list_destroy; 6427 6428 hdd_tdls_context_init(hdd_ctx); 6429 6430 hdd_rx_wake_lock_create(hdd_ctx); 6431 6432 ret = hdd_sap_context_init(hdd_ctx); 6433 if (ret) 6434 goto scan_destroy; 6435 6436 ret = hdd_roc_context_init(hdd_ctx); 6437 if (ret) 6438 goto sap_destroy; 6439 6440 wlan_hdd_cfg80211_extscan_init(hdd_ctx); 6441 6442 hdd_init_offloaded_packets_ctx(hdd_ctx); 6443 6444 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy, 6445 hdd_ctx->config); 6446 if (ret) 6447 goto roc_destroy; 6448 6449 return 0; 6450 6451 roc_destroy: 6452 hdd_roc_context_destroy(hdd_ctx); 6453 6454 sap_destroy: 6455 hdd_sap_context_destroy(hdd_ctx); 6456 6457 scan_destroy: 6458 hdd_scan_context_destroy(hdd_ctx); 6459 hdd_rx_wake_lock_destroy(hdd_ctx); 6460 hdd_tdls_context_destroy(hdd_ctx); 6461 6462 list_destroy: 6463 qdf_list_destroy(&hdd_ctx->hddAdapters); 6464 return ret; 6465 } 6466 6467 /** 6468 * hdd_context_create() - Allocate and inialize HDD context. 6469 * @dev: Device Pointer to the underlying device 6470 * 6471 * Allocate and initialize HDD context. HDD context is allocated as part of 6472 * wiphy allocation and then context is initialized. 6473 * 6474 * Return: HDD context on success and ERR_PTR on failure 6475 */ 6476 static hdd_context_t *hdd_context_create(struct device *dev) 6477 { 6478 QDF_STATUS status; 6479 int ret = 0; 6480 hdd_context_t *hdd_ctx; 6481 v_CONTEXT_t p_cds_context; 6482 6483 ENTER(); 6484 6485 p_cds_context = cds_get_global_context(); 6486 if (p_cds_context == NULL) { 6487 hdd_alert("Failed to get CDS global context"); 6488 ret = -EINVAL; 6489 goto err_out; 6490 } 6491 6492 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)); 6493 6494 if (hdd_ctx == NULL) { 6495 ret = -ENOMEM; 6496 goto err_out; 6497 } 6498 6499 hdd_ctx->pcds_context = p_cds_context; 6500 hdd_ctx->parent_dev = dev; 6501 6502 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config)); 6503 if (hdd_ctx->config == NULL) { 6504 hdd_alert("Failed to alloc memory for HDD config!"); 6505 ret = -ENOMEM; 6506 goto err_free_hdd_context; 6507 } 6508 6509 /* Read and parse the qcom_cfg.ini file */ 6510 status = hdd_parse_config_ini(hdd_ctx); 6511 if (QDF_STATUS_SUCCESS != status) { 6512 hdd_err("Error (status: %d) parsing INI file: %s", status, 6513 WLAN_INI_FILE); 6514 ret = -EINVAL; 6515 goto err_free_config; 6516 } 6517 6518 hdd_ctx->configuredMcastBcastFilter = 6519 hdd_ctx->config->mcastBcastFilterSetting; 6520 6521 hdd_notice("Setting configuredMcastBcastFilter: %d", 6522 hdd_ctx->config->mcastBcastFilterSetting); 6523 6524 if (hdd_ctx->config->fhostNSOffload) 6525 hdd_ctx->ns_offload_enable = true; 6526 6527 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event); 6528 6529 hdd_override_ini_config(hdd_ctx); 6530 6531 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx; 6532 6533 ret = hdd_context_init(hdd_ctx); 6534 6535 if (ret) 6536 goto err_free_config; 6537 6538 6539 pld_set_fw_debug_mode(hdd_ctx->parent_dev, 6540 hdd_ctx->config->enable_fw_log); 6541 6542 6543 /* Uses to enabled logging after SSR */ 6544 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log; 6545 6546 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) 6547 goto skip_multicast_logging; 6548 6549 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs); 6550 6551 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx); 6552 if (ret) 6553 goto err_deinit_hdd_context; 6554 6555 ret = hdd_logging_sock_activate_svc(hdd_ctx); 6556 if (ret) 6557 goto err_free_histogram; 6558 6559 6560 /* 6561 * Update QDF trace levels based upon the code. The multicast 6562 * levels of the code need not be set when the logger thread 6563 * is not enabled. 6564 */ 6565 if (cds_is_multicast_logging()) 6566 wlan_logging_set_log_level(); 6567 6568 skip_multicast_logging: 6569 hdd_set_trace_level_for_each(hdd_ctx); 6570 6571 return hdd_ctx; 6572 6573 err_free_histogram: 6574 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx); 6575 6576 err_deinit_hdd_context: 6577 hdd_context_deinit(hdd_ctx); 6578 6579 err_free_config: 6580 qdf_mem_free(hdd_ctx->config); 6581 6582 err_free_hdd_context: 6583 wiphy_free(hdd_ctx->wiphy); 6584 6585 err_out: 6586 return ERR_PTR(ret); 6587 } 6588 6589 #ifdef WLAN_OPEN_P2P_INTERFACE 6590 /** 6591 * hdd_open_p2p_interface - Open P2P interface 6592 * @hdd_ctx: HDD context 6593 * @rtnl_held: True if RTNL lock held 6594 * 6595 * Open P2P interface during probe. This function called to open the P2P 6596 * interface at probe along with STA interface. 6597 * 6598 * Return: 0 on success and errno on failure 6599 */ 6600 static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held) 6601 { 6602 hdd_adapter_t *adapter; 6603 uint8_t *p2p_dev_addr; 6604 6605 if (hdd_ctx->config->isP2pDeviceAddrAdministrated && 6606 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) { 6607 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes, 6608 hdd_ctx->config->intfMacAddr[0].bytes, 6609 sizeof(tSirMacAddr)); 6610 6611 /* 6612 * Generate the P2P Device Address. This consists of 6613 * the device's primary MAC address with the locally 6614 * administered bit set. 6615 */ 6616 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02; 6617 } else { 6618 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx); 6619 if (p2p_dev_addr == NULL) { 6620 hdd_alert("Failed to allocate mac_address for p2p_device"); 6621 return -ENOSPC; 6622 } 6623 6624 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr, 6625 QDF_MAC_ADDR_SIZE); 6626 } 6627 6628 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d", 6629 &hdd_ctx->p2pDeviceAddress.bytes[0], 6630 NET_NAME_UNKNOWN, rtnl_held); 6631 6632 if (NULL == adapter) { 6633 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface"); 6634 return -ENOSPC; 6635 } 6636 6637 return 0; 6638 } 6639 #else 6640 static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, 6641 bool rtnl_held) 6642 { 6643 return 0; 6644 } 6645 #endif 6646 6647 /** 6648 * hdd_start_station_adapter()- Start the Station Adapter 6649 * @adapter: HDD adapter 6650 * 6651 * This function initializes the adapter for the station mode. 6652 * 6653 * Return: 0 on success or errno on failure. 6654 */ 6655 int hdd_start_station_adapter(hdd_adapter_t *adapter) 6656 { 6657 QDF_STATUS status; 6658 6659 ENTER_DEV(adapter->dev); 6660 6661 status = hdd_init_station_mode(adapter); 6662 6663 if (QDF_STATUS_SUCCESS != status) { 6664 hdd_err("Error Initializing station mode: %d", status); 6665 return qdf_status_to_os_return(status); 6666 } 6667 6668 hdd_register_tx_flow_control(adapter, 6669 hdd_tx_resume_timer_expired_handler, 6670 hdd_tx_resume_cb); 6671 6672 EXIT(); 6673 return 0; 6674 } 6675 6676 /** 6677 * hdd_start_ap_adapter()- Start AP Adapter 6678 * @adapter: HDD adapter 6679 * 6680 * This function initializes the adapter for the AP mode. 6681 * 6682 * Return: 0 on success errno on failure. 6683 */ 6684 int hdd_start_ap_adapter(hdd_adapter_t *adapter) 6685 { 6686 QDF_STATUS status; 6687 6688 ENTER(); 6689 6690 status = hdd_init_ap_mode(adapter); 6691 6692 if (QDF_STATUS_SUCCESS != status) { 6693 hdd_err("Error Initializing the AP mode: %d", status); 6694 return qdf_status_to_os_return(status); 6695 } 6696 6697 hdd_register_tx_flow_control(adapter, 6698 hdd_softap_tx_resume_timer_expired_handler, 6699 hdd_softap_tx_resume_cb); 6700 6701 EXIT(); 6702 return 0; 6703 } 6704 6705 /** 6706 * hdd_start_ftm_adapter()- Start FTM adapter 6707 * @adapter: HDD adapter 6708 * 6709 * This function initializes the adapter for the FTM mode. 6710 * 6711 * Return: 0 on success or errno on failure. 6712 */ 6713 int hdd_start_ftm_adapter(hdd_adapter_t *adapter) 6714 { 6715 QDF_STATUS qdf_status; 6716 6717 ENTER_DEV(adapter->dev); 6718 6719 qdf_status = hdd_init_tx_rx(adapter); 6720 6721 if (QDF_STATUS_SUCCESS != qdf_status) { 6722 hdd_err("Failed to start FTM adapter: %d", qdf_status); 6723 return qdf_status_to_os_return(qdf_status); 6724 } 6725 6726 return 0; 6727 EXIT(); 6728 } 6729 6730 /** 6731 * hdd_open_interfaces - Open all required interfaces 6732 * hdd_ctx: HDD context 6733 * rtnl_held: True if RTNL lock is held 6734 * 6735 * Open all the interfaces like STA, P2P and OCB based on the configuration. 6736 * 6737 * Return: Primary adapter on success and PTR_ERR on failure 6738 */ 6739 static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx, 6740 bool rtnl_held) 6741 { 6742 hdd_adapter_t *adapter = NULL; 6743 hdd_adapter_t *adapter_11p = NULL; 6744 int ret; 6745 6746 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) { 6747 /* Create only 802.11p interface */ 6748 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d", 6749 wlan_hdd_get_intf_addr(hdd_ctx), 6750 NET_NAME_UNKNOWN, rtnl_held); 6751 6752 if (adapter == NULL) 6753 return ERR_PTR(-ENOSPC); 6754 6755 return adapter; 6756 } 6757 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d", 6758 wlan_hdd_get_intf_addr(hdd_ctx), 6759 NET_NAME_UNKNOWN, rtnl_held); 6760 6761 if (adapter == NULL) 6762 return ERR_PTR(-ENOSPC); 6763 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held); 6764 if (ret) 6765 goto err_close_adapter; 6766 6767 /* Open 802.11p Interface */ 6768 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) { 6769 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, 6770 "wlanocb%d", 6771 wlan_hdd_get_intf_addr(hdd_ctx), 6772 NET_NAME_UNKNOWN, rtnl_held); 6773 if (adapter_11p == NULL) { 6774 hdd_err("Failed to open 802.11p interface"); 6775 goto err_close_adapter; 6776 } 6777 } 6778 6779 return adapter; 6780 6781 err_close_adapter: 6782 hdd_close_all_adapters(hdd_ctx, rtnl_held); 6783 return ERR_PTR(ret); 6784 } 6785 6786 /** 6787 * hdd_update_country_code - Update country code 6788 * @hdd_ctx: HDD context 6789 * @adapter: Primary adapter context 6790 * 6791 * Update country code based on module parameter country_code at SME and wait 6792 * for the settings to take effect. 6793 * 6794 * Return: 0 on success and errno on failure 6795 */ 6796 static int hdd_update_country_code(hdd_context_t *hdd_ctx, 6797 hdd_adapter_t *adapter) 6798 { 6799 QDF_STATUS status; 6800 int ret = 0; 6801 unsigned long rc; 6802 6803 if (country_code == NULL) 6804 return 0; 6805 6806 INIT_COMPLETION(adapter->change_country_code); 6807 6808 status = sme_change_country_code(hdd_ctx->hHal, 6809 wlan_hdd_change_country_code_callback, 6810 country_code, adapter, 6811 hdd_ctx->pcds_context, eSIR_TRUE, 6812 eSIR_TRUE); 6813 6814 6815 if (!QDF_IS_STATUS_SUCCESS(status)) { 6816 hdd_err("SME Change Country code from module param fail ret=%d", 6817 ret); 6818 return -EINVAL; 6819 } 6820 6821 rc = wait_for_completion_timeout(&adapter->change_country_code, 6822 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY)); 6823 if (!rc) { 6824 hdd_err("SME while setting country code timed out"); 6825 ret = -ETIMEDOUT; 6826 } 6827 6828 return ret; 6829 } 6830 6831 #ifdef QCA_LL_TX_FLOW_CONTROL_V2 6832 /** 6833 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration 6834 * @cds_cfg: CDS Configuration 6835 * @hdd_ctx: Pointer to hdd context 6836 * 6837 * Return: none 6838 */ 6839 static inline void hdd_txrx_populate_cds_config(struct cds_config_info 6840 *cds_cfg, 6841 hdd_context_t *hdd_ctx) 6842 { 6843 cds_cfg->tx_flow_stop_queue_th = 6844 hdd_ctx->config->TxFlowStopQueueThreshold; 6845 cds_cfg->tx_flow_start_queue_offset = 6846 hdd_ctx->config->TxFlowStartQueueOffset; 6847 } 6848 #else 6849 static inline void hdd_txrx_populate_cds_config(struct cds_config_info 6850 *cds_cfg, 6851 hdd_context_t *hdd_ctx) 6852 { 6853 } 6854 #endif 6855 6856 #ifdef FEATURE_WLAN_RA_FILTERING 6857 /** 6858 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration 6859 * @cds_cfg: CDS Configuration 6860 * @hdd_ctx: Pointer to hdd context 6861 * 6862 * Return: none 6863 */ 6864 inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg, 6865 hdd_context_t *hdd_ctx) 6866 { 6867 cds_cfg->ra_ratelimit_interval = 6868 hdd_ctx->config->RArateLimitInterval; 6869 cds_cfg->is_ra_ratelimit_enabled = 6870 hdd_ctx->config->IsRArateLimitEnabled; 6871 } 6872 #else 6873 inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg, 6874 hdd_context_t *hdd_ctx) 6875 { 6876 } 6877 #endif 6878 6879 /** 6880 * hdd_update_cds_config() - API to update cds configuration parameters 6881 * @hdd_ctx: HDD Context 6882 * 6883 * Return: 0 for Success, errno on failure 6884 */ 6885 static int hdd_update_cds_config(hdd_context_t *hdd_ctx) 6886 { 6887 struct cds_config_info *cds_cfg; 6888 6889 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg)); 6890 if (!cds_cfg) { 6891 hdd_err("failed to allocate cds config"); 6892 return -ENOMEM; 6893 } 6894 6895 /* UMA is supported in hardware for performing the 6896 * frame translation 802.11 <-> 802.3 6897 */ 6898 cds_cfg->frame_xln_reqd = 1; 6899 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION; 6900 cds_cfg->powersave_offload_enabled = 6901 hdd_ctx->config->enablePowersaveOffload; 6902 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM; 6903 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM; 6904 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM; 6905 cds_cfg->wow_enable = hdd_ctx->config->wowEnable; 6906 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters; 6907 6908 /* Here ol_ini_info is used to store ini status of arp offload 6909 * ns offload and others. Currently 1st bit is used for arp 6910 * off load and 2nd bit for ns offload currently, rest bits are unused 6911 */ 6912 if (hdd_ctx->config->fhostArpOffload) 6913 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1; 6914 if (hdd_ctx->config->fhostNSOffload) 6915 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2; 6916 6917 /* 6918 * Copy the DFS Phyerr Filtering Offload status. 6919 * This parameter reflects the value of the 6920 * dfs_phyerr_filter_offload flag as set in the ini. 6921 */ 6922 cds_cfg->dfs_phyerr_filter_offload = 6923 hdd_ctx->config->fDfsPhyerrFilterOffload; 6924 if (hdd_ctx->config->ssdp) 6925 cds_cfg->ssdp = hdd_ctx->config->ssdp; 6926 6927 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList; 6928 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers; 6929 6930 cds_cfg->ap_maxoffload_reorderbuffs = 6931 hdd_ctx->config->apMaxOffloadReorderBuffs; 6932 6933 cds_cfg->ap_disable_intrabss_fwd = 6934 hdd_ctx->config->apDisableIntraBssFwd; 6935 6936 cds_cfg->dfs_pri_multiplier = 6937 hdd_ctx->config->dfsRadarPriMultiplier; 6938 cds_cfg->reorder_offload = 6939 hdd_ctx->config->reorderOffloadSupport; 6940 6941 /* IPA micro controller data path offload resource config item */ 6942 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx); 6943 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount; 6944 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize; 6945 cds_cfg->uc_rxind_ringcount = 6946 hdd_ctx->config->IpaUcRxIndRingCount; 6947 cds_cfg->uc_tx_partition_base = 6948 hdd_ctx->config->IpaUcTxPartitionBase; 6949 cds_cfg->max_scan = hdd_ctx->config->max_scan_count; 6950 6951 cds_cfg->ip_tcp_udp_checksum_offload = 6952 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload; 6953 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread; 6954 cds_cfg->ce_classify_enabled = 6955 hdd_ctx->config->ce_classify_enabled; 6956 cds_cfg->bpf_packet_filter_enable = 6957 hdd_ctx->config->bpf_packet_filter_enable; 6958 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck; 6959 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr; 6960 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers; 6961 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE; 6962 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable; 6963 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery; 6964 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash; 6965 6966 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx); 6967 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx); 6968 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx); 6969 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx); 6970 cds_init_ini_config(cds_cfg); 6971 return 0; 6972 } 6973 6974 /** 6975 * hdd_init_thermal_info - Initialize thermal level 6976 * @hdd_ctx: HDD context 6977 * 6978 * Initialize thermal level at SME layer and set the thermal level callback 6979 * which would be called when a configured thermal threshold is hit. 6980 * 6981 * Return: 0 on success and errno on failure 6982 */ 6983 static int hdd_init_thermal_info(hdd_context_t *hdd_ctx) 6984 { 6985 tSmeThermalParams thermal_param; 6986 QDF_STATUS status; 6987 6988 thermal_param.smeThermalMgmtEnabled = 6989 hdd_ctx->config->thermalMitigationEnable; 6990 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod; 6991 6992 thermal_param.sme_throttle_duty_cycle_tbl[0] = 6993 hdd_ctx->config->throttle_dutycycle_level0; 6994 thermal_param.sme_throttle_duty_cycle_tbl[1] = 6995 hdd_ctx->config->throttle_dutycycle_level1; 6996 thermal_param.sme_throttle_duty_cycle_tbl[2] = 6997 hdd_ctx->config->throttle_dutycycle_level2; 6998 thermal_param.sme_throttle_duty_cycle_tbl[3] = 6999 hdd_ctx->config->throttle_dutycycle_level3; 7000 7001 thermal_param.smeThermalLevels[0].smeMinTempThreshold = 7002 hdd_ctx->config->thermalTempMinLevel0; 7003 thermal_param.smeThermalLevels[0].smeMaxTempThreshold = 7004 hdd_ctx->config->thermalTempMaxLevel0; 7005 thermal_param.smeThermalLevels[1].smeMinTempThreshold = 7006 hdd_ctx->config->thermalTempMinLevel1; 7007 thermal_param.smeThermalLevels[1].smeMaxTempThreshold = 7008 hdd_ctx->config->thermalTempMaxLevel1; 7009 thermal_param.smeThermalLevels[2].smeMinTempThreshold = 7010 hdd_ctx->config->thermalTempMinLevel2; 7011 thermal_param.smeThermalLevels[2].smeMaxTempThreshold = 7012 hdd_ctx->config->thermalTempMaxLevel2; 7013 thermal_param.smeThermalLevels[3].smeMinTempThreshold = 7014 hdd_ctx->config->thermalTempMinLevel3; 7015 thermal_param.smeThermalLevels[3].smeMaxTempThreshold = 7016 hdd_ctx->config->thermalTempMaxLevel3; 7017 7018 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param); 7019 7020 if (!QDF_IS_STATUS_SUCCESS(status)) 7021 return qdf_status_to_os_return(status); 7022 7023 sme_add_set_thermal_level_callback(hdd_ctx->hHal, 7024 hdd_set_thermal_level_cb); 7025 7026 return 0; 7027 7028 } 7029 7030 #if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK) 7031 /** 7032 * hdd_hold_rtnl_lock - Hold RTNL lock 7033 * 7034 * Hold RTNL lock 7035 * 7036 * Return: True if held and false otherwise 7037 */ 7038 static inline bool hdd_hold_rtnl_lock(void) 7039 { 7040 rtnl_lock(); 7041 return true; 7042 } 7043 7044 /** 7045 * hdd_release_rtnl_lock - Release RTNL lock 7046 * 7047 * Release RTNL lock 7048 * 7049 * Return: None 7050 */ 7051 static inline void hdd_release_rtnl_lock(void) 7052 { 7053 rtnl_unlock(); 7054 } 7055 #else 7056 static inline bool hdd_hold_rtnl_lock(void) { return false; } 7057 static inline void hdd_release_rtnl_lock(void) { } 7058 #endif 7059 7060 #if !defined(REMOVE_PKT_LOG) 7061 7062 /* MAX iwpriv command support */ 7063 #define PKTLOG_SET_BUFF_SIZE 3 7064 #define MAX_PKTLOG_SIZE 16 7065 7066 /** 7067 * hdd_pktlog_set_buff_size() - set pktlog buffer size 7068 * @hdd_ctx: hdd context 7069 * @set_value2: pktlog buffer size value 7070 * 7071 * 7072 * Return: 0 for success or error. 7073 */ 7074 static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2) 7075 { 7076 struct sir_wifi_start_log start_log = { 0 }; 7077 QDF_STATUS status; 7078 7079 start_log.ring_id = RING_ID_PER_PACKET_STATS; 7080 start_log.verbose_level = WLAN_LOG_LEVEL_OFF; 7081 start_log.ini_triggered = cds_is_packet_log_enabled(); 7082 start_log.user_triggered = 1; 7083 start_log.size = set_value2; 7084 7085 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log); 7086 if (!QDF_IS_STATUS_SUCCESS(status)) { 7087 hdd_err("sme_wifi_start_logger failed(err=%d)", status); 7088 EXIT(); 7089 return -EINVAL; 7090 } 7091 7092 return 0; 7093 } 7094 7095 /** 7096 * hdd_process_pktlog_command() - process pktlog command 7097 * @hdd_ctx: hdd context 7098 * @set_value: value set by user 7099 * @set_value2: pktlog buffer size value 7100 * 7101 * This function process pktlog command. 7102 * set_value2 only matters when set_value is 3 (set buff size) 7103 * otherwise we ignore it. 7104 * 7105 * Return: 0 for success or error. 7106 */ 7107 int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value, 7108 int set_value2) 7109 { 7110 int ret; 7111 bool enable; 7112 uint8_t user_triggered = 0; 7113 7114 ret = wlan_hdd_validate_context(hdd_ctx); 7115 if (0 != ret) 7116 return ret; 7117 7118 hdd_info("set pktlog %d, set size %d", set_value, set_value2); 7119 7120 if (set_value > PKTLOG_SET_BUFF_SIZE) { 7121 hdd_err("invalid pktlog value %d", set_value); 7122 return -EINVAL; 7123 } 7124 7125 if (set_value == PKTLOG_SET_BUFF_SIZE) { 7126 if (set_value2 <= 0) { 7127 hdd_err("invalid pktlog size %d", set_value2); 7128 return -EINVAL; 7129 } else if (set_value2 > MAX_PKTLOG_SIZE) { 7130 hdd_err("Pktlog buff size is too large. max value is 16MB.\n"); 7131 return -EINVAL; 7132 } 7133 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2); 7134 } 7135 7136 /* 7137 * set_value = 0 then disable packetlog 7138 * set_value = 1 enable packetlog forcefully 7139 * set_vlaue = 2 then disable packetlog if disabled through ini or 7140 * enable packetlog with AUTO type. 7141 */ 7142 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ? 7143 true : false; 7144 7145 if (1 == set_value) { 7146 enable = true; 7147 user_triggered = 1; 7148 } 7149 7150 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0); 7151 } 7152 /** 7153 * hdd_pktlog_enable_disable() - Enable/Disable packet logging 7154 * @hdd_ctx: HDD context 7155 * @enable: Flag to enable/disable 7156 * @user_triggered: triggered through iwpriv 7157 * @size: buffer size to be used for packetlog 7158 * 7159 * Return: 0 on success; error number otherwise 7160 */ 7161 int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable, 7162 uint8_t user_triggered, int size) 7163 { 7164 struct sir_wifi_start_log start_log; 7165 QDF_STATUS status; 7166 7167 start_log.ring_id = RING_ID_PER_PACKET_STATS; 7168 start_log.verbose_level = 7169 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF; 7170 start_log.ini_triggered = cds_is_packet_log_enabled(); 7171 start_log.user_triggered = user_triggered; 7172 start_log.size = size; 7173 /* 7174 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other 7175 * commands. Host uses this flag to decide whether to send pktlog 7176 * disable command to fw without sending pktlog enable command 7177 * previously. For eg, If vendor sends pktlog disable command without 7178 * sending pktlog enable command, then host discards the packet 7179 * but for iwpriv command, host will send it to fw. 7180 */ 7181 start_log.is_iwpriv_command = 1; 7182 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log); 7183 if (!QDF_IS_STATUS_SUCCESS(status)) { 7184 hdd_err("sme_wifi_start_logger failed(err=%d)", status); 7185 EXIT(); 7186 return -EINVAL; 7187 } 7188 7189 return 0; 7190 } 7191 #endif /* REMOVE_PKT_LOG */ 7192 7193 7194 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH 7195 /** 7196 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel 7197 * switch without restart 7198 * 7199 * Registers callback function to change the operating channel of SAP by using 7200 * channel switch announcements instead of restarting SAP. 7201 * 7202 * Return: QDF_STATUS 7203 */ 7204 QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void) 7205 { 7206 QDF_STATUS status; 7207 7208 status = cds_register_sap_restart_channel_switch_cb( 7209 (void *)hdd_sap_restart_with_channel_switch); 7210 if (!QDF_IS_STATUS_SUCCESS(status)) 7211 hdd_err("restart cb registration failed"); 7212 7213 return status; 7214 } 7215 #endif 7216 7217 /** 7218 * hdd_get_platform_wlan_mac_buff() - API to query platform driver 7219 * for MAC address 7220 * @dev: Device Pointer 7221 * @num: Number of Valid Mac address 7222 * 7223 * Return: Pointer to MAC address buffer 7224 */ 7225 static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev, 7226 uint32_t *num) 7227 { 7228 return pld_get_wlan_mac_address(dev, num); 7229 } 7230 7231 /** 7232 * hdd_populate_random_mac_addr() - API to populate random mac addresses 7233 * @hdd_ctx: HDD Context 7234 * @num: Number of random mac addresses needed 7235 * 7236 * Generate random addresses using bit manipulation on the base mac address 7237 * 7238 * Return: None 7239 */ 7240 static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num) 7241 { 7242 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num; 7243 uint32_t iter; 7244 struct hdd_config *ini = hdd_ctx->config; 7245 uint8_t *buf = NULL; 7246 uint8_t macaddr_b3, tmp_br3; 7247 uint8_t *src = ini->intfMacAddr[0].bytes; 7248 7249 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) { 7250 buf = ini->intfMacAddr[iter].bytes; 7251 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE); 7252 macaddr_b3 = buf[3]; 7253 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) & 7254 INTF_MACADDR_MASK; 7255 macaddr_b3 += tmp_br3; 7256 macaddr_b3 ^= (1 << INTF_MACADDR_MASK); 7257 buf[0] |= 0x02; 7258 buf[3] = macaddr_b3; 7259 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf)); 7260 } 7261 } 7262 7263 /** 7264 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver 7265 * @hdd_ctx: HDD Context 7266 * 7267 * API to get mac addresses from platform driver and update the driver 7268 * structures and configure FW with the base mac address. 7269 * Return: int 7270 */ 7271 static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx) 7272 { 7273 uint32_t no_of_mac_addr, iter; 7274 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA; 7275 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE; 7276 uint8_t *addr, *buf; 7277 struct device *dev = hdd_ctx->parent_dev; 7278 struct hdd_config *ini = hdd_ctx->config; 7279 tSirMacAddr mac_addr; 7280 QDF_STATUS status; 7281 7282 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr); 7283 7284 if (no_of_mac_addr == 0 || !addr) { 7285 hdd_warn("Platform Driver Doesn't have wlan mac addresses"); 7286 return -EINVAL; 7287 } 7288 7289 if (no_of_mac_addr > max_mac_addr) 7290 no_of_mac_addr = max_mac_addr; 7291 7292 qdf_mem_copy(&mac_addr, addr, mac_addr_size); 7293 7294 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) { 7295 buf = ini->intfMacAddr[iter].bytes; 7296 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE); 7297 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf)); 7298 } 7299 7300 status = sme_set_custom_mac_addr(mac_addr); 7301 7302 if (!QDF_IS_STATUS_SUCCESS(status)) 7303 return -EAGAIN; 7304 if (no_of_mac_addr < max_mac_addr) 7305 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr - 7306 no_of_mac_addr); 7307 return 0; 7308 } 7309 7310 /** 7311 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW 7312 * @hdd_ctx: HDD Context 7313 * 7314 * Update MAC address to FW. If MAC address passed by FW is invalid, host 7315 * will generate its own MAC and update it to FW. 7316 * 7317 * Return: 0 for success 7318 * Non-zero error code for failure 7319 */ 7320 static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx) 7321 { 7322 tSirMacAddr customMacAddr; 7323 QDF_STATUS status; 7324 7325 qdf_mem_copy(&customMacAddr, 7326 &hdd_ctx->config->intfMacAddr[0].bytes[0], 7327 sizeof(tSirMacAddr)); 7328 status = sme_set_custom_mac_addr(customMacAddr); 7329 if (!QDF_IS_STATUS_SUCCESS(status)) 7330 return -EAGAIN; 7331 return 0; 7332 } 7333 7334 /** 7335 * hdd_initialize_mac_address() - API to get wlan mac addresses 7336 * @hdd_ctx: HDD Context 7337 * 7338 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver 7339 * is provisioned with mac addresses, driver uses it, else it will use 7340 * wlan_mac.bin to update HW MAC addresses. 7341 * 7342 * Return: None 7343 */ 7344 static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx) 7345 { 7346 QDF_STATUS status; 7347 int ret; 7348 7349 ret = hdd_platform_wlan_mac(hdd_ctx); 7350 if (ret == 0) 7351 return; 7352 7353 hdd_warn("Can't update mac config via platform driver ret:%d", ret); 7354 7355 status = hdd_update_mac_config(hdd_ctx); 7356 7357 if (QDF_IS_STATUS_SUCCESS(status)) 7358 return; 7359 7360 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen"); 7361 7362 if (hdd_ctx->update_mac_addr_to_fw) { 7363 ret = hdd_update_mac_addr_to_fw(hdd_ctx); 7364 if (ret != 0) { 7365 hdd_err("MAC address out-of-sync, ret:%d", ret); 7366 QDF_ASSERT(ret); 7367 } 7368 } 7369 } 7370 7371 /** 7372 * hdd_tsf_init() - Initialize the TSF synchronization interface 7373 * @hdd_ctx: HDD global context 7374 * 7375 * When TSF synchronization via GPIO is supported by the driver and 7376 * has been enabled in the configuration file, this function plumbs 7377 * the GPIO value down to firmware via SME. 7378 * 7379 * Return: None 7380 */ 7381 #ifdef WLAN_FEATURE_TSF 7382 static void hdd_tsf_init(hdd_context_t *hdd_ctx) 7383 { 7384 QDF_STATUS status; 7385 7386 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID) 7387 return; 7388 7389 status = sme_set_tsf_gpio(hdd_ctx->hHal, 7390 hdd_ctx->config->tsf_gpio_pin); 7391 if (!QDF_IS_STATUS_SUCCESS(status)) 7392 hdd_err("Set tsf GPIO failed, status: %d", status); 7393 } 7394 #else 7395 static void hdd_tsf_init(hdd_context_t *hdd_ctx) 7396 { 7397 } 7398 #endif 7399 7400 /** 7401 * hdd_pre_enable_configure() - Configurations prior to cds_enable 7402 * @hdd_ctx: HDD context 7403 * 7404 * Pre configurations to be done at lower layer before calling cds enable. 7405 * 7406 * Return: 0 on success and errno on failure. 7407 */ 7408 static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx) 7409 { 7410 int ret; 7411 QDF_STATUS status; 7412 tSirRetStatus hal_status; 7413 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 7414 7415 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb); 7416 /* 7417 * Set 802.11p config 7418 * TODO-OCB: This has been temporarily added here to ensure this 7419 * parameter is set in CSR when we init the channel list. This should 7420 * be removed once the 5.9 GHz channels are added to the regulatory 7421 * domain. 7422 */ 7423 hdd_set_dot11p_config(hdd_ctx); 7424 7425 /* 7426 * Note that the cds_pre_enable() sequence triggers the cfg download. 7427 * The cfg download must occur before we update the SME config 7428 * since the SME config operation must access the cfg database 7429 */ 7430 status = hdd_set_sme_config(hdd_ctx); 7431 7432 if (QDF_STATUS_SUCCESS != status) { 7433 hdd_alert("Failed hdd_set_sme_config: %d", status); 7434 ret = qdf_status_to_os_return(status); 7435 goto out; 7436 } 7437 7438 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS, 7439 hdd_ctx->config->tx_chain_mask_1ss, 7440 PDEV_CMD); 7441 if (0 != ret) { 7442 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret); 7443 goto out; 7444 } 7445 7446 hdd_program_country_code(hdd_ctx); 7447 7448 status = hdd_set_sme_chan_list(hdd_ctx); 7449 if (status != QDF_STATUS_SUCCESS) { 7450 hdd_alert("Failed to init channel list: %d", status); 7451 ret = qdf_status_to_os_return(status); 7452 goto out; 7453 } 7454 7455 /* Apply the cfg.ini to cfg.dat */ 7456 if (!hdd_update_config_cfg(hdd_ctx)) { 7457 hdd_alert("config update failed"); 7458 ret = -EINVAL; 7459 goto out; 7460 } 7461 7462 /* 7463 * Set the MAC Address Currently this is used by HAL to add self sta. 7464 * Remove this once self sta is added as part of session open. 7465 */ 7466 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID, 7467 hdd_ctx->config->intfMacAddr[0].bytes, 7468 sizeof(hdd_ctx->config->intfMacAddr[0])); 7469 7470 if (!IS_SIR_STATUS_SUCCESS(hal_status)) { 7471 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]", 7472 hal_status, hal_status); 7473 ret = -EINVAL; 7474 goto out; 7475 } 7476 7477 hdd_init_channel_avoidance(hdd_ctx); 7478 7479 out: 7480 return ret; 7481 } 7482 7483 /** 7484 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler 7485 * @context_ptr - hdd context pointer 7486 * @event_ptr - event structure pointer 7487 * 7488 * This is the p2p listen offload stop event handler, it sends vendor 7489 * event back to supplicant to notify the stop reason. 7490 * 7491 * Return: None 7492 */ 7493 static void wlan_hdd_p2p_lo_event_callback(void *context_ptr, 7494 void *event_ptr) 7495 { 7496 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr; 7497 struct sir_p2p_lo_event *evt = event_ptr; 7498 struct sk_buff *vendor_event; 7499 7500 ENTER(); 7501 7502 if (hdd_ctx == NULL) { 7503 hdd_err("Invalid HDD context pointer"); 7504 return; 7505 } 7506 7507 vendor_event = 7508 cfg80211_vendor_event_alloc(hdd_ctx->wiphy, 7509 NULL, sizeof(uint32_t) + NLMSG_HDRLEN, 7510 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX, 7511 GFP_KERNEL); 7512 7513 if (!vendor_event) { 7514 hdd_err("cfg80211_vendor_event_alloc failed"); 7515 return; 7516 } 7517 7518 if (nla_put_u32(vendor_event, 7519 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON, 7520 evt->reason_code)) { 7521 hdd_err("nla put failed"); 7522 kfree_skb(vendor_event); 7523 return; 7524 } 7525 7526 cfg80211_vendor_event(vendor_event, GFP_KERNEL); 7527 } 7528 7529 /** 7530 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config 7531 * @hdd_ctx: HDD context 7532 * 7533 * This function sends the adaptive dwell time config configuration to the 7534 * firmware via WMA 7535 * 7536 * Return: 0 - success, < 0 - failure 7537 */ 7538 static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx) 7539 { 7540 QDF_STATUS status; 7541 struct adaptive_dwelltime_params dwelltime_params; 7542 7543 dwelltime_params.is_enabled = 7544 hdd_ctx->config->adaptive_dwell_mode_enabled; 7545 dwelltime_params.dwelltime_mode = 7546 hdd_ctx->config->global_adapt_dwelltime_mode; 7547 dwelltime_params.lpf_weight = 7548 hdd_ctx->config->adapt_dwell_lpf_weight; 7549 dwelltime_params.passive_mon_intval = 7550 hdd_ctx->config->adapt_dwell_passive_mon_intval; 7551 dwelltime_params.wifi_act_threshold = 7552 hdd_ctx->config->adapt_dwell_wifi_act_threshold; 7553 7554 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal, 7555 &dwelltime_params); 7556 7557 hdd_debug("Sending Adaptive Dwelltime Configuration to fw"); 7558 if (!QDF_IS_STATUS_SUCCESS(status)) { 7559 hdd_err("Failed to send Adaptive Dwelltime configuration!"); 7560 return -EAGAIN; 7561 } 7562 return 0; 7563 } 7564 7565 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN 7566 /** 7567 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback 7568 * @hdd_ctx: HDD context 7569 * 7570 * Set auto shutdown callback to get indications from firmware to indicate 7571 * userspace to shutdown WLAN after a configured amount of inactivity. 7572 * 7573 * Return: 0 on success and errno on failure. 7574 */ 7575 static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx) 7576 { 7577 QDF_STATUS status; 7578 7579 if (!hdd_ctx->config->WlanAutoShutdown) 7580 return 0; 7581 7582 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal, 7583 wlan_hdd_auto_shutdown_cb); 7584 if (status != QDF_STATUS_SUCCESS) 7585 hdd_err("Auto shutdown feature could not be enabled: %d", 7586 status); 7587 7588 return qdf_status_to_os_return(status); 7589 } 7590 #else 7591 static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx) 7592 { 7593 return 0; 7594 } 7595 #endif 7596 7597 /** 7598 * hdd_features_init() - Init features 7599 * @hdd_ctx: HDD context 7600 * @adapter: Primary adapter context 7601 * 7602 * Initialize features and their feature context after WLAN firmware is up. 7603 * 7604 * Return: 0 on success and errno on failure. 7605 */ 7606 static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) 7607 { 7608 tSirTxPowerLimit hddtxlimit; 7609 QDF_STATUS status; 7610 int ret; 7611 7612 ENTER(); 7613 7614 ret = hdd_update_country_code(hdd_ctx, adapter); 7615 if (ret) { 7616 hdd_err("Failed to update country code: %d", ret); 7617 goto out; 7618 } 7619 7620 /* FW capabilities received, Set the Dot11 mode */ 7621 sme_setdef_dot11mode(hdd_ctx->hHal); 7622 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal, 7623 hdd_ctx->config->sta_prefer_80MHz_over_160MHz); 7624 7625 7626 if (hdd_ctx->config->fIsImpsEnabled) 7627 hdd_set_idle_ps_config(hdd_ctx, true); 7628 else 7629 hdd_set_idle_ps_config(hdd_ctx, false); 7630 7631 if (hdd_lro_init(hdd_ctx)) 7632 hdd_err("Unable to initialize LRO in fw"); 7633 7634 if (hdd_adaptive_dwelltime_init(hdd_ctx)) 7635 hdd_err("Unable to send adaptive dwelltime setting to FW"); 7636 7637 ret = hdd_init_thermal_info(hdd_ctx); 7638 if (ret) { 7639 hdd_err("Error while initializing thermal information"); 7640 goto deregister_frames; 7641 } 7642 7643 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g; 7644 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g; 7645 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit); 7646 if (!QDF_IS_STATUS_SUCCESS(status)) 7647 hdd_err("Error setting txlimit in sme: %d", status); 7648 7649 hdd_tsf_init(hdd_ctx); 7650 hdd_encrypt_decrypt_init(hdd_ctx); 7651 7652 ret = hdd_register_cb(hdd_ctx); 7653 if (ret) { 7654 hdd_err("Failed to register HDD callbacks!"); 7655 goto deregister_frames; 7656 } 7657 7658 if (hdd_ctx->config->dual_mac_feature_disable) { 7659 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx); 7660 if (status != QDF_STATUS_SUCCESS) { 7661 hdd_err("Failed to disable dual mac features"); 7662 goto deregister_cb; 7663 } 7664 } 7665 7666 /* register P2P Listen Offload event callback */ 7667 if (wma_is_p2p_lo_capable()) 7668 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx, 7669 wlan_hdd_p2p_lo_event_callback); 7670 7671 ret = hdd_set_auto_shutdown_cb(hdd_ctx); 7672 7673 if (ret) 7674 goto deregister_cb; 7675 7676 EXIT(); 7677 return 0; 7678 7679 deregister_cb: 7680 hdd_deregister_cb(hdd_ctx); 7681 deregister_frames: 7682 wlan_hdd_cfg80211_deregister_frames(adapter); 7683 out: 7684 return -EINVAL; 7685 7686 } 7687 7688 7689 /** 7690 * hdd_configure_cds() - Configure cds modules 7691 * @hdd_ctx: HDD context 7692 * @adapter: Primary adapter context 7693 * 7694 * Enable Cds modules after WLAN firmware is up. 7695 * 7696 * Return: 0 on success and errno on failure. 7697 */ 7698 int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) 7699 { 7700 int ret; 7701 QDF_STATUS status; 7702 /* structure of function pointers to be used by CDS */ 7703 struct cds_sme_cbacks sme_cbacks; 7704 7705 ret = hdd_pre_enable_configure(hdd_ctx); 7706 if (ret) { 7707 hdd_err("Failed to pre-configure cds"); 7708 goto out; 7709 } 7710 7711 /* 7712 * Start CDS which starts up the SME/MAC/HAL modules and everything 7713 * else 7714 */ 7715 status = cds_enable(hdd_ctx->pcds_context); 7716 7717 if (!QDF_IS_STATUS_SUCCESS(status)) { 7718 hdd_alert("cds_enable failed"); 7719 goto out; 7720 } 7721 7722 status = hdd_post_cds_enable_config(hdd_ctx); 7723 if (!QDF_IS_STATUS_SUCCESS(status)) { 7724 hdd_alert("hdd_post_cds_enable_config failed"); 7725 goto cds_disable; 7726 } 7727 7728 ret = hdd_features_init(hdd_ctx, adapter); 7729 if (ret) 7730 goto cds_disable; 7731 7732 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels; 7733 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss; 7734 status = cds_init_policy_mgr(&sme_cbacks); 7735 if (!QDF_IS_STATUS_SUCCESS(status)) { 7736 hdd_err("Policy manager initialization failed"); 7737 goto hdd_features_deinit; 7738 } 7739 7740 return 0; 7741 7742 hdd_features_deinit: 7743 hdd_deregister_cb(hdd_ctx); 7744 wlan_hdd_cfg80211_deregister_frames(adapter); 7745 cds_disable: 7746 cds_disable(hdd_ctx->pcds_context); 7747 7748 out: 7749 return -EINVAL; 7750 } 7751 7752 /** 7753 * hdd_deconfigure_cds() -De-Configure cds 7754 * @hdd_ctx: HDD context 7755 * 7756 * Deconfigure Cds modules before WLAN firmware is down. 7757 * 7758 * Return: 0 on success and errno on failure. 7759 */ 7760 static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx) 7761 { 7762 QDF_STATUS qdf_status; 7763 int ret = 0; 7764 7765 ENTER(); 7766 /* De-register the SME callbacks */ 7767 hdd_deregister_cb(hdd_ctx); 7768 hdd_encrypt_decrypt_deinit(hdd_ctx); 7769 7770 /* De-init Policy Manager */ 7771 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) { 7772 hdd_err("Failed to deinit policy manager"); 7773 /* Proceed and complete the clean up */ 7774 ret = -EINVAL; 7775 } 7776 7777 qdf_status = cds_disable(hdd_ctx->pcds_context); 7778 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 7779 hdd_err("Failed to Disable the CDS Modules! :%d", 7780 qdf_status); 7781 ret = -EINVAL; 7782 } 7783 7784 EXIT(); 7785 return ret; 7786 } 7787 7788 7789 /** 7790 * hdd_wlan_stop_modules - Single driver state machine for stoping modules 7791 * @hdd_ctx: HDD context 7792 * 7793 * This function maintains the driver state machine it will be invoked from 7794 * exit, shutdown and con_mode change handler. Depending on the driver state 7795 * shall perform the stopping/closing of the modules. 7796 * 7797 * Return: 0 for success; non-zero for failure 7798 */ 7799 int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx) 7800 { 7801 void *hif_ctx; 7802 qdf_device_t qdf_ctx; 7803 QDF_STATUS qdf_status; 7804 int ret = 0; 7805 p_cds_sched_context cds_sched_context = NULL; 7806 7807 ENTER(); 7808 7809 7810 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 7811 if (!qdf_ctx) { 7812 hdd_err("QDF device context NULL"); 7813 return -EINVAL; 7814 } 7815 7816 cds_sched_context = get_cds_sched_ctxt(); 7817 if (!cds_sched_context) { 7818 hdd_err("cds scheduler context NULL"); 7819 return -EINVAL; 7820 } 7821 mutex_lock(&hdd_ctx->iface_change_lock); 7822 hdd_ctx->stop_modules_in_progress = true; 7823 7824 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status); 7825 7826 switch (hdd_ctx->driver_status) { 7827 case DRIVER_MODULES_UNINITIALIZED: 7828 hdd_info("Modules not initialized just return"); 7829 goto done; 7830 case DRIVER_MODULES_CLOSED: 7831 hdd_info("Modules already closed"); 7832 goto done; 7833 case DRIVER_MODULES_ENABLED: 7834 hdd_disable_power_management(); 7835 if (hdd_deconfigure_cds(hdd_ctx)) { 7836 hdd_alert("Failed to de-configure CDS"); 7837 QDF_ASSERT(0); 7838 ret = -EINVAL; 7839 } 7840 hdd_info("successfully Disabled the CDS modules!"); 7841 hdd_ctx->driver_status = DRIVER_MODULES_OPENED; 7842 break; 7843 case DRIVER_MODULES_OPENED: 7844 hdd_info("Closing CDS modules!"); 7845 break; 7846 default: 7847 hdd_err("Trying to stop wlan in a wrong state: %d", 7848 hdd_ctx->driver_status); 7849 QDF_ASSERT(0); 7850 ret = -EINVAL; 7851 goto done; 7852 } 7853 7854 qdf_status = cds_post_disable(hdd_ctx->pcds_context); 7855 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 7856 hdd_err("Failed to process post CDS disable Modules! :%d", 7857 qdf_status); 7858 ret = -EINVAL; 7859 QDF_ASSERT(0); 7860 } 7861 qdf_status = cds_close(hdd_ctx->pcds_context); 7862 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 7863 hdd_warn("Failed to stop CDS:%d", qdf_status); 7864 ret = -EINVAL; 7865 QDF_ASSERT(0); 7866 } 7867 /* Clean up message queues of TX, RX and MC thread */ 7868 if (!cds_is_driver_recovering()) 7869 cds_sched_flush_mc_mqs(cds_sched_context); 7870 7871 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 7872 if (!hif_ctx) { 7873 hdd_err("Hif context is Null"); 7874 ret = -EINVAL; 7875 } 7876 7877 hdd_hif_close(hif_ctx); 7878 7879 ol_cds_free(); 7880 7881 if (!cds_is_driver_recovering()) { 7882 ret = pld_power_off(qdf_ctx->dev); 7883 if (ret) 7884 hdd_err("CNSS power down failed put device into Low power mode:%d", 7885 ret); 7886 } 7887 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED; 7888 7889 done: 7890 hdd_ctx->stop_modules_in_progress = false; 7891 mutex_unlock(&hdd_ctx->iface_change_lock); 7892 EXIT(); 7893 7894 return ret; 7895 7896 } 7897 7898 /** 7899 * hdd_iface_change_callback() - Function invoked when stop modules expires 7900 * @priv: pointer to hdd context 7901 * 7902 * This function is invoked when the timer waiting for the interface change 7903 * expires, it shall cut-down the power to wlan and stop all the modules. 7904 * 7905 * Return: void 7906 */ 7907 static void hdd_iface_change_callback(void *priv) 7908 { 7909 hdd_context_t *hdd_ctx = (hdd_context_t *) priv; 7910 int ret; 7911 int status = wlan_hdd_validate_context(hdd_ctx); 7912 7913 if (status) 7914 return; 7915 7916 ENTER(); 7917 hdd_info("Interface change timer expired close the modules!"); 7918 ret = hdd_wlan_stop_modules(hdd_ctx); 7919 if (ret) 7920 hdd_alert("Failed to stop modules"); 7921 EXIT(); 7922 } 7923 7924 /** 7925 * hdd_state_info_dump() - prints state information of hdd layer 7926 * @buf: buffer pointer 7927 * @size: size of buffer to be filled 7928 * 7929 * This function is used to dump state information of hdd layer 7930 * 7931 * Return: None 7932 */ 7933 static void hdd_state_info_dump(char **buf_ptr, uint16_t *size) 7934 { 7935 hdd_context_t *hdd_ctx; 7936 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; 7937 QDF_STATUS status; 7938 hdd_station_ctx_t *hdd_sta_ctx; 7939 hdd_adapter_t *adapter; 7940 uint16_t len = 0; 7941 char *buf = *buf_ptr; 7942 7943 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 7944 if (!hdd_ctx) { 7945 hdd_err("Failed to get hdd context "); 7946 return; 7947 } 7948 7949 hdd_notice("size of buffer: %d", *size); 7950 7951 len += scnprintf(buf + len, *size - len, 7952 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended); 7953 len += scnprintf(buf + len, *size - len, 7954 "\n isMcThreadSuspended %d", 7955 hdd_ctx->isMcThreadSuspended); 7956 7957 status = hdd_get_front_adapter(hdd_ctx, &adapter_node); 7958 7959 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) { 7960 adapter = adapter_node->pAdapter; 7961 if (adapter->dev) 7962 len += scnprintf(buf + len, *size - len, 7963 "\n device name: %s", adapter->dev->name); 7964 len += scnprintf(buf + len, *size - len, 7965 "\n device_mode: %d", adapter->device_mode); 7966 switch (adapter->device_mode) { 7967 case QDF_STA_MODE: 7968 case QDF_P2P_CLIENT_MODE: 7969 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); 7970 len += scnprintf(buf + len, *size - len, 7971 "\n connState: %d", 7972 hdd_sta_ctx->conn_info.connState); 7973 break; 7974 7975 default: 7976 break; 7977 } 7978 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); 7979 adapter_node = next; 7980 } 7981 7982 *size -= len; 7983 *buf_ptr += len; 7984 } 7985 7986 /** 7987 * hdd_register_debug_callback() - registration function for hdd layer 7988 * to print hdd state information 7989 * 7990 * Return: None 7991 */ 7992 static void hdd_register_debug_callback(void) 7993 { 7994 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump); 7995 } 7996 7997 /** 7998 * hdd_wlan_startup() - HDD init function 7999 * @dev: Pointer to the underlying device 8000 * 8001 * This is the driver startup code executed once a WLAN device has been detected 8002 * 8003 * Return: 0 for success, < 0 for failure 8004 */ 8005 int hdd_wlan_startup(struct device *dev) 8006 { 8007 QDF_STATUS status; 8008 hdd_adapter_t *adapter = NULL; 8009 hdd_context_t *hdd_ctx = NULL; 8010 int ret; 8011 void *hif_sc; 8012 bool rtnl_held; 8013 int set_value; 8014 8015 ENTER(); 8016 8017 hdd_ctx = hdd_context_create(dev); 8018 8019 if (IS_ERR(hdd_ctx)) 8020 return PTR_ERR(hdd_ctx); 8021 8022 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW, 8023 hdd_iface_change_callback, (void *)hdd_ctx); 8024 8025 mutex_init(&hdd_ctx->iface_change_lock); 8026 8027 ret = hdd_init_netlink_services(hdd_ctx); 8028 if (ret) 8029 goto err_hdd_free_context; 8030 8031 hdd_green_ap_init(hdd_ctx); 8032 8033 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false); 8034 if (ret) { 8035 hdd_alert("Failed to start modules: %d", ret); 8036 goto err_exit_nl_srv; 8037 } 8038 8039 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config); 8040 8041 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME); 8042 8043 if (NULL == hdd_ctx->hHal) { 8044 hdd_alert("HAL context is null"); 8045 goto err_stop_modules; 8046 } 8047 8048 ret = hdd_wiphy_init(hdd_ctx); 8049 if (ret) { 8050 hdd_alert("Failed to initialize wiphy: %d", ret); 8051 goto err_stop_modules; 8052 } 8053 8054 if (hdd_ctx->config->enable_dp_trace) 8055 qdf_dp_trace_init(); 8056 8057 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE) 8058 goto err_wiphy_unregister; 8059 8060 hdd_initialize_mac_address(hdd_ctx); 8061 8062 rtnl_held = hdd_hold_rtnl_lock(); 8063 8064 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held); 8065 8066 if (IS_ERR(adapter)) { 8067 hdd_alert("Failed to open interface, adapter is NULL"); 8068 ret = PTR_ERR(adapter); 8069 goto err_ipa_cleanup; 8070 } 8071 8072 hif_sc = cds_get_context(QDF_MODULE_ID_HIF); 8073 if (!hif_sc) { 8074 hdd_err("HIF context is NULL"); 8075 goto err_close_adapter; 8076 } 8077 /* 8078 * target hw version/revision would only be retrieved after firmware 8079 * donwload 8080 */ 8081 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version, 8082 &hdd_ctx->target_hw_revision, 8083 &hdd_ctx->target_hw_name); 8084 8085 /* Get the wlan hw/fw version */ 8086 hdd_wlan_get_version(hdd_ctx, NULL, NULL); 8087 8088 hdd_release_rtnl_lock(); 8089 rtnl_held = false; 8090 8091 if (hdd_ctx->config->enable_go_cts2self_for_sta) 8092 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal); 8093 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE 8094 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer, 8095 QDF_TIMER_TYPE_SW, 8096 hdd_skip_acs_scan_timer_handler, 8097 (void *)hdd_ctx); 8098 if (!QDF_IS_STATUS_SUCCESS(status)) 8099 hdd_err("Failed to init ACS Skip timer"); 8100 qdf_spinlock_create(&hdd_ctx->acs_skip_lock); 8101 #endif 8102 8103 hdd_bus_bandwidth_init(hdd_ctx); 8104 8105 hdd_lpass_notify_start(hdd_ctx); 8106 8107 if (hdd_ctx->rps) 8108 hdd_set_rps_cpu_mask(hdd_ctx); 8109 8110 8111 if (cds_is_packet_log_enabled()) 8112 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0); 8113 8114 ret = hdd_register_notifiers(hdd_ctx); 8115 if (ret) 8116 goto err_debugfs_exit; 8117 8118 status = wlansap_global_init(); 8119 if (QDF_IS_STATUS_ERROR(status)) 8120 goto err_debugfs_exit; 8121 8122 hdd_runtime_suspend_context_init(hdd_ctx); 8123 memdump_init(); 8124 hdd_driver_memdump_init(); 8125 8126 if (hdd_ctx->config->fIsImpsEnabled) 8127 hdd_set_idle_ps_config(hdd_ctx, true); 8128 8129 if (hdd_ctx->config->sifs_burst_duration) { 8130 set_value = (SIFS_BURST_DUR_MULTIPLIER) * 8131 hdd_ctx->config->sifs_burst_duration; 8132 8133 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX)) 8134 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR, 8135 set_value, PDEV_CMD); 8136 } 8137 8138 qdf_mc_timer_start(&hdd_ctx->iface_change_timer, 8139 hdd_ctx->config->iface_change_wait_time * 5000); 8140 8141 if (hdd_ctx->config->goptimize_chan_avoid_event) { 8142 status = sme_enable_disable_chanavoidind_event( 8143 hdd_ctx->hHal, 0); 8144 if (!QDF_IS_STATUS_SUCCESS(status)) 8145 hdd_err("Failed to disable Chan Avoidance Indication"); 8146 } 8147 goto success; 8148 8149 err_debugfs_exit: 8150 hdd_debugfs_exit(adapter); 8151 8152 err_close_adapter: 8153 hdd_close_all_adapters(hdd_ctx, false); 8154 8155 if (rtnl_held) 8156 hdd_release_rtnl_lock(); 8157 8158 err_ipa_cleanup: 8159 hdd_ipa_cleanup(hdd_ctx); 8160 8161 err_wiphy_unregister: 8162 wiphy_unregister(hdd_ctx->wiphy); 8163 8164 err_stop_modules: 8165 hdd_wlan_stop_modules(hdd_ctx); 8166 8167 8168 status = cds_sched_close(hdd_ctx->pcds_context); 8169 if (!QDF_IS_STATUS_SUCCESS(status)) { 8170 hdd_alert("Failed to close CDS Scheduler"); 8171 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status)); 8172 } 8173 8174 err_exit_nl_srv: 8175 hdd_green_ap_deinit(hdd_ctx); 8176 hdd_exit_netlink_services(hdd_ctx); 8177 8178 cds_deinit_ini_config(); 8179 err_hdd_free_context: 8180 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx); 8181 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer); 8182 mutex_destroy(&hdd_ctx->iface_change_lock); 8183 hdd_context_destroy(hdd_ctx); 8184 QDF_BUG(1); 8185 8186 return -EIO; 8187 8188 success: 8189 EXIT(); 8190 return 0; 8191 } 8192 8193 /** 8194 * hdd_wlan_update_target_info() - update target type info 8195 * @hdd_ctx: HDD context 8196 * @context: hif context 8197 * 8198 * Update target info received from firmware in hdd context 8199 * Return:None 8200 */ 8201 8202 void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context) 8203 { 8204 struct hif_target_info *tgt_info = hif_get_target_info_handle(context); 8205 8206 if (!tgt_info) { 8207 hdd_err("Target info is Null"); 8208 return; 8209 } 8210 8211 hdd_ctx->target_type = tgt_info->target_type; 8212 } 8213 8214 /** 8215 * hdd_register_cb - Register HDD callbacks. 8216 * @hdd_ctx: HDD context 8217 * 8218 * Register the HDD callbacks to CDS/SME. 8219 * 8220 * Return: 0 for success or Error code for failure 8221 */ 8222 int hdd_register_cb(hdd_context_t *hdd_ctx) 8223 { 8224 QDF_STATUS status; 8225 int ret = 0; 8226 8227 ENTER(); 8228 8229 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done); 8230 8231 sme_register_oem_data_rsp_callback(hdd_ctx->hHal, 8232 hdd_send_oem_data_rsp_msg); 8233 8234 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal, 8235 wlan_hdd_cfg80211_fw_mem_dump_cb); 8236 if (!QDF_IS_STATUS_SUCCESS(status)) { 8237 hdd_err("Failed to register memdump callback"); 8238 ret = -EINVAL; 8239 return ret; 8240 } 8241 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal, 8242 hdd_indicate_mgmt_frame); 8243 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx); 8244 sme_nan_register_callback(hdd_ctx->hHal, 8245 wlan_hdd_cfg80211_nan_callback); 8246 sme_stats_ext_register_callback(hdd_ctx->hHal, 8247 wlan_hdd_cfg80211_stats_ext_callback); 8248 8249 sme_ext_scan_register_callback(hdd_ctx->hHal, 8250 wlan_hdd_cfg80211_extscan_callback); 8251 8252 status = cds_register_sap_restart_channel_switch_cb( 8253 (void *)hdd_sap_restart_with_channel_switch); 8254 if (!QDF_IS_STATUS_SUCCESS(status)) { 8255 hdd_err("restart cb registration failed"); 8256 ret = -EINVAL; 8257 return ret; 8258 } 8259 8260 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal, 8261 hdd_rssi_threshold_breached); 8262 8263 status = sme_bpf_offload_register_callback(hdd_ctx->hHal, 8264 hdd_get_bpf_offload_cb); 8265 if (!QDF_IS_STATUS_SUCCESS(status)) { 8266 hdd_err("set bpf offload callback failed"); 8267 ret = -EINVAL; 8268 return ret; 8269 } 8270 8271 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal, 8272 wlan_hdd_cfg80211_link_layer_stats_callback); 8273 8274 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx); 8275 8276 EXIT(); 8277 8278 return ret; 8279 } 8280 8281 /** 8282 * hdd_deregister_cb() - De-Register HDD callbacks. 8283 * @hdd_ctx: HDD context 8284 * 8285 * De-Register the HDD callbacks to CDS/SME. 8286 * 8287 * Return: void 8288 */ 8289 void hdd_deregister_cb(hdd_context_t *hdd_ctx) 8290 { 8291 QDF_STATUS status; 8292 8293 ENTER(); 8294 8295 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal); 8296 if (!QDF_IS_STATUS_SUCCESS(status)) 8297 hdd_err("De-register of dcc stats callback failed: %d", 8298 status); 8299 8300 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal); 8301 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal); 8302 if (!QDF_IS_STATUS_SUCCESS(status)) 8303 hdd_err("De-register bpf offload callback failed: %d", 8304 status); 8305 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal); 8306 8307 status = cds_deregister_sap_restart_channel_switch_cb(); 8308 if (!QDF_IS_STATUS_SUCCESS(status)) 8309 hdd_err("De-register restart cb registration failed: %d", 8310 status); 8311 8312 sme_stats_ext_register_callback(hdd_ctx->hHal, 8313 wlan_hdd_cfg80211_stats_ext_callback); 8314 8315 sme_nan_deregister_callback(hdd_ctx->hHal); 8316 status = sme_reset_tsfcb(hdd_ctx->hHal); 8317 if (!QDF_IS_STATUS_SUCCESS(status)) 8318 hdd_err("Failed to de-register tsfcb the callback:%d", 8319 status); 8320 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal); 8321 if (!QDF_IS_STATUS_SUCCESS(status)) 8322 hdd_err("Failed to de-register the fw mem dump callback: %d", 8323 status); 8324 8325 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal); 8326 sme_deregister11d_scan_done_callback(hdd_ctx->hHal); 8327 8328 EXIT(); 8329 } 8330 8331 /** 8332 * hdd_softap_sta_deauth() - handle deauth req from HDD 8333 * @adapter: Pointer to the HDD 8334 * @enable: bool value 8335 * 8336 * This to take counter measure to handle deauth req from HDD 8337 * 8338 * Return: None 8339 */ 8340 QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter, 8341 struct tagCsrDelStaParams *pDelStaParams) 8342 { 8343 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT; 8344 8345 ENTER(); 8346 8347 hdd_notice("hdd_softap_sta_deauth:(%p, false)", 8348 (WLAN_HDD_GET_CTX(adapter))->pcds_context); 8349 8350 /* Ignore request to deauth bcmc station */ 8351 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1) 8352 return qdf_status; 8353 8354 qdf_status = 8355 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), 8356 pDelStaParams); 8357 8358 EXIT(); 8359 return qdf_status; 8360 } 8361 8362 /** 8363 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD 8364 * @adapter: Pointer to the HDD 8365 * @p_del_sta_params: pointer to station deletion parameters 8366 * 8367 * This to take counter measure to handle deauth req from HDD 8368 * 8369 * Return: None 8370 */ 8371 void hdd_softap_sta_disassoc(hdd_adapter_t *adapter, 8372 struct tagCsrDelStaParams *pDelStaParams) 8373 { 8374 ENTER(); 8375 8376 hdd_err("hdd_softap_sta_disassoc:(%p, false)", 8377 (WLAN_HDD_GET_CTX(adapter))->pcds_context); 8378 8379 /* Ignore request to disassoc bcmc station */ 8380 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1) 8381 return; 8382 8383 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), 8384 pDelStaParams); 8385 } 8386 8387 void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter, 8388 bool enable) 8389 { 8390 ENTER(); 8391 8392 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", 8393 (WLAN_HDD_GET_CTX(adapter))->pcds_context); 8394 8395 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter), 8396 (bool) enable); 8397 } 8398 8399 /** 8400 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected 8401 * @hdd_ctx: HDD Context 8402 * 8403 * API to find if there is any STA or P2P-Client is connected 8404 * 8405 * Return: true if connected; false otherwise 8406 */ 8407 QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx) 8408 { 8409 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal); 8410 } 8411 8412 /** 8413 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one 8414 * @adapter: HDD adapter pointer 8415 * 8416 * This function loop through each adapter and disable roaming on each STA 8417 * device mode except the input adapter. 8418 * 8419 * Note: On the input adapter roaming is not enabled yet hence no need to 8420 * disable. 8421 * 8422 * Return: None 8423 */ 8424 void wlan_hdd_disable_roaming(hdd_adapter_t *adapter) 8425 { 8426 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 8427 hdd_adapter_t *adapterIdx = NULL; 8428 hdd_adapter_list_node_t *adapterNode = NULL; 8429 hdd_adapter_list_node_t *pNext = NULL; 8430 QDF_STATUS status; 8431 8432 if (hdd_ctx->config->isFastRoamIniFeatureEnabled && 8433 hdd_ctx->config->isRoamOffloadScanEnabled && 8434 QDF_STA_MODE == adapter->device_mode && 8435 cds_is_sta_active_connection_exists()) { 8436 hdd_notice("Connect received on STA sessionId(%d)", 8437 adapter->sessionId); 8438 /* 8439 * Loop through adapter and disable roaming for each STA device 8440 * mode except the input adapter. 8441 */ 8442 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 8443 8444 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 8445 adapterIdx = adapterNode->pAdapter; 8446 8447 if (QDF_STA_MODE == adapterIdx->device_mode 8448 && adapter->sessionId != adapterIdx->sessionId) { 8449 hdd_notice("Disable Roaming on sessionId(%d)", 8450 adapterIdx->sessionId); 8451 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX 8452 (adapterIdx), 8453 adapterIdx->sessionId, 0); 8454 } 8455 8456 status = hdd_get_next_adapter(hdd_ctx, 8457 adapterNode, 8458 &pNext); 8459 adapterNode = pNext; 8460 } 8461 } 8462 } 8463 8464 /** 8465 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one 8466 * @adapter: HDD adapter pointer 8467 * 8468 * This function loop through each adapter and enable roaming on each STA 8469 * device mode except the input adapter. 8470 * Note: On the input adapter no need to enable roaming because link got 8471 * disconnected on this. 8472 * 8473 * Return: None 8474 */ 8475 void wlan_hdd_enable_roaming(hdd_adapter_t *adapter) 8476 { 8477 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 8478 hdd_adapter_t *adapterIdx = NULL; 8479 hdd_adapter_list_node_t *adapterNode = NULL; 8480 hdd_adapter_list_node_t *pNext = NULL; 8481 QDF_STATUS status; 8482 8483 if (hdd_ctx->config->isFastRoamIniFeatureEnabled && 8484 hdd_ctx->config->isRoamOffloadScanEnabled && 8485 QDF_STA_MODE == adapter->device_mode && 8486 cds_is_sta_active_connection_exists()) { 8487 hdd_notice("Disconnect received on STA sessionId(%d)", 8488 adapter->sessionId); 8489 /* 8490 * Loop through adapter and enable roaming for each STA device 8491 * mode except the input adapter. 8492 */ 8493 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 8494 8495 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 8496 adapterIdx = adapterNode->pAdapter; 8497 8498 if (QDF_STA_MODE == adapterIdx->device_mode 8499 && adapter->sessionId != adapterIdx->sessionId) { 8500 hdd_notice("Enabling Roaming on sessionId(%d)", 8501 adapterIdx->sessionId); 8502 sme_start_roaming(WLAN_HDD_GET_HAL_CTX 8503 (adapterIdx), 8504 adapterIdx->sessionId, 8505 REASON_CONNECT); 8506 } 8507 8508 status = hdd_get_next_adapter(hdd_ctx, 8509 adapterNode, 8510 &pNext); 8511 adapterNode = pNext; 8512 } 8513 } 8514 } 8515 8516 void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len) 8517 { 8518 struct sk_buff *skb; 8519 struct nlmsghdr *nlh; 8520 tAniMsgHdr *ani_hdr; 8521 void *nl_data = NULL; 8522 int flags = GFP_KERNEL; 8523 struct radio_index_tlv *radio_info; 8524 int tlv_len; 8525 8526 if (in_interrupt() || irqs_disabled() || in_atomic()) 8527 flags = GFP_ATOMIC; 8528 8529 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags); 8530 8531 if (skb == NULL) { 8532 hdd_err("alloc_skb failed"); 8533 return; 8534 } 8535 8536 nlh = (struct nlmsghdr *)skb->data; 8537 nlh->nlmsg_pid = 0; /* from kernel */ 8538 nlh->nlmsg_flags = 0; 8539 nlh->nlmsg_seq = 0; 8540 nlh->nlmsg_type = WLAN_NL_MSG_SVC; 8541 8542 ani_hdr = NLMSG_DATA(nlh); 8543 ani_hdr->type = type; 8544 8545 switch (type) { 8546 case WLAN_SVC_FW_CRASHED_IND: 8547 case WLAN_SVC_FW_SHUTDOWN_IND: 8548 case WLAN_SVC_LTE_COEX_IND: 8549 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND: 8550 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND: 8551 ani_hdr->length = 0; 8552 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr))); 8553 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr))); 8554 break; 8555 case WLAN_SVC_WLAN_STATUS_IND: 8556 case WLAN_SVC_WLAN_VERSION_IND: 8557 case WLAN_SVC_DFS_CAC_START_IND: 8558 case WLAN_SVC_DFS_CAC_END_IND: 8559 case WLAN_SVC_DFS_RADAR_DETECT_IND: 8560 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND: 8561 case WLAN_SVC_WLAN_TP_IND: 8562 case WLAN_SVC_WLAN_TP_TX_IND: 8563 case WLAN_SVC_RPS_ENABLE_IND: 8564 ani_hdr->length = len; 8565 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len)); 8566 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr); 8567 memcpy(nl_data, data, len); 8568 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len)); 8569 break; 8570 8571 default: 8572 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d", 8573 type); 8574 kfree_skb(skb); 8575 return; 8576 } 8577 8578 /* 8579 * Add radio index at the end of the svc event in TLV format to maintain 8580 * the backward compatibility with userspace applications. 8581 */ 8582 8583 tlv_len = 0; 8584 8585 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv)) 8586 < WLAN_NL_MAX_PAYLOAD) { 8587 radio_info = (struct radio_index_tlv *)((char *) ani_hdr + 8588 sizeof(*ani_hdr) + len); 8589 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX; 8590 radio_info->length = (unsigned short) sizeof(radio_info->radio); 8591 radio_info->radio = radio; 8592 tlv_len = sizeof(*radio_info); 8593 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO, 8594 "Added radio index tlv - radio index %d", 8595 radio_info->radio); 8596 } 8597 8598 nlh->nlmsg_len += tlv_len; 8599 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len)); 8600 8601 nl_srv_bcast(skb); 8602 8603 return; 8604 } 8605 8606 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN 8607 void wlan_hdd_auto_shutdown_cb(void) 8608 { 8609 hdd_context_t *hdd_ctx = cds_get_global_context(); 8610 8611 if (!hdd_ctx) 8612 return; 8613 8614 hdd_err("Wlan Idle. Sending Shutdown event.."); 8615 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index, 8616 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0); 8617 } 8618 8619 void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable) 8620 { 8621 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 8622 QDF_STATUS status; 8623 hdd_adapter_t *adapter; 8624 bool ap_connected = false, sta_connected = false; 8625 tHalHandle hal_handle; 8626 8627 hal_handle = hdd_ctx->hHal; 8628 if (hal_handle == NULL) 8629 return; 8630 8631 if (hdd_ctx->config->WlanAutoShutdown == 0) 8632 return; 8633 8634 if (enable == false) { 8635 if (sme_set_auto_shutdown_timer(hal_handle, 0) != 8636 QDF_STATUS_SUCCESS) { 8637 hdd_err("Failed to stop wlan auto shutdown timer"); 8638 } 8639 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index, 8640 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0); 8641 return; 8642 } 8643 8644 /* To enable shutdown timer check conncurrency */ 8645 if (cds_concurrent_open_sessions_running()) { 8646 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 8647 8648 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 8649 adapter = adapterNode->pAdapter; 8650 if (adapter 8651 && adapter->device_mode == 8652 QDF_STA_MODE) { 8653 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)-> 8654 conn_info.connState == 8655 eConnectionState_Associated) { 8656 sta_connected = true; 8657 break; 8658 } 8659 } 8660 if (adapter 8661 && adapter->device_mode == QDF_SAP_MODE) { 8662 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)-> 8663 bApActive == true) { 8664 ap_connected = true; 8665 break; 8666 } 8667 } 8668 status = hdd_get_next_adapter(hdd_ctx, 8669 adapterNode, 8670 &pNext); 8671 adapterNode = pNext; 8672 } 8673 } 8674 8675 if (ap_connected == true || sta_connected == true) { 8676 hdd_notice("CC Session active. Shutdown timer not enabled"); 8677 return; 8678 } else { 8679 if (sme_set_auto_shutdown_timer(hal_handle, 8680 hdd_ctx->config-> 8681 WlanAutoShutdown) 8682 != QDF_STATUS_SUCCESS) 8683 hdd_err("Failed to start wlan auto shutdown timer"); 8684 else 8685 hdd_notice("Auto Shutdown timer for %d seconds enabled", 8686 hdd_ctx->config->WlanAutoShutdown); 8687 8688 } 8689 } 8690 #endif 8691 8692 hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter, 8693 bool check_start_bss) 8694 { 8695 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter); 8696 hdd_adapter_t *adapter, *con_sap_adapter; 8697 QDF_STATUS status = QDF_STATUS_SUCCESS; 8698 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 8699 8700 con_sap_adapter = NULL; 8701 8702 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 8703 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 8704 adapter = adapterNode->pAdapter; 8705 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) || 8706 (adapter->device_mode == QDF_P2P_GO_MODE)) && 8707 adapter != this_sap_adapter) { 8708 if (check_start_bss) { 8709 if (test_bit(SOFTAP_BSS_STARTED, 8710 &adapter->event_flags)) { 8711 con_sap_adapter = adapter; 8712 break; 8713 } 8714 } else { 8715 con_sap_adapter = adapter; 8716 break; 8717 } 8718 } 8719 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext); 8720 adapterNode = pNext; 8721 } 8722 8723 return con_sap_adapter; 8724 } 8725 8726 #ifdef MSM_PLATFORM 8727 void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter) 8728 { 8729 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 8730 8731 if (QDF_TIMER_STATE_RUNNING == 8732 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) 8733 return; 8734 8735 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer, 8736 hdd_ctx->config->busBandwidthComputeInterval); 8737 } 8738 8739 void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter) 8740 { 8741 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL; 8742 QDF_STATUS status; 8743 bool can_stop = true; 8744 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); 8745 8746 if (QDF_TIMER_STATE_RUNNING != 8747 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) { 8748 /* trying to stop timer, when not running is not good */ 8749 hdd_info("bus band width compute timer is not running"); 8750 return; 8751 } 8752 8753 if (cds_concurrent_open_sessions_running()) { 8754 status = hdd_get_front_adapter(hdd_ctx, &adapterNode); 8755 8756 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) { 8757 adapter = adapterNode->pAdapter; 8758 if (adapter 8759 && (adapter->device_mode == QDF_STA_MODE 8760 || adapter->device_mode == QDF_P2P_CLIENT_MODE) 8761 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)-> 8762 conn_info.connState == 8763 eConnectionState_Associated) { 8764 can_stop = false; 8765 break; 8766 } 8767 if (adapter 8768 && (adapter->device_mode == QDF_SAP_MODE 8769 || adapter->device_mode == QDF_P2P_GO_MODE) 8770 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == 8771 true) { 8772 can_stop = false; 8773 break; 8774 } 8775 status = hdd_get_next_adapter(hdd_ctx, 8776 adapterNode, 8777 &pNext); 8778 adapterNode = pNext; 8779 } 8780 } 8781 8782 if (can_stop == true) { 8783 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer); 8784 hdd_reset_tcp_delack(hdd_ctx); 8785 } 8786 } 8787 #endif 8788 8789 /** 8790 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's 8791 * and sta's operating channel. 8792 * @sta_adapter: Describe the first argument to foobar. 8793 * @ap_adapter: Describe the second argument to foobar. 8794 * @roam_profile: Roam profile of AP to which STA wants to connect. 8795 * @concurrent_chnl_same: If both SAP and STA channels are same then 8796 * set this flag to true else false. 8797 * 8798 * This function checks the sap's operating channel and sta's operating channel. 8799 * if both are same then it will return false else it will restart the sap in 8800 * sta's channel and return true. 8801 * 8802 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE. 8803 */ 8804 QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter, 8805 hdd_adapter_t *ap_adapter, 8806 tCsrRoamProfile *roam_profile, 8807 tScanResultHandle *scan_cache, 8808 bool *concurrent_chnl_same) 8809 { 8810 hdd_ap_ctx_t *hdd_ap_ctx; 8811 uint8_t channel_id; 8812 QDF_STATUS status; 8813 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode; 8814 *concurrent_chnl_same = true; 8815 8816 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); 8817 status = 8818 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter), 8819 roam_profile, 8820 scan_cache, 8821 &channel_id); 8822 if ((QDF_STATUS_SUCCESS == status)) { 8823 if ((QDF_SAP_MODE == device_mode) && 8824 (channel_id < SIR_11A_CHANNEL_BEGIN)) { 8825 if (hdd_ap_ctx->operatingChannel != channel_id) { 8826 *concurrent_chnl_same = false; 8827 hdd_info("channels are different"); 8828 } 8829 } else if ((QDF_P2P_GO_MODE == device_mode) && 8830 (channel_id >= SIR_11A_CHANNEL_BEGIN)) { 8831 if (hdd_ap_ctx->operatingChannel != channel_id) { 8832 *concurrent_chnl_same = false; 8833 hdd_info("channels are different"); 8834 } 8835 } 8836 } else { 8837 /* 8838 * Lets handle worst case scenario here, Scan cache lookup is 8839 * failed so we have to stop the SAP to avoid any channel 8840 * discrepancy between SAP's channel and STA's channel. 8841 * Return the status as failure so caller function could know 8842 * that scan look up is failed. 8843 */ 8844 hdd_err("Finding AP from scan cache failed"); 8845 return QDF_STATUS_E_FAILURE; 8846 } 8847 return QDF_STATUS_SUCCESS; 8848 } 8849 8850 /** 8851 * wlan_hdd_stop_sap() - This function stops bss of SAP. 8852 * @ap_adapter: SAP adapter 8853 * 8854 * This function will process the stopping of sap adapter. 8855 * 8856 * Return: None 8857 */ 8858 void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter) 8859 { 8860 hdd_ap_ctx_t *hdd_ap_ctx; 8861 hdd_hostapd_state_t *hostapd_state; 8862 QDF_STATUS qdf_status; 8863 hdd_context_t *hdd_ctx; 8864 8865 if (NULL == ap_adapter) { 8866 hdd_err("ap_adapter is NULL here"); 8867 return; 8868 } 8869 8870 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); 8871 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter); 8872 if (wlan_hdd_validate_context(hdd_ctx)) 8873 return; 8874 8875 mutex_lock(&hdd_ctx->sap_lock); 8876 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) { 8877 wlan_hdd_del_station(ap_adapter); 8878 hdd_cleanup_actionframe(hdd_ctx, ap_adapter); 8879 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter); 8880 hdd_info("Now doing SAP STOPBSS"); 8881 qdf_event_reset(&hostapd_state->qdf_stop_bss_event); 8882 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx-> 8883 sapContext)) { 8884 qdf_status = qdf_wait_single_event(&hostapd_state-> 8885 qdf_stop_bss_event, 8886 BSS_WAIT_TIMEOUT); 8887 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 8888 mutex_unlock(&hdd_ctx->sap_lock); 8889 hdd_err("SAP Stop Failed"); 8890 return; 8891 } 8892 } 8893 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); 8894 cds_decr_session_set_pcl(ap_adapter->device_mode, 8895 ap_adapter->sessionId); 8896 hdd_info("SAP Stop Success"); 8897 } else { 8898 hdd_err("Can't stop ap because its not started"); 8899 } 8900 mutex_unlock(&hdd_ctx->sap_lock); 8901 return; 8902 } 8903 8904 /** 8905 * wlan_hdd_start_sap() - this function starts bss of SAP. 8906 * @ap_adapter: SAP adapter 8907 * 8908 * This function will process the starting of sap adapter. 8909 * 8910 * Return: None 8911 */ 8912 void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter) 8913 { 8914 hdd_ap_ctx_t *hdd_ap_ctx; 8915 hdd_hostapd_state_t *hostapd_state; 8916 QDF_STATUS qdf_status; 8917 hdd_context_t *hdd_ctx; 8918 tsap_Config_t *sap_config; 8919 8920 if (NULL == ap_adapter) { 8921 hdd_err("ap_adapter is NULL here"); 8922 return; 8923 } 8924 8925 if (QDF_SAP_MODE != ap_adapter->device_mode) { 8926 hdd_err("SoftAp role has not been enabled"); 8927 return; 8928 } 8929 8930 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter); 8931 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter); 8932 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter); 8933 sap_config = &ap_adapter->sessionCtx.ap.sapConfig; 8934 8935 if (wlan_hdd_validate_context(hdd_ctx)) 8936 return; 8937 8938 mutex_lock(&hdd_ctx->sap_lock); 8939 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) 8940 goto end; 8941 8942 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) { 8943 hdd_err("SAP Not able to set AP IEs"); 8944 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL); 8945 goto end; 8946 } 8947 8948 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb, 8949 &hdd_ap_ctx->sapConfig, 8950 ap_adapter->dev) 8951 != QDF_STATUS_SUCCESS) 8952 goto end; 8953 8954 hdd_info("Waiting for SAP to start"); 8955 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event, 8956 BSS_WAIT_TIMEOUT); 8957 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 8958 hdd_err("SAP Start failed"); 8959 goto end; 8960 } 8961 hdd_info("SAP Start Success"); 8962 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); 8963 cds_incr_active_session(ap_adapter->device_mode, 8964 ap_adapter->sessionId); 8965 hostapd_state->bCommit = true; 8966 8967 end: 8968 mutex_unlock(&hdd_ctx->sap_lock); 8969 return; 8970 } 8971 8972 /** 8973 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual 8974 * mac scan config 8975 * @status: Status of set antenna mode 8976 * 8977 * Callback on setting the dual mac configuration 8978 * 8979 * Return: None 8980 */ 8981 void wlan_hdd_soc_set_antenna_mode_cb( 8982 enum set_antenna_mode_status status) 8983 { 8984 hdd_context_t *hdd_ctx; 8985 8986 hdd_info("Status: %d", status); 8987 8988 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 8989 if (0 != wlan_hdd_validate_context(hdd_ctx)) 8990 return; 8991 8992 /* Signal the completion of set dual mac config */ 8993 complete(&hdd_ctx->set_antenna_mode_cmpl); 8994 } 8995 8996 /** 8997 * hdd_get_fw_version() - Get FW version 8998 * @hdd_ctx: pointer to HDD context. 8999 * @major_spid: FW version - major spid. 9000 * @minor_spid: FW version - minor spid 9001 * @ssid: FW version - ssid 9002 * @crmid: FW version - crmid 9003 * 9004 * This function is called to get the firmware build version stored 9005 * as part of the HDD context 9006 * 9007 * Return: None 9008 */ 9009 void hdd_get_fw_version(hdd_context_t *hdd_ctx, 9010 uint32_t *major_spid, uint32_t *minor_spid, 9011 uint32_t *siid, uint32_t *crmid) 9012 { 9013 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28; 9014 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24; 9015 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20; 9016 *crmid = hdd_ctx->target_fw_version & 0x7fff; 9017 } 9018 9019 #ifdef QCA_CONFIG_SMP 9020 /** 9021 * wlan_hdd_get_cpu() - get cpu_index 9022 * 9023 * Return: cpu_index 9024 */ 9025 int wlan_hdd_get_cpu(void) 9026 { 9027 int cpu_index = get_cpu(); 9028 put_cpu(); 9029 return cpu_index; 9030 } 9031 #endif 9032 9033 /** 9034 * hdd_get_fwpath() - get framework path 9035 * 9036 * This function is used to get the string written by 9037 * userspace to start the wlan driver 9038 * 9039 * Return: string 9040 */ 9041 const char *hdd_get_fwpath(void) 9042 { 9043 return fwpath.string; 9044 } 9045 9046 /** 9047 * hdd_init() - Initialize Driver 9048 * 9049 * This function initilizes CDS global context with the help of cds_init. This 9050 * has to be the first function called after probe to get a valid global 9051 * context. 9052 * 9053 * Return: 0 for success, errno on failure 9054 */ 9055 int hdd_init(void) 9056 { 9057 v_CONTEXT_t p_cds_context = NULL; 9058 int ret = 0; 9059 9060 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE 9061 wlan_logging_sock_init_svc(); 9062 #endif 9063 p_cds_context = cds_init(); 9064 9065 if (p_cds_context == NULL) { 9066 hdd_alert("Failed to allocate CDS context"); 9067 ret = -ENOMEM; 9068 goto err_out; 9069 } 9070 9071 hdd_trace_init(); 9072 hdd_register_debug_callback(); 9073 9074 err_out: 9075 return ret; 9076 } 9077 9078 /** 9079 * hdd_deinit() - Deinitialize Driver 9080 * 9081 * This function frees CDS global context with the help of cds_deinit. This 9082 * has to be the last function call in remove callback to free the global 9083 * context. 9084 */ 9085 void hdd_deinit(void) 9086 { 9087 cds_deinit(); 9088 9089 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE 9090 wlan_logging_sock_deinit_svc(); 9091 #endif 9092 } 9093 9094 #ifdef QCA_WIFI_3_0_ADRASTEA 9095 #define HDD_WLAN_START_WAIT_TIME (3600 * 1000) 9096 #else 9097 #define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000) 9098 #endif 9099 9100 /** 9101 * __hdd_module_init - Module init helper 9102 * 9103 * Module init helper function used by both module and static driver. 9104 * 9105 * Return: 0 for success, errno on failure 9106 */ 9107 static int __hdd_module_init(void) 9108 { 9109 int ret = 0; 9110 9111 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME, 9112 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); 9113 9114 pld_init(); 9115 9116 ret = hdd_init(); 9117 if (ret) { 9118 pr_err("hdd_init failed %x\n", ret); 9119 goto err_hdd_init; 9120 } 9121 9122 dispatcher_init(); 9123 9124 qdf_wake_lock_create(&wlan_wake_lock, "wlan"); 9125 9126 hdd_set_conparam((uint32_t) con_mode); 9127 9128 ret = wlan_hdd_register_driver(); 9129 if (ret) { 9130 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME, 9131 ret); 9132 goto out; 9133 } 9134 9135 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); 9136 9137 return 0; 9138 out: 9139 qdf_wake_lock_destroy(&wlan_wake_lock); 9140 dispatcher_deinit(); 9141 hdd_deinit(); 9142 9143 err_hdd_init: 9144 pld_deinit(); 9145 9146 return ret; 9147 } 9148 9149 /** 9150 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion 9151 * 9152 * Block the unloading of the driver until the cds recovery is completed 9153 * 9154 * Return: None 9155 */ 9156 static void hdd_wait_for_recovery_completion(void) 9157 { 9158 int retry = 0; 9159 9160 /* Wait for recovery to complete */ 9161 while (cds_is_driver_recovering()) { 9162 hdd_alert("Recovery in progress; wait here!!!"); 9163 msleep(1000); 9164 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) { 9165 hdd_alert("SSR never completed, fatal error"); 9166 QDF_BUG(0); 9167 } 9168 } 9169 } 9170 9171 /** 9172 * __hdd_module_exit - Module exit helper 9173 * 9174 * Module exit helper function used by both module and static driver. 9175 */ 9176 static void __hdd_module_exit(void) 9177 { 9178 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME, 9179 QWLAN_VERSIONSTR); 9180 9181 hdd_wait_for_recovery_completion(); 9182 9183 wlan_hdd_unregister_driver(); 9184 9185 qdf_wake_lock_destroy(&wlan_wake_lock); 9186 9187 dispatcher_deinit(); 9188 hdd_deinit(); 9189 pld_deinit(); 9190 9191 return; 9192 } 9193 9194 #ifndef MODULE 9195 /** 9196 * wlan_boot_cb() - Wlan boot callback 9197 * @kobj: object whose directory we're creating the link in. 9198 * @attr: attribute the user is interacting with 9199 * @buff: the buffer containing the user data 9200 * @count: number of bytes in the buffer 9201 * 9202 * This callback is invoked when the fs is ready to start the 9203 * wlan driver initialization. 9204 * 9205 * Return: 'count' on success or a negative error code in case of failure 9206 */ 9207 static ssize_t wlan_boot_cb(struct kobject *kobj, 9208 struct kobj_attribute *attr, 9209 const char *buf, 9210 size_t count) 9211 { 9212 9213 int ret = 0; 9214 9215 if (wlan_loader->loaded_state) { 9216 pr_info("Wlan driver already initialized"); 9217 return 0; 9218 } 9219 9220 9221 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME, 9222 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); 9223 9224 if (__hdd_module_init()) { 9225 pr_err("%s: Failed to register handler\n", __func__); 9226 ret = -EINVAL; 9227 } else 9228 wlan_loader->loaded_state = MODULE_INITIALIZED; 9229 9230 return count; 9231 9232 } 9233 9234 /** 9235 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is 9236 * ready 9237 * 9238 * This is creates the syfs entry boot_wlan. Which shall be invoked 9239 * when the filesystem is ready. 9240 * 9241 * Return: 0 for success, errno on failure 9242 */ 9243 static int wlan_init_sysfs(void) 9244 { 9245 int ret = -EINVAL; 9246 9247 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL); 9248 if (!wlan_loader) { 9249 pr_err("%s: memory alloc failed\n", __func__); 9250 ret = -ENOMEM; 9251 return ret; 9252 } 9253 9254 wlan_loader->boot_wlan_obj = NULL; 9255 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)), 9256 GFP_KERNEL); 9257 if (!wlan_loader->attr_group) { 9258 pr_err("%s: malloc attr_group failed\n", __func__); 9259 ret = -ENOMEM; 9260 goto error_return; 9261 } 9262 9263 wlan_loader->loaded_state = 0; 9264 wlan_loader->attr_group->attrs = attrs; 9265 9266 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan", 9267 kernel_kobj); 9268 if (!wlan_loader->boot_wlan_obj) { 9269 pr_err("%s: sysfs create and add failed\n", __func__); 9270 ret = -ENOMEM; 9271 goto error_return; 9272 } 9273 9274 ret = sysfs_create_group(wlan_loader->boot_wlan_obj, 9275 wlan_loader->attr_group); 9276 if (ret) { 9277 pr_err("%s: sysfs create group failed %d\n", __func__, ret); 9278 goto error_return; 9279 } 9280 9281 return 0; 9282 9283 error_return: 9284 9285 if (wlan_loader->boot_wlan_obj) { 9286 kobject_del(wlan_loader->boot_wlan_obj); 9287 wlan_loader->boot_wlan_obj = NULL; 9288 } 9289 9290 return ret; 9291 } 9292 9293 /** 9294 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan 9295 * 9296 * Return: 0 on success or errno on failure 9297 */ 9298 static int wlan_deinit_sysfs(void) 9299 { 9300 9301 if (!wlan_loader) { 9302 hdd_alert("wlan loader context is Null!"); 9303 return -EINVAL; 9304 } 9305 9306 if (wlan_loader->boot_wlan_obj) { 9307 sysfs_remove_group(wlan_loader->boot_wlan_obj, 9308 wlan_loader->attr_group); 9309 kobject_del(wlan_loader->boot_wlan_obj); 9310 wlan_loader->boot_wlan_obj = NULL; 9311 } 9312 9313 return 0; 9314 } 9315 9316 #endif 9317 9318 #ifdef MODULE 9319 /** 9320 * __hdd_module_init - Module init helper 9321 * 9322 * Module init helper function used by both module and static driver. 9323 * 9324 * Return: 0 for success, errno on failure 9325 */ 9326 static int hdd_module_init(void) 9327 { 9328 int ret = 0; 9329 9330 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME, 9331 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); 9332 9333 if (__hdd_module_init()) { 9334 pr_err("%s: Failed to register handler\n", __func__); 9335 ret = -EINVAL; 9336 } 9337 9338 return ret; 9339 } 9340 #else 9341 static int __init hdd_module_init(void) 9342 { 9343 int ret = -EINVAL; 9344 9345 ret = wlan_init_sysfs(); 9346 if (ret) 9347 pr_err("Failed to create sysfs entry for loading wlan"); 9348 9349 return ret; 9350 } 9351 #endif 9352 9353 9354 #ifdef MODULE 9355 /** 9356 * hdd_module_exit() - Exit function 9357 * 9358 * This is the driver exit point (invoked when module is unloaded using rmmod) 9359 * 9360 * Return: None 9361 */ 9362 static void __exit hdd_module_exit(void) 9363 { 9364 __hdd_module_exit(); 9365 } 9366 #else 9367 static void __exit hdd_module_exit(void) 9368 { 9369 __hdd_module_exit(); 9370 wlan_deinit_sysfs(); 9371 } 9372 #endif 9373 9374 static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp) 9375 { 9376 return param_set_copystring(kmessage, kp); 9377 } 9378 9379 /** 9380 * is_con_mode_valid() check con mode is valid or not 9381 * @mode: global con mode 9382 * 9383 * Return: TRUE on success FALSE on failure 9384 */ 9385 static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode) 9386 { 9387 switch (mode) { 9388 case QDF_GLOBAL_MONITOR_MODE: 9389 case QDF_GLOBAL_FTM_MODE: 9390 case QDF_GLOBAL_EPPING_MODE: 9391 case QDF_GLOBAL_MISSION_MODE: 9392 return true; 9393 default: 9394 return false; 9395 } 9396 } 9397 9398 /** 9399 * hdd_get_adpter_mode() - returns adapter mode based on global con mode 9400 * @mode: global con mode 9401 * 9402 * Return: adapter mode 9403 */ 9404 static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode( 9405 enum tQDF_GLOBAL_CON_MODE mode) 9406 { 9407 9408 switch (mode) { 9409 case QDF_GLOBAL_MISSION_MODE: 9410 return QDF_STA_MODE; 9411 case QDF_GLOBAL_MONITOR_MODE: 9412 return QDF_MONITOR_MODE; 9413 case QDF_GLOBAL_EPPING_MODE: 9414 return QDF_EPPING_MODE; 9415 case QDF_GLOBAL_FTM_MODE: 9416 return QDF_FTM_MODE; 9417 case QDF_GLOBAL_QVIT_MODE: 9418 return QDF_QVIT_MODE; 9419 default: 9420 return QDF_MAX_NO_OF_MODE; 9421 } 9422 } 9423 9424 static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx, 9425 enum tQDF_GLOBAL_CON_MODE curr_mode) 9426 { 9427 switch (curr_mode) { 9428 case QDF_GLOBAL_MISSION_MODE: 9429 case QDF_GLOBAL_MONITOR_MODE: 9430 case QDF_GLOBAL_FTM_MODE: 9431 hdd_abort_mac_scan_all_adapters(hdd_ctx); 9432 hdd_stop_all_adapters(hdd_ctx); 9433 hdd_deinit_all_adapters(hdd_ctx, false); 9434 hdd_close_all_adapters(hdd_ctx, false); 9435 break; 9436 case QDF_GLOBAL_EPPING_MODE: 9437 epping_disable(); 9438 epping_close(); 9439 break; 9440 default: 9441 return; 9442 } 9443 } 9444 9445 static int hdd_register_req_mode(hdd_context_t *hdd_ctx, 9446 enum tQDF_GLOBAL_CON_MODE mode) 9447 { 9448 hdd_adapter_t *adapter; 9449 int ret = 0; 9450 bool rtnl_held; 9451 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 9452 QDF_STATUS status; 9453 9454 if (!qdf_dev) { 9455 hdd_err("qdf device context is Null return!"); 9456 return -EINVAL; 9457 } 9458 9459 rtnl_held = hdd_hold_rtnl_lock(); 9460 switch (mode) { 9461 case QDF_GLOBAL_MISSION_MODE: 9462 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held); 9463 if (IS_ERR(adapter)) { 9464 hdd_alert("Failed to open interface, adapter is NULL"); 9465 ret = -EINVAL; 9466 } 9467 break; 9468 case QDF_GLOBAL_FTM_MODE: 9469 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d", 9470 wlan_hdd_get_intf_addr(hdd_ctx), 9471 NET_NAME_UNKNOWN, rtnl_held); 9472 if (adapter == NULL) 9473 ret = -EINVAL; 9474 break; 9475 case QDF_GLOBAL_MONITOR_MODE: 9476 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d", 9477 wlan_hdd_get_intf_addr(hdd_ctx), 9478 NET_NAME_UNKNOWN, rtnl_held); 9479 if (adapter == NULL) 9480 ret = -EINVAL; 9481 break; 9482 case QDF_GLOBAL_EPPING_MODE: 9483 status = epping_open(); 9484 if (status != QDF_STATUS_SUCCESS) { 9485 hdd_err("Failed to open in eeping mode: %d", status); 9486 ret = -EINVAL; 9487 break; 9488 } 9489 ret = epping_enable(qdf_dev->dev); 9490 if (ret) { 9491 hdd_err("Failed to enable in epping mode : %d", ret); 9492 epping_close(); 9493 } 9494 break; 9495 default: 9496 hdd_info("Mode not supported"); 9497 ret = -ENOTSUPP; 9498 break; 9499 } 9500 hdd_release_rtnl_lock(); 9501 rtnl_held = false; 9502 return ret; 9503 } 9504 9505 /** 9506 * __con_mode_handler() - Handles module param con_mode change 9507 * @kmessage: con mode name on which driver to be bring up 9508 * @kp: The associated kernel parameter 9509 * @hdd_ctx: Pointer to the global HDD context 9510 * 9511 * This function is invoked when user updates con mode using sys entry, 9512 * to initialize and bring-up driver in that specific mode. 9513 * 9514 * Return - 0 on success and failure code on failure 9515 */ 9516 static int __con_mode_handler(const char *kmessage, struct kernel_param *kp, 9517 hdd_context_t *hdd_ctx) 9518 { 9519 int ret; 9520 hdd_adapter_t *adapter; 9521 enum tQDF_GLOBAL_CON_MODE curr_mode; 9522 enum tQDF_ADAPTER_MODE adapter_mode; 9523 9524 ret = wlan_hdd_validate_context(hdd_ctx); 9525 if (ret) 9526 return ret; 9527 9528 cds_set_load_in_progress(true); 9529 9530 hdd_info("con_mode handler: %s", kmessage); 9531 ret = param_set_int(kmessage, kp); 9532 9533 9534 9535 if (!(is_con_mode_valid(con_mode))) { 9536 hdd_err("invlaid con_mode %d", con_mode); 9537 ret = -EINVAL; 9538 goto reset_flags; 9539 } 9540 9541 curr_mode = hdd_get_conparam(); 9542 if (curr_mode == con_mode) { 9543 hdd_err("curr mode: %d is same as user triggered mode %d", 9544 curr_mode, con_mode); 9545 ret = 0; 9546 goto reset_flags; 9547 } 9548 9549 /* Cleanup present mode before switching to new mode */ 9550 hdd_cleanup_present_mode(hdd_ctx, curr_mode); 9551 9552 ret = hdd_wlan_stop_modules(hdd_ctx); 9553 if (ret) { 9554 hdd_err("Stop wlan modules failed"); 9555 goto reset_flags; 9556 } 9557 9558 hdd_set_conparam(con_mode); 9559 9560 /* Register for new con_mode & then kick_start modules again */ 9561 ret = hdd_register_req_mode(hdd_ctx, con_mode); 9562 if (ret) { 9563 hdd_err("Failed to register for new mode"); 9564 goto reset_flags; 9565 } 9566 9567 adapter_mode = hdd_get_adpter_mode(con_mode); 9568 if (adapter_mode == QDF_MAX_NO_OF_MODE) { 9569 hdd_err("invalid adapter"); 9570 ret = -EINVAL; 9571 goto reset_flags; 9572 } 9573 9574 adapter = hdd_get_adapter(hdd_ctx, adapter_mode); 9575 if (!adapter) { 9576 hdd_err("Failed to get adapter:%d", adapter_mode); 9577 goto reset_flags; 9578 } 9579 9580 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false); 9581 if (ret) { 9582 hdd_err("Start wlan modules failed: %d", ret); 9583 goto reset_flags; 9584 } 9585 9586 if (con_mode == QDF_GLOBAL_MONITOR_MODE || 9587 con_mode == QDF_GLOBAL_FTM_MODE) { 9588 if (hdd_start_adapter(adapter)) { 9589 hdd_err("Failed to start %s adapter", kmessage); 9590 ret = -EINVAL; 9591 goto reset_flags; 9592 } 9593 } 9594 9595 hdd_info("Mode successfully changed to %s", kmessage); 9596 ret = 0; 9597 9598 reset_flags: 9599 cds_set_load_in_progress(false); 9600 return ret; 9601 } 9602 9603 9604 static int con_mode_handler(const char *kmessage, struct kernel_param *kp) 9605 { 9606 int ret; 9607 hdd_context_t *hdd_ctx; 9608 9609 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); 9610 ret = wlan_hdd_validate_context(hdd_ctx); 9611 if (ret) 9612 return ret; 9613 9614 cds_ssr_protect(__func__); 9615 ret = __con_mode_handler(kmessage, kp, hdd_ctx); 9616 cds_ssr_unprotect(__func__); 9617 9618 return ret; 9619 } 9620 9621 /** 9622 * hdd_get_conparam() - driver exit point 9623 * 9624 * This is the driver exit point (invoked when module is unloaded using rmmod) 9625 * 9626 * Return: enum tQDF_GLOBAL_CON_MODE 9627 */ 9628 enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void) 9629 { 9630 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode; 9631 } 9632 9633 void hdd_set_conparam(uint32_t con_param) 9634 { 9635 curr_con_mode = con_param; 9636 } 9637 9638 /** 9639 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface 9640 * @hdd_ctx: HDD context 9641 * 9642 * Cleans up the pre cac interface, if it exists 9643 * 9644 * Return: None 9645 */ 9646 void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx) 9647 { 9648 uint8_t session_id; 9649 QDF_STATUS status; 9650 struct hdd_adapter_s *precac_adapter; 9651 9652 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id); 9653 if (QDF_IS_STATUS_ERROR(status)) { 9654 hdd_err("failed to get pre cac vdev id"); 9655 return; 9656 } 9657 9658 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id); 9659 if (!precac_adapter) { 9660 hdd_err("invalid pre cac adapater"); 9661 return; 9662 } 9663 9664 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work, 9665 wlan_hdd_sap_pre_cac_failure, 9666 (void *)precac_adapter); 9667 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work); 9668 9669 } 9670 9671 /** 9672 * hdd_update_ol_config - API to update ol configuration parameters 9673 * @hdd_ctx: HDD context 9674 * 9675 * Return: void 9676 */ 9677 static void hdd_update_ol_config(hdd_context_t *hdd_ctx) 9678 { 9679 struct ol_config_info cfg; 9680 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI); 9681 9682 if (!ol_ctx) 9683 return; 9684 9685 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery; 9686 cfg.enable_uart_print = hdd_ctx->config->enablefwprint; 9687 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log; 9688 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled; 9689 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx); 9690 9691 ol_init_ini_config(ol_ctx, &cfg); 9692 } 9693 9694 #ifdef FEATURE_RUNTIME_PM 9695 /** 9696 * hdd_populate_runtime_cfg() - populate runtime configuration 9697 * @hdd_ctx: hdd context 9698 * @cfg: pointer to the configuration memory being populated 9699 * 9700 * Return: void 9701 */ 9702 static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx, 9703 struct hif_config_info *cfg) 9704 { 9705 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm; 9706 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay; 9707 } 9708 #else 9709 static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx, 9710 struct hif_config_info *cfg) 9711 { 9712 } 9713 #endif 9714 9715 /** 9716 * hdd_update_hif_config - API to update HIF configuration parameters 9717 * @hdd_ctx: HDD Context 9718 * 9719 * Return: void 9720 */ 9721 static void hdd_update_hif_config(hdd_context_t *hdd_ctx) 9722 { 9723 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF); 9724 struct hif_config_info cfg; 9725 9726 if (!scn) 9727 return; 9728 9729 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery; 9730 hdd_populate_runtime_cfg(hdd_ctx, &cfg); 9731 hif_init_ini_config(scn, &cfg); 9732 } 9733 9734 /** 9735 * hdd_update_config() - Initialize driver per module ini parameters 9736 * @hdd_ctx: HDD Context 9737 * 9738 * API is used to initialize all driver per module configuration parameters 9739 * Return: 0 for success, errno for failure 9740 */ 9741 int hdd_update_config(hdd_context_t *hdd_ctx) 9742 { 9743 int ret; 9744 9745 hdd_update_ol_config(hdd_ctx); 9746 hdd_update_hif_config(hdd_ctx); 9747 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) 9748 ret = hdd_update_cds_config_ftm(hdd_ctx); 9749 else 9750 ret = hdd_update_cds_config(hdd_ctx); 9751 9752 return ret; 9753 } 9754 9755 /** 9756 * wlan_hdd_get_dfs_mode() - get ACS DFS mode 9757 * @mode : cfg80211 DFS mode 9758 * 9759 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE 9760 */ 9761 enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode) 9762 { 9763 switch (mode) { 9764 case DFS_MODE_ENABLE: 9765 return ACS_DFS_MODE_ENABLE; 9766 break; 9767 case DFS_MODE_DISABLE: 9768 return ACS_DFS_MODE_DISABLE; 9769 break; 9770 case DFS_MODE_DEPRIORITIZE: 9771 return ACS_DFS_MODE_DEPRIORITIZE; 9772 break; 9773 default: 9774 hdd_err("ACS dfs mode is NONE"); 9775 return ACS_DFS_MODE_NONE; 9776 } 9777 } 9778 9779 /** 9780 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event 9781 * @hddctx: pointer to hdd context 9782 * @set_value: enable/disable 9783 * 9784 * When Host sends vendor command enable, FW will send *ONE* CA ind to 9785 * Host(even though it is duplicate). When Host send vendor command 9786 * disable,FW doesn't perform any action. Whenever any change in 9787 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host. 9788 * 9789 * return - 0 on success, appropriate error values on failure. 9790 */ 9791 int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value) 9792 { 9793 QDF_STATUS status; 9794 9795 if (0 != wlan_hdd_validate_context(hddctx)) { 9796 return -EAGAIN; 9797 } 9798 9799 if (!hddctx->config->goptimize_chan_avoid_event) { 9800 hdd_warn("goptimize_chan_avoid_event ini param disabled"); 9801 return -EINVAL; 9802 } 9803 9804 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value); 9805 if (!QDF_IS_STATUS_SUCCESS(status)) { 9806 hdd_err("Failed to send chan avoid command to SME"); 9807 return -EINVAL; 9808 } 9809 return 0; 9810 } 9811 9812 /* Register the module init/exit functions */ 9813 module_init(hdd_module_init); 9814 module_exit(hdd_module_exit); 9815 9816 MODULE_LICENSE("Dual BSD/GPL"); 9817 MODULE_AUTHOR("Qualcomm Atheros, Inc."); 9818 MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER"); 9819 9820 module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode, 9821 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 9822 9823 module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath, 9824 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 9825 9826 module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH); 9827 9828 module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH); 9829 9830 module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH); 9831