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: cds_api.c 30 * 31 * Connectivity driver services APIs 32 */ 33 34 #include <cds_mq.h> 35 #include "cds_sched.h" 36 #include <cds_api.h> 37 #include "sir_types.h" 38 #include "sir_api.h" 39 #include "sir_mac_prot_def.h" 40 #include "sme_api.h" 41 #include "mac_init_api.h" 42 #include "wlan_qct_sys.h" 43 #include "i_cds_packet.h" 44 #include "cds_reg_service.h" 45 #include "wma_types.h" 46 #include "wlan_hdd_main.h" 47 #include <linux/vmalloc.h> 48 49 #include "pld_common.h" 50 #include "sap_api.h" 51 #include "qdf_trace.h" 52 #include "bmi.h" 53 #include "ol_fw.h" 54 #include "ol_if_athvar.h" 55 #include "hif.h" 56 #include "cds_concurrency.h" 57 #include "cds_utils.h" 58 #include "wlan_logging_sock_svc.h" 59 #include "wma.h" 60 #include "pktlog_ac.h" 61 #include "wlan_hdd_ipa.h" 62 63 #include <cdp_txrx_cmn_reg.h> 64 #include <cdp_txrx_cfg.h> 65 #include <cdp_txrx_misc.h> 66 #include <dispatcher_init_deinit.h> 67 /* Preprocessor Definitions and Constants */ 68 69 /* Maximum number of cds message queue get wrapper failures to cause panic */ 70 #define CDS_WRAPPER_MAX_FAIL_COUNT (CDS_CORE_MAX_MESSAGES * 3) 71 72 /* Data definitions */ 73 static cds_context_type g_cds_context; 74 static p_cds_contextType gp_cds_context; 75 static struct __qdf_device g_qdf_ctx; 76 77 /* Debug variable to detect MC thread stuck */ 78 static atomic_t cds_wrapper_empty_count; 79 80 static uint8_t cds_multicast_logging; 81 82 static struct ol_if_ops dp_ol_if_ops = { 83 .peer_set_default_routing = wma_peer_set_default_routing, 84 .peer_rx_reorder_queue_setup = wma_peer_rx_reorder_queue_setup, 85 .peer_rx_reorder_queue_remove = wma_peer_rx_reorder_queue_remove, 86 /* TODO: Add any other control path calls required to OL_IF/WMA layer */ 87 }; 88 89 void cds_sys_probe_thread_cback(void *pUserData); 90 91 /** 92 * cds_init() - Initialize CDS 93 * 94 * This function allocates the resource required for CDS, but does not 95 * initialize all the members. This overall initialization will happen at 96 * cds_open(). 97 * 98 * Return: Global context on success and NULL on failure. 99 */ 100 v_CONTEXT_t cds_init(void) 101 { 102 qdf_mc_timer_manager_init(); 103 qdf_mem_init(); 104 105 gp_cds_context = &g_cds_context; 106 107 gp_cds_context->qdf_ctx = &g_qdf_ctx; 108 qdf_mem_zero(&g_qdf_ctx, sizeof(g_qdf_ctx)); 109 110 qdf_trace_spin_lock_init(); 111 112 #if defined(TRACE_RECORD) 113 qdf_trace_init(); 114 #endif 115 qdf_register_debugcb_init(); 116 117 cds_ssr_protect_init(); 118 119 return gp_cds_context; 120 } 121 122 /** 123 * cds_deinit() - Deinitialize CDS 124 * 125 * This function frees the CDS resources 126 */ 127 void cds_deinit(void) 128 { 129 if (gp_cds_context == NULL) 130 return; 131 132 qdf_mc_timer_manager_exit(); 133 qdf_mem_exit(); 134 135 gp_cds_context->qdf_ctx = NULL; 136 gp_cds_context = NULL; 137 138 qdf_mem_zero(&g_cds_context, sizeof(g_cds_context)); 139 return; 140 } 141 142 #ifdef FEATURE_WLAN_DIAG_SUPPORT 143 /** 144 * cds_tdls_tx_rx_mgmt_event()- send tdls mgmt rx tx event 145 * @event_id: event id 146 * @tx_rx: tx or rx 147 * @type: type of frame 148 * @action_sub_type: action frame type 149 * @peer_mac: peer mac 150 * 151 * This Function sends tdls mgmt rx tx diag event 152 * 153 * Return: void. 154 */ 155 void cds_tdls_tx_rx_mgmt_event(uint8_t event_id, uint8_t tx_rx, 156 uint8_t type, uint8_t action_sub_type, uint8_t *peer_mac) 157 { 158 WLAN_HOST_DIAG_EVENT_DEF(tdls_tx_rx_mgmt, 159 struct host_event_tdls_tx_rx_mgmt); 160 161 tdls_tx_rx_mgmt.event_id = event_id; 162 tdls_tx_rx_mgmt.tx_rx = tx_rx; 163 tdls_tx_rx_mgmt.type = type; 164 tdls_tx_rx_mgmt.action_sub_type = action_sub_type; 165 qdf_mem_copy(tdls_tx_rx_mgmt.peer_mac, 166 peer_mac, CDS_MAC_ADDRESS_LEN); 167 WLAN_HOST_DIAG_EVENT_REPORT(&tdls_tx_rx_mgmt, 168 EVENT_WLAN_TDLS_TX_RX_MGMT); 169 } 170 #endif 171 172 /** 173 * cds_cdp_cfg_attach() - attach data path config module 174 * @cds_cfg: generic platform level config instance 175 * 176 * Return: none 177 */ 178 static void cds_cdp_cfg_attach(struct cds_config_info *cds_cfg) 179 { 180 struct txrx_pdev_cfg_param_t cdp_cfg = {0}; 181 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 182 183 cdp_cfg.is_full_reorder_offload = cds_cfg->reorder_offload; 184 cdp_cfg.is_uc_offload_enabled = cds_cfg->uc_offload_enabled; 185 cdp_cfg.uc_tx_buffer_count = cds_cfg->uc_txbuf_count; 186 cdp_cfg.uc_tx_buffer_size = cds_cfg->uc_txbuf_size; 187 cdp_cfg.uc_rx_indication_ring_count = cds_cfg->uc_rxind_ringcount; 188 cdp_cfg.uc_tx_partition_base = cds_cfg->uc_tx_partition_base; 189 cdp_cfg.enable_rxthread = cds_cfg->enable_rxthread; 190 cdp_cfg.ip_tcp_udp_checksum_offload = 191 cds_cfg->ip_tcp_udp_checksum_offload; 192 cdp_cfg.ce_classify_enabled = cds_cfg->ce_classify_enabled; 193 194 gp_cds_context->cfg_ctx = cdp_cfg_attach(soc, gp_cds_context->qdf_ctx, 195 (void *)(&cdp_cfg)); 196 if (!gp_cds_context->cfg_ctx) { 197 WMA_LOGP("%s: failed to init cfg handle", __func__); 198 return; 199 } 200 201 /* Configure Receive flow steering */ 202 cdp_cfg_set_flow_steering(soc, &gp_cds_context->cfg_ctx, 203 cds_cfg->flow_steering_enabled); 204 205 cdp_cfg_set_flow_control_parameters(soc, &gp_cds_context->cfg_ctx, 206 (void *)cds_cfg); 207 208 /* adjust the cfg_ctx default value based on setting */ 209 cdp_cfg_set_rx_fwd_disabled(soc, gp_cds_context->cfg_ctx, 210 (uint8_t) cds_cfg->ap_disable_intrabss_fwd); 211 212 /* 213 * adjust the packet log enable default value 214 * based on CFG INI setting 215 */ 216 cdp_cfg_set_packet_log_enabled(soc, gp_cds_context->cfg_ctx, 217 (uint8_t)cds_is_packet_log_enabled()); 218 } 219 220 /** 221 * cds_open() - open the CDS Module 222 * 223 * cds_open() function opens the CDS Scheduler 224 * Upon successful initialization: 225 * - All CDS submodules should have been initialized 226 * 227 * - The CDS scheduler should have opened 228 * 229 * - All the WLAN SW components should have been opened. This includes 230 * SYS, MAC, SME, WMA and TL. 231 * 232 * Return: QDF status 233 */ 234 QDF_STATUS cds_open(void) 235 { 236 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 237 int iter = 0; 238 tSirRetStatus sirStatus = eSIR_SUCCESS; 239 struct cds_config_info *cds_cfg; 240 qdf_device_t qdf_ctx; 241 HTC_INIT_INFO htcInfo; 242 struct ol_context *ol_ctx; 243 struct hif_opaque_softc *scn; 244 void *HTCHandle; 245 hdd_context_t *pHddCtx; 246 cds_context_type *cds_ctx; 247 248 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, 249 "%s: Opening CDS", __func__); 250 251 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); 252 if (!cds_ctx) { 253 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 254 "%s: Trying to open CDS without a PreOpen", __func__); 255 QDF_ASSERT(0); 256 return QDF_STATUS_E_FAILURE; 257 } 258 259 /* Initialize the timer module */ 260 qdf_timer_module_init(); 261 262 /* Initialize bug reporting structure */ 263 cds_init_log_completion(); 264 265 /* Initialize the probe event */ 266 if (qdf_event_create(&gp_cds_context->ProbeEvent) != QDF_STATUS_SUCCESS) { 267 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 268 "%s: Unable to init probeEvent", __func__); 269 QDF_ASSERT(0); 270 return QDF_STATUS_E_FAILURE; 271 } 272 if (qdf_event_create(&(gp_cds_context->wmaCompleteEvent)) != 273 QDF_STATUS_SUCCESS) { 274 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 275 "%s: Unable to init wmaCompleteEvent", __func__); 276 QDF_ASSERT(0); 277 goto err_probe_event; 278 } 279 280 /* Initialize the free message queue */ 281 qdf_status = cds_mq_init(&gp_cds_context->freeVosMq); 282 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 283 /* Critical Error ... Cannot proceed further */ 284 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 285 "%s: Failed to initialize CDS free message queue", 286 __func__); 287 QDF_ASSERT(0); 288 goto err_wma_complete_event; 289 } 290 291 for (iter = 0; iter < CDS_CORE_MAX_MESSAGES; iter++) { 292 (gp_cds_context->aMsgWrappers[iter]).pVosMsg = 293 &(gp_cds_context->aMsgBuffers[iter]); 294 INIT_LIST_HEAD(&gp_cds_context->aMsgWrappers[iter].msgNode); 295 cds_mq_put(&gp_cds_context->freeVosMq, 296 &(gp_cds_context->aMsgWrappers[iter])); 297 } 298 299 pHddCtx = (hdd_context_t *) (gp_cds_context->pHDDContext); 300 if ((NULL == pHddCtx) || (NULL == pHddCtx->config)) { 301 /* Critical Error ... Cannot proceed further */ 302 cds_err("Hdd Context is Null"); 303 QDF_ASSERT(0); 304 goto err_msg_queue; 305 } 306 307 if (!QDF_IS_STATUS_SUCCESS(qdf_mutex_create( 308 &cds_ctx->qdf_conc_list_lock))) { 309 cds_err("Failed to init qdf_conc_list_lock"); 310 QDF_ASSERT(0); 311 goto err_msg_queue; 312 } 313 314 /* Now Open the CDS Scheduler */ 315 316 if (pHddCtx->driver_status == DRIVER_MODULES_UNINITIALIZED || 317 cds_is_driver_recovering()) { 318 qdf_status = cds_sched_open(gp_cds_context, 319 &gp_cds_context->qdf_sched, 320 sizeof(cds_sched_context)); 321 322 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 323 /* Critical Error ... Cannot proceed further */ 324 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 325 "%s: Failed to open CDS Scheduler", __func__); 326 QDF_ASSERT(0); 327 goto err_concurrency_lock; 328 } 329 } 330 331 scn = cds_get_context(QDF_MODULE_ID_HIF); 332 if (!scn) { 333 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 334 "%s: scn is null!", __func__); 335 goto err_sched_close; 336 } 337 338 cds_cfg = cds_get_ini_config(); 339 if (!cds_cfg) { 340 cds_err("Cds config is NULL"); 341 QDF_ASSERT(0); 342 goto err_sched_close; 343 } 344 hdd_enable_fastpath(pHddCtx->config, scn); 345 hdd_wlan_update_target_info(pHddCtx, scn); 346 347 ol_ctx = cds_get_context(QDF_MODULE_ID_BMI); 348 /* Initialize BMI and Download firmware */ 349 qdf_status = bmi_download_firmware(ol_ctx); 350 if (qdf_status != QDF_STATUS_SUCCESS) { 351 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 352 "BMI FIALED status:%d", qdf_status); 353 goto err_bmi_close; 354 } 355 htcInfo.pContext = ol_ctx; 356 htcInfo.TargetFailure = ol_target_failure; 357 htcInfo.TargetSendSuspendComplete = wma_target_suspend_acknowledge; 358 htcInfo.target_initial_wakeup_cb = wma_handle_initial_wake_up; 359 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 360 361 /* Create HTC */ 362 gp_cds_context->htc_ctx = 363 htc_create(scn, &htcInfo, qdf_ctx, cds_get_conparam()); 364 if (!gp_cds_context->htc_ctx) { 365 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 366 "%s: Failed to Create HTC", __func__); 367 goto err_bmi_close; 368 } 369 370 if (bmi_done(ol_ctx)) { 371 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 372 "%s: Failed to complete BMI phase", __func__); 373 goto err_htc_close; 374 } 375 376 /*Open the WMA module */ 377 qdf_status = wma_open(gp_cds_context, 378 hdd_update_tgt_cfg, 379 hdd_dfs_indicate_radar, cds_cfg); 380 381 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 382 /* Critical Error ... Cannot proceed further */ 383 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 384 "%s: Failed to open WMA module", __func__); 385 QDF_ASSERT(0); 386 goto err_htc_close; 387 } 388 389 /* Number of peers limit differs in each chip version. If peer max 390 * limit configured in ini exceeds more than supported, WMA adjusts 391 * and keeps correct limit in cds_cfg.max_station. So, make sure 392 * config entry pHddCtx->config->maxNumberOfPeers has adjusted value 393 */ 394 /* In FTM mode cds_cfg->max_stations will be zero. On updating same 395 * into hdd context config entry, leads to pe_open() to fail, if 396 * con_mode change happens from FTM mode to any other mode. 397 */ 398 if (DRIVER_TYPE_PRODUCTION == cds_cfg->driver_type) 399 pHddCtx->config->maxNumberOfPeers = cds_cfg->max_station; 400 401 HTCHandle = cds_get_context(QDF_MODULE_ID_HTC); 402 if (!HTCHandle) { 403 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 404 "%s: HTCHandle is null!", __func__); 405 goto err_wma_close; 406 } 407 if (htc_wait_target(HTCHandle)) { 408 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 409 "%s: Failed to complete BMI phase", __func__); 410 goto err_wma_close; 411 } 412 bmi_target_ready(scn, gp_cds_context->cfg_ctx); 413 /* Now proceed to open the MAC */ 414 415 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 416 "%s: target_type %d 8074:%d 6290:%d", 417 __func__, pHddCtx->target_type, 418 TARGET_TYPE_QCA8074, TARGET_TYPE_QCA6290); 419 420 if (TARGET_TYPE_QCA6290 == pHddCtx->target_type) 421 gp_cds_context->dp_soc = cdp_soc_attach(LITHIUM_DP, 422 gp_cds_context->pHIFContext, scn, 423 gp_cds_context->htc_ctx, gp_cds_context->qdf_ctx, 424 &dp_ol_if_ops); 425 else 426 gp_cds_context->dp_soc = cdp_soc_attach(MOB_DRV_LEGACY_DP, 427 gp_cds_context->pHIFContext, scn, 428 gp_cds_context->htc_ctx, gp_cds_context->qdf_ctx, 429 &dp_ol_if_ops); 430 431 cds_cdp_cfg_attach(cds_cfg); 432 433 /* UMA is supported in hardware for performing the 434 * frame translation 802.11 <-> 802.3 435 */ 436 cds_cfg->frame_xln_reqd = 1; 437 438 sirStatus = 439 mac_open(&(gp_cds_context->pMACContext), 440 gp_cds_context->pHDDContext, cds_cfg); 441 442 if (eSIR_SUCCESS != sirStatus) { 443 /* Critical Error ... Cannot proceed further */ 444 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 445 "%s: Failed to open MAC", __func__); 446 QDF_ASSERT(0); 447 goto err_wma_close; 448 } 449 450 /* Now proceed to open the SME */ 451 qdf_status = sme_open(gp_cds_context->pMACContext); 452 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 453 /* Critical Error ... Cannot proceed further */ 454 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 455 "%s: Failed to open SME", __func__); 456 QDF_ASSERT(0); 457 goto err_mac_close; 458 } 459 gp_cds_context->pdev_txrx_ctx = 460 cdp_pdev_attach(cds_get_context(QDF_MODULE_ID_SOC), 461 gp_cds_context->cfg_ctx, 462 gp_cds_context->htc_ctx, 463 gp_cds_context->qdf_ctx, 0); 464 if (!gp_cds_context->pdev_txrx_ctx) { 465 /* Critical Error ... Cannot proceed further */ 466 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 467 "%s: Failed to open TXRX", __func__); 468 QDF_ASSERT(0); 469 goto err_sme_close; 470 } 471 472 gp_cds_context->cdp_update_mac_id = cdp_update_mac_id; 473 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, 474 "%s: CDS successfully Opened", __func__); 475 476 dispatcher_psoc_open(); 477 478 return QDF_STATUS_SUCCESS; 479 480 err_sme_close: 481 sme_close(gp_cds_context->pMACContext); 482 483 err_mac_close: 484 mac_close(gp_cds_context->pMACContext); 485 486 err_wma_close: 487 wma_close(gp_cds_context); 488 489 wma_wmi_service_close(gp_cds_context); 490 491 err_htc_close: 492 if (gp_cds_context->htc_ctx) { 493 htc_destroy(gp_cds_context->htc_ctx); 494 gp_cds_context->htc_ctx = NULL; 495 } 496 497 err_bmi_close: 498 bmi_cleanup(ol_ctx); 499 500 err_sched_close: 501 cds_sched_close(gp_cds_context); 502 cds_shutdown_notifier_purge(); 503 504 err_concurrency_lock: 505 qdf_mutex_destroy(&cds_ctx->qdf_conc_list_lock); 506 507 err_msg_queue: 508 cds_mq_deinit(&gp_cds_context->freeVosMq); 509 510 err_wma_complete_event: 511 qdf_event_destroy(&gp_cds_context->wmaCompleteEvent); 512 513 err_probe_event: 514 qdf_event_destroy(&gp_cds_context->ProbeEvent); 515 516 return QDF_STATUS_E_FAILURE; 517 } /* cds_open() */ 518 519 /** 520 * cds_pre_enable() - pre enable cds 521 * @cds_context: CDS context 522 * 523 * Return: QDF status 524 */ 525 QDF_STATUS cds_pre_enable(v_CONTEXT_t cds_context) 526 { 527 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 528 p_cds_contextType p_cds_context = (p_cds_contextType) cds_context; 529 void *scn; 530 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 531 532 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO, "cds prestart"); 533 if (gp_cds_context != p_cds_context) { 534 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 535 "%s: Context mismatch", __func__); 536 QDF_ASSERT(0); 537 return QDF_STATUS_E_INVAL; 538 } 539 540 if (p_cds_context->pMACContext == NULL) { 541 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 542 "%s: MAC NULL context", __func__); 543 QDF_ASSERT(0); 544 return QDF_STATUS_E_INVAL; 545 } 546 547 if (p_cds_context->pWMAContext == NULL) { 548 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 549 "%s: WMA NULL context", __func__); 550 QDF_ASSERT(0); 551 return QDF_STATUS_E_INVAL; 552 } 553 554 scn = cds_get_context(QDF_MODULE_ID_HIF); 555 if (!scn) { 556 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 557 "%s: scn is null!", __func__); 558 return QDF_STATUS_E_FAILURE; 559 } 560 561 /* call Packetlog connect service */ 562 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam() && 563 QDF_GLOBAL_EPPING_MODE != cds_get_conparam()) 564 cdp_pkt_log_con_service(soc, 565 gp_cds_context->pdev_txrx_ctx, scn); 566 567 /* Reset wma wait event */ 568 qdf_event_reset(&gp_cds_context->wmaCompleteEvent); 569 570 /*call WMA pre start */ 571 qdf_status = wma_pre_start(gp_cds_context); 572 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 573 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_FATAL, 574 "Failed to WMA prestart"); 575 QDF_ASSERT(0); 576 return QDF_STATUS_E_FAILURE; 577 } 578 579 /* Need to update time out of complete */ 580 qdf_status = qdf_wait_single_event(&gp_cds_context->wmaCompleteEvent, 581 CDS_WMA_TIMEOUT); 582 if (qdf_status != QDF_STATUS_SUCCESS) { 583 if (qdf_status == QDF_STATUS_E_TIMEOUT) { 584 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 585 "%s: Timeout occurred before WMA complete", 586 __func__); 587 } else { 588 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 589 "%s: wma_pre_start reporting other error", 590 __func__); 591 } 592 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 593 "%s: Test MC thread by posting a probe message to SYS", 594 __func__); 595 wlan_sys_probe(); 596 597 QDF_ASSERT(0); 598 return QDF_STATUS_E_FAILURE; 599 } 600 601 qdf_status = htc_start(gp_cds_context->htc_ctx); 602 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 603 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_FATAL, 604 "Failed to Start HTC"); 605 QDF_ASSERT(0); 606 return QDF_STATUS_E_FAILURE; 607 } 608 qdf_status = wma_wait_for_ready_event(gp_cds_context->pWMAContext); 609 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 610 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 611 "Failed to get ready event from target firmware"); 612 /* 613 * Panic only if recovery is disabled, else return failure so 614 * that driver load can fail gracefully. We cannot trigger self 615 * recovery here because driver is not fully loaded yet. 616 */ 617 if (!cds_is_self_recovery_enabled()) 618 QDF_BUG(0); 619 620 htc_stop(gp_cds_context->htc_ctx); 621 return QDF_STATUS_E_FAILURE; 622 } 623 624 if (cdp_pdev_post_attach(soc, gp_cds_context->pdev_txrx_ctx)) { 625 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 626 "Failed to attach pdev"); 627 htc_stop(gp_cds_context->htc_ctx); 628 QDF_ASSERT(0); 629 return QDF_STATUS_E_FAILURE; 630 } 631 632 return QDF_STATUS_SUCCESS; 633 } 634 635 /** 636 * cds_enable() - start/enable cds module 637 * @cds_context: CDS context 638 * 639 * Return: QDF status 640 */ 641 QDF_STATUS cds_enable(v_CONTEXT_t cds_context) 642 { 643 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 644 tSirRetStatus sirStatus = eSIR_SUCCESS; 645 p_cds_contextType p_cds_context = (p_cds_contextType) cds_context; 646 tHalMacStartParameters halStartParams; 647 648 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 649 "%s: Starting Libra SW", __func__); 650 651 /* We support only one instance for now ... */ 652 if (gp_cds_context != p_cds_context) { 653 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 654 "%s: mismatch in context", __func__); 655 return QDF_STATUS_E_FAILURE; 656 } 657 658 if ((p_cds_context->pWMAContext == NULL) || 659 (p_cds_context->pMACContext == NULL)) { 660 if (p_cds_context->pWMAContext == NULL) 661 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 662 "%s: WMA NULL context", __func__); 663 else 664 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 665 "%s: MAC NULL context", __func__); 666 667 return QDF_STATUS_E_FAILURE; 668 } 669 670 /* Start the wma */ 671 qdf_status = wma_start(p_cds_context); 672 if (qdf_status != QDF_STATUS_SUCCESS) { 673 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 674 "%s: Failed to start wma", __func__); 675 return QDF_STATUS_E_FAILURE; 676 } 677 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 678 "%s: wma correctly started", __func__); 679 680 /* Start the MAC */ 681 qdf_mem_zero(&halStartParams, 682 sizeof(tHalMacStartParameters)); 683 684 /* Start the MAC */ 685 sirStatus = 686 mac_start(p_cds_context->pMACContext, &halStartParams); 687 688 if (eSIR_SUCCESS != sirStatus) { 689 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 690 "%s: Failed to start MAC", __func__); 691 goto err_wma_stop; 692 } 693 694 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 695 "%s: MAC correctly started", __func__); 696 697 /* START SME */ 698 qdf_status = sme_start(p_cds_context->pMACContext); 699 700 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 701 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 702 "%s: Failed to start SME", __func__); 703 goto err_mac_stop; 704 } 705 706 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 707 "%s: SME correctly started", __func__); 708 709 if (cdp_soc_attach_target(cds_get_context(QDF_MODULE_ID_SOC))) { 710 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 711 "%s: Failed to attach soc target", __func__); 712 goto err_sme_stop; 713 } 714 715 if (cdp_pdev_attach_target(cds_get_context(QDF_MODULE_ID_SOC), 716 cds_get_context(QDF_MODULE_ID_TXRX))) { 717 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 718 "%s: Failed to attach pdev target", __func__); 719 goto err_soc_target_detach; 720 } 721 722 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 723 "TL correctly started"); 724 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 725 "%s: CDS Start is successful!!", __func__); 726 727 dispatcher_psoc_enable(); 728 729 return QDF_STATUS_SUCCESS; 730 731 err_soc_target_detach: 732 /* NOOP */ 733 734 err_sme_stop: 735 sme_stop(p_cds_context->pMACContext, HAL_STOP_TYPE_SYS_RESET); 736 737 err_mac_stop: 738 mac_stop(p_cds_context->pMACContext, HAL_STOP_TYPE_SYS_RESET); 739 740 err_wma_stop: 741 qdf_event_reset(&(gp_cds_context->wmaCompleteEvent)); 742 qdf_status = wma_stop(p_cds_context, HAL_STOP_TYPE_RF_KILL); 743 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 744 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 745 "%s: Failed to stop wma", __func__); 746 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 747 wma_setneedshutdown(cds_context); 748 } else { 749 qdf_status = 750 qdf_wait_single_event(&(gp_cds_context->wmaCompleteEvent), 751 CDS_WMA_TIMEOUT); 752 if (qdf_status != QDF_STATUS_SUCCESS) { 753 if (qdf_status == QDF_STATUS_E_TIMEOUT) { 754 QDF_TRACE(QDF_MODULE_ID_QDF, 755 QDF_TRACE_LEVEL_FATAL, 756 "%s: Timeout occurred before WMA_stop complete", 757 __func__); 758 } else { 759 QDF_TRACE(QDF_MODULE_ID_QDF, 760 QDF_TRACE_LEVEL_FATAL, 761 "%s: WMA_stop reporting other error", 762 __func__); 763 } 764 QDF_ASSERT(0); 765 wma_setneedshutdown(cds_context); 766 } 767 } 768 769 return QDF_STATUS_E_FAILURE; 770 } /* cds_enable() */ 771 772 /** 773 * cds_disable() - stop/disable cds module 774 * @cds_context: CDS context 775 * 776 * Return: QDF status 777 */ 778 QDF_STATUS cds_disable(v_CONTEXT_t cds_context) 779 { 780 QDF_STATUS qdf_status; 781 void *handle; 782 783 /* PSOC disable for all new components. It needs to happen before 784 * target is PDEV suspended such that a component can abort all its 785 * ongoing transaction with FW. Always keep it before wma_stop() as 786 * wma_stop() does target PDEV suspend. 787 */ 788 dispatcher_psoc_disable(); 789 790 791 qdf_status = wma_stop(cds_context, HAL_STOP_TYPE_RF_KILL); 792 793 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 794 cds_err("Failed to stop wma"); 795 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 796 wma_setneedshutdown(cds_context); 797 } 798 799 handle = cds_get_context(QDF_MODULE_ID_PE); 800 if (!handle) { 801 cds_err("Invalid PE context return!"); 802 return QDF_STATUS_E_INVAL; 803 } 804 qdf_status = sme_stop(handle, HAL_STOP_TYPE_SYS_DEEP_SLEEP); 805 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 806 cds_err("Failed to stop SME: %d", qdf_status); 807 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 808 } 809 qdf_status = mac_stop(handle, HAL_STOP_TYPE_SYS_DEEP_SLEEP); 810 811 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 812 cds_err("Failed to stop MAC"); 813 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 814 } 815 816 return qdf_status; 817 } 818 819 #ifdef HIF_USB 820 static inline void cds_suspend_target(tp_wma_handle wma_handle) 821 { 822 QDF_STATUS status; 823 /* Suspend the target and disable interrupt */ 824 status = wma_suspend_target(wma_handle, 0); 825 if (status) 826 cds_err("Failed to suspend target, status = %d", status); 827 } 828 #else 829 static inline void cds_suspend_target(tp_wma_handle wma_handle) 830 { 831 QDF_STATUS status; 832 /* Suspend the target and disable interrupt */ 833 status = wma_suspend_target(wma_handle, 1); 834 if (status) 835 cds_err("Failed to suspend target, status = %d", status); 836 } 837 #endif /* HIF_USB */ 838 839 /** 840 * cds_post_disable() - post disable cds module 841 * @cds_context: CDS context 842 * 843 * Return: QDF status 844 */ 845 QDF_STATUS cds_post_disable(v_CONTEXT_t cds_context) 846 { 847 tp_wma_handle wma_handle; 848 struct hif_opaque_softc *hif_ctx; 849 wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 850 if (!wma_handle) { 851 cds_err("Failed to get wma_handle!"); 852 return QDF_STATUS_E_INVAL; 853 } 854 855 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 856 if (!hif_ctx) { 857 cds_err("Failed to get hif_handle!"); 858 return QDF_STATUS_E_INVAL; 859 } 860 861 /* 862 * With new state machine changes cds_close can be invoked without 863 * cds_disable. So, send the following clean up prerequisites to fw, 864 * So Fw and host are in sync for cleanup indication: 865 * - Send PDEV_SUSPEND indication to firmware 866 * - Disable HIF Interrupts. 867 * - Clean up CE tasklets. 868 */ 869 870 cds_info("send denint sequence to firmware"); 871 if (!cds_is_driver_recovering()) 872 cds_suspend_target(wma_handle); 873 hif_disable_isr(hif_ctx); 874 hif_reset_soc(hif_ctx); 875 876 return QDF_STATUS_SUCCESS; 877 } 878 879 /** 880 * cds_close() - close cds module 881 * @cds_context: CDS context 882 * 883 * This API allows user to close modules registered 884 * with connectivity device services. 885 * 886 * Return: QDF status 887 */ 888 QDF_STATUS cds_close(v_CONTEXT_t cds_context) 889 { 890 QDF_STATUS qdf_status; 891 892 qdf_status = wma_wmi_work_close(cds_context); 893 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 894 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 895 "%s: Failed to close wma_wmi_work", __func__); 896 QDF_ASSERT(0); 897 } 898 899 if (gp_cds_context->htc_ctx) { 900 htc_stop(gp_cds_context->htc_ctx); 901 htc_destroy(gp_cds_context->htc_ctx); 902 gp_cds_context->htc_ctx = NULL; 903 } 904 905 cdp_pdev_detach(cds_get_context(QDF_MODULE_ID_SOC), 906 gp_cds_context->pdev_txrx_ctx, 1); 907 cds_free_context(cds_context, QDF_MODULE_ID_TXRX, 908 gp_cds_context->pdev_txrx_ctx); 909 910 qdf_status = sme_close(((p_cds_contextType) cds_context)->pMACContext); 911 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 912 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 913 "%s: Failed to close SME", __func__); 914 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 915 } 916 917 qdf_status = mac_close(((p_cds_contextType) cds_context)->pMACContext); 918 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 919 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 920 "%s: Failed to close MAC", __func__); 921 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 922 } 923 924 ((p_cds_contextType) cds_context)->pMACContext = NULL; 925 926 if (true == wma_needshutdown(cds_context)) { 927 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 928 "%s: Failed to shutdown wma", __func__); 929 } else { 930 qdf_status = wma_close(cds_context); 931 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 932 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 933 "%s: Failed to close wma", __func__); 934 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 935 } 936 } 937 938 qdf_status = wma_wmi_service_close(cds_context); 939 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 940 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 941 "%s: Failed to close wma_wmi_service", __func__); 942 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 943 } 944 945 cds_mq_deinit(&((p_cds_contextType) cds_context)->freeVosMq); 946 947 qdf_status = qdf_event_destroy(&gp_cds_context->wmaCompleteEvent); 948 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 949 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 950 "%s: failed to destroy wmaCompleteEvent", __func__); 951 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 952 } 953 954 qdf_status = qdf_event_destroy(&gp_cds_context->ProbeEvent); 955 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 956 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 957 "%s: failed to destroy ProbeEvent", __func__); 958 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 959 } 960 961 if (!QDF_IS_STATUS_SUCCESS(qdf_mutex_destroy( 962 &gp_cds_context->qdf_conc_list_lock))) { 963 cds_err("Failed to destroy qdf_conc_list_lock"); 964 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 965 } 966 967 cds_shutdown_notifier_purge(); 968 969 cds_deinit_log_completion(); 970 cds_deinit_ini_config(); 971 qdf_timer_module_deinit(); 972 973 dispatcher_psoc_close(); 974 975 return QDF_STATUS_SUCCESS; 976 } 977 978 void cds_flush_cache_rx_queue(void) 979 { 980 uint8_t sta_id; 981 void *peer; 982 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX); 983 984 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) { 985 peer = cdp_peer_find_by_local_id( 986 cds_get_context(QDF_MODULE_ID_SOC), 987 pdev, sta_id); 988 if (!peer) 989 continue; 990 cdp_flush_rx_frames(cds_get_context(QDF_MODULE_ID_SOC), 991 peer, 1); 992 } 993 return; 994 } 995 996 997 /** 998 * cds_get_context() - get context data area 999 * 1000 * @moduleId: ID of the module who's context data is being retrived. 1001 * 1002 * Each module in the system has a context / data area that is allocated 1003 * and managed by CDS. This API allows any user to get a pointer to its 1004 * allocated context data area from the CDS global context. 1005 * 1006 * Return: pointer to the context data area of the module ID 1007 * specified, or NULL if the context data is not allocated for 1008 * the module ID specified 1009 */ 1010 void *cds_get_context(QDF_MODULE_ID moduleId) 1011 { 1012 void *pModContext = NULL; 1013 1014 if (gp_cds_context == NULL) { 1015 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1016 "%s: cds context pointer is null", __func__); 1017 return NULL; 1018 } 1019 1020 switch (moduleId) { 1021 case QDF_MODULE_ID_HDD: 1022 { 1023 pModContext = gp_cds_context->pHDDContext; 1024 break; 1025 } 1026 1027 case QDF_MODULE_ID_SME: 1028 case QDF_MODULE_ID_PE: 1029 { 1030 /* In all these cases, we just return the MAC Context */ 1031 pModContext = gp_cds_context->pMACContext; 1032 break; 1033 } 1034 1035 case QDF_MODULE_ID_WMA: 1036 { 1037 /* For wma module */ 1038 pModContext = gp_cds_context->pWMAContext; 1039 break; 1040 } 1041 1042 case QDF_MODULE_ID_QDF: 1043 { 1044 /* For SYS this is CDS itself */ 1045 pModContext = gp_cds_context; 1046 break; 1047 } 1048 1049 case QDF_MODULE_ID_HIF: 1050 { 1051 pModContext = gp_cds_context->pHIFContext; 1052 break; 1053 } 1054 1055 case QDF_MODULE_ID_HTC: 1056 { 1057 pModContext = gp_cds_context->htc_ctx; 1058 break; 1059 } 1060 1061 case QDF_MODULE_ID_QDF_DEVICE: 1062 { 1063 pModContext = gp_cds_context->qdf_ctx; 1064 break; 1065 } 1066 1067 case QDF_MODULE_ID_BMI: 1068 { 1069 pModContext = gp_cds_context->g_ol_context; 1070 break; 1071 } 1072 1073 case QDF_MODULE_ID_TXRX: 1074 { 1075 pModContext = gp_cds_context->pdev_txrx_ctx; 1076 break; 1077 } 1078 1079 case QDF_MODULE_ID_CFG: 1080 { 1081 pModContext = gp_cds_context->cfg_ctx; 1082 break; 1083 } 1084 1085 case QDF_MODULE_ID_SOC: 1086 { 1087 pModContext = gp_cds_context->dp_soc; 1088 break; 1089 } 1090 1091 default: 1092 { 1093 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1094 "%s: Module ID %i does not have its context maintained by CDS", 1095 __func__, moduleId); 1096 QDF_ASSERT(0); 1097 return NULL; 1098 } 1099 } 1100 1101 if (pModContext == NULL) { 1102 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1103 "%s: Module ID %i context is Null", __func__, 1104 moduleId); 1105 } 1106 1107 return pModContext; 1108 } /* cds_get_context() */ 1109 1110 /** 1111 * cds_get_global_context() - get CDS global Context 1112 * 1113 * This API allows any user to get the CDS Global Context pointer from a 1114 * module context data area. 1115 * 1116 * Return: pointer to the CDS global context, NULL if the function is 1117 * unable to retreive the CDS context. 1118 */ 1119 v_CONTEXT_t cds_get_global_context(void) 1120 { 1121 if (gp_cds_context == NULL) { 1122 /* 1123 * To avoid recursive call, this should not change to 1124 * QDF_TRACE(). 1125 */ 1126 pr_err("%s: global cds context is NULL", __func__); 1127 } 1128 1129 return gp_cds_context; 1130 } /* cds_get_global_context() */ 1131 1132 /** 1133 * cds_get_driver_state() - Get current driver state 1134 * 1135 * This API returns current driver state stored in global context. 1136 * 1137 * Return: Driver state enum 1138 */ 1139 enum cds_driver_state cds_get_driver_state(void) 1140 { 1141 if (gp_cds_context == NULL) { 1142 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1143 "%s: global cds context is NULL", __func__); 1144 1145 return CDS_DRIVER_STATE_UNINITIALIZED; 1146 } 1147 1148 return gp_cds_context->driver_state; 1149 } 1150 1151 /** 1152 * cds_set_driver_state() - Set current driver state 1153 * @state: Driver state to be set to. 1154 * 1155 * This API sets driver state to state. This API only sets the state and doesn't 1156 * clear states, please make sure to use cds_clear_driver_state to clear any 1157 * state if required. 1158 * 1159 * Return: None 1160 */ 1161 void cds_set_driver_state(enum cds_driver_state state) 1162 { 1163 if (gp_cds_context == NULL) { 1164 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1165 "%s: global cds context is NULL: %x", __func__, 1166 state); 1167 1168 return; 1169 } 1170 1171 gp_cds_context->driver_state |= state; 1172 } 1173 1174 /** 1175 * cds_clear_driver_state() - Clear current driver state 1176 * @state: Driver state to be cleared. 1177 * 1178 * This API clears driver state. This API only clears the state, please make 1179 * sure to use cds_set_driver_state to set any new states. 1180 * 1181 * Return: None 1182 */ 1183 void cds_clear_driver_state(enum cds_driver_state state) 1184 { 1185 if (gp_cds_context == NULL) { 1186 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1187 "%s: global cds context is NULL: %x", __func__, 1188 state); 1189 1190 return; 1191 } 1192 1193 gp_cds_context->driver_state &= ~state; 1194 } 1195 1196 /** 1197 * cds_alloc_context() - allocate a context within the CDS global Context 1198 * @p_cds_context: pointer to the global Vos context 1199 * @moduleId: module ID who's context area is being allocated. 1200 * @ppModuleContext: pointer to location where the pointer to the 1201 * allocated context is returned. Note this output pointer 1202 * is valid only if the API returns QDF_STATUS_SUCCESS 1203 * @param size: size of the context area to be allocated. 1204 * 1205 * This API allows any user to allocate a user context area within the 1206 * CDS Global Context. 1207 * 1208 * Return: QDF status 1209 */ 1210 QDF_STATUS cds_alloc_context(void *p_cds_context, QDF_MODULE_ID moduleID, 1211 void **ppModuleContext, uint32_t size) 1212 { 1213 void **pGpModContext = NULL; 1214 1215 if (p_cds_context == NULL) { 1216 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1217 "%s: cds context is null", __func__); 1218 return QDF_STATUS_E_FAILURE; 1219 } 1220 1221 if ((gp_cds_context != p_cds_context) || (ppModuleContext == NULL)) { 1222 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1223 "%s: context mismatch or null param passed", 1224 __func__); 1225 return QDF_STATUS_E_FAILURE; 1226 } 1227 1228 switch (moduleID) { 1229 case QDF_MODULE_ID_WMA: 1230 { 1231 pGpModContext = &(gp_cds_context->pWMAContext); 1232 break; 1233 } 1234 1235 case QDF_MODULE_ID_HIF: 1236 { 1237 pGpModContext = &(gp_cds_context->pHIFContext); 1238 break; 1239 } 1240 1241 case QDF_MODULE_ID_BMI: 1242 { 1243 pGpModContext = &(gp_cds_context->g_ol_context); 1244 break; 1245 } 1246 1247 case QDF_MODULE_ID_EPPING: 1248 case QDF_MODULE_ID_SME: 1249 case QDF_MODULE_ID_PE: 1250 case QDF_MODULE_ID_HDD: 1251 case QDF_MODULE_ID_HDD_SOFTAP: 1252 default: 1253 { 1254 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1255 "%s: Module ID %i " 1256 "does not have its context allocated by CDS", 1257 __func__, moduleID); 1258 QDF_ASSERT(0); 1259 return QDF_STATUS_E_INVAL; 1260 } 1261 } 1262 1263 if (NULL != *pGpModContext) { 1264 /* Context has already been allocated! 1265 * Prevent double allocation 1266 */ 1267 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1268 "%s: Module ID %i context has already been allocated", 1269 __func__, moduleID); 1270 return QDF_STATUS_E_EXISTS; 1271 } 1272 1273 /* Dynamically allocate the context for module */ 1274 1275 *ppModuleContext = qdf_mem_malloc(size); 1276 1277 if (*ppModuleContext == NULL) { 1278 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1279 "%s: Failed to " "allocate Context for module ID %i", 1280 __func__, moduleID); 1281 QDF_ASSERT(0); 1282 return QDF_STATUS_E_NOMEM; 1283 } 1284 1285 *pGpModContext = *ppModuleContext; 1286 1287 return QDF_STATUS_SUCCESS; 1288 } /* cds_alloc_context() */ 1289 1290 /** 1291 * cds_set_context() - API to set context in global CDS Context 1292 * @module_id: Module ID 1293 * @context: Pointer to the Module Context 1294 * 1295 * API to set a MODULE Context in global CDS Context 1296 * 1297 * Return: QDF_STATUS 1298 */ 1299 QDF_STATUS cds_set_context(QDF_MODULE_ID module_id, void *context) 1300 { 1301 p_cds_contextType p_cds_context = cds_get_global_context(); 1302 1303 if (!p_cds_context) { 1304 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1305 "cds context is Invalid"); 1306 return QDF_STATUS_NOT_INITIALIZED; 1307 } 1308 1309 switch (module_id) { 1310 case QDF_MODULE_ID_HIF: 1311 p_cds_context->pHIFContext = context; 1312 break; 1313 default: 1314 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1315 "%s: Module ID %i does not have its context managed by CDS", 1316 __func__, module_id); 1317 QDF_ASSERT(0); 1318 return QDF_STATUS_E_INVAL; 1319 } 1320 1321 return QDF_STATUS_SUCCESS; 1322 } 1323 1324 /** 1325 * cds_free_context() - free an allocated context within the 1326 * CDS global Context 1327 * @p_cds_context: pointer to the global Vos context 1328 * @moduleId: module ID who's context area is being free 1329 * @pModuleContext: pointer to module context area to be free'd. 1330 * 1331 * This API allows a user to free the user context area within the 1332 * CDS Global Context. 1333 * 1334 * Return: QDF status 1335 */ 1336 QDF_STATUS cds_free_context(void *p_cds_context, QDF_MODULE_ID moduleID, 1337 void *pModuleContext) 1338 { 1339 void **pGpModContext = NULL; 1340 1341 if ((p_cds_context == NULL) || (gp_cds_context != p_cds_context) || 1342 (pModuleContext == NULL)) { 1343 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1344 "%s: Null params or context mismatch", __func__); 1345 return QDF_STATUS_E_FAILURE; 1346 } 1347 1348 switch (moduleID) { 1349 case QDF_MODULE_ID_WMA: 1350 { 1351 pGpModContext = &(gp_cds_context->pWMAContext); 1352 break; 1353 } 1354 1355 case QDF_MODULE_ID_HIF: 1356 { 1357 pGpModContext = &(gp_cds_context->pHIFContext); 1358 break; 1359 } 1360 1361 case QDF_MODULE_ID_TXRX: 1362 { 1363 pGpModContext = &(gp_cds_context->pdev_txrx_ctx); 1364 break; 1365 } 1366 1367 case QDF_MODULE_ID_BMI: 1368 { 1369 pGpModContext = &(gp_cds_context->g_ol_context); 1370 break; 1371 } 1372 1373 case QDF_MODULE_ID_EPPING: 1374 case QDF_MODULE_ID_HDD: 1375 case QDF_MODULE_ID_SME: 1376 case QDF_MODULE_ID_PE: 1377 case QDF_MODULE_ID_HDD_SOFTAP: 1378 default: 1379 { 1380 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1381 "%s: Module ID %i " 1382 "does not have its context allocated by CDS", 1383 __func__, moduleID); 1384 QDF_ASSERT(0); 1385 return QDF_STATUS_E_INVAL; 1386 } 1387 } 1388 1389 if (NULL == *pGpModContext) { 1390 /* Context has not been allocated or freed already! */ 1391 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1392 "%s: Module ID %i " 1393 "context has not been allocated or freed already", 1394 __func__, moduleID); 1395 return QDF_STATUS_E_FAILURE; 1396 } 1397 1398 if (*pGpModContext != pModuleContext) { 1399 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1400 "%s: pGpModContext != pModuleContext", __func__); 1401 return QDF_STATUS_E_FAILURE; 1402 } 1403 1404 if (pModuleContext != NULL) 1405 qdf_mem_free(pModuleContext); 1406 1407 *pGpModContext = NULL; 1408 1409 return QDF_STATUS_SUCCESS; 1410 } /* cds_free_context() */ 1411 1412 /** 1413 * cds_mq_post_message_by_priority() - posts message using priority 1414 * to message queue 1415 * @msgQueueId: message queue id 1416 * @pMsg: message to be posted 1417 * @is_high_priority: wheather message is high priority 1418 * 1419 * This function is used to post high priority message to message queue 1420 * 1421 * Return: QDF_STATUS_SUCCESS on success 1422 * QDF_STATUS_E_FAILURE on failure 1423 * QDF_STATUS_E_RESOURCES on resource allocation failure 1424 */ 1425 QDF_STATUS cds_mq_post_message_by_priority(CDS_MQ_ID msgQueueId, 1426 cds_msg_t *pMsg, 1427 int is_high_priority) 1428 { 1429 p_cds_mq_type pTargetMq = NULL; 1430 p_cds_msg_wrapper pMsgWrapper = NULL; 1431 uint32_t debug_count = 0; 1432 1433 if ((gp_cds_context == NULL) || (pMsg == NULL)) { 1434 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1435 "%s: Null params or global cds context is null", 1436 __func__); 1437 QDF_ASSERT(0); 1438 return QDF_STATUS_E_FAILURE; 1439 } 1440 1441 switch (msgQueueId) { 1442 /* Message Queue ID for messages bound for SME */ 1443 case CDS_MQ_ID_SME: 1444 { 1445 pTargetMq = &(gp_cds_context->qdf_sched.smeMcMq); 1446 break; 1447 } 1448 1449 /* Message Queue ID for messages bound for PE */ 1450 case CDS_MQ_ID_PE: 1451 { 1452 pTargetMq = &(gp_cds_context->qdf_sched.peMcMq); 1453 break; 1454 } 1455 1456 /* Message Queue ID for messages bound for wma */ 1457 case CDS_MQ_ID_WMA: 1458 { 1459 pTargetMq = &(gp_cds_context->qdf_sched.wmaMcMq); 1460 break; 1461 } 1462 1463 /* Message Queue ID for messages bound for the SYS module */ 1464 case CDS_MQ_ID_SYS: 1465 { 1466 pTargetMq = &(gp_cds_context->qdf_sched.sysMcMq); 1467 break; 1468 } 1469 1470 default: 1471 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1472 ("%s: Trying to queue msg into unknown MC Msg queue ID %d"), 1473 __func__, msgQueueId); 1474 1475 return QDF_STATUS_E_FAILURE; 1476 } 1477 1478 QDF_ASSERT(NULL != pTargetMq); 1479 if (pTargetMq == NULL) { 1480 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1481 "%s: pTargetMq == NULL", __func__); 1482 return QDF_STATUS_E_FAILURE; 1483 } 1484 1485 /* Try and get a free Msg wrapper */ 1486 pMsgWrapper = cds_mq_get(&gp_cds_context->freeVosMq); 1487 1488 if (NULL == pMsgWrapper) { 1489 debug_count = atomic_inc_return(&cds_wrapper_empty_count); 1490 if (1 == debug_count) { 1491 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1492 "%s: CDS Core run out of message wrapper %d", 1493 __func__, debug_count); 1494 cds_flush_logs(WLAN_LOG_TYPE_FATAL, 1495 WLAN_LOG_INDICATOR_HOST_ONLY, 1496 WLAN_LOG_REASON_VOS_MSG_UNDER_RUN, 1497 true, false); 1498 } 1499 if (CDS_WRAPPER_MAX_FAIL_COUNT == debug_count) 1500 QDF_BUG(0); 1501 1502 return QDF_STATUS_E_RESOURCES; 1503 } 1504 1505 atomic_set(&cds_wrapper_empty_count, 0); 1506 1507 /* Copy the message now */ 1508 qdf_mem_copy((void *)pMsgWrapper->pVosMsg, 1509 (void *)pMsg, sizeof(cds_msg_t)); 1510 1511 if (is_high_priority) 1512 cds_mq_put_front(pTargetMq, pMsgWrapper); 1513 else 1514 cds_mq_put(pTargetMq, pMsgWrapper); 1515 1516 set_bit(MC_POST_EVENT_MASK, &gp_cds_context->qdf_sched.mcEventFlag); 1517 wake_up_interruptible(&gp_cds_context->qdf_sched.mcWaitQueue); 1518 1519 return QDF_STATUS_SUCCESS; 1520 } /* cds_mq_post_message() */ 1521 1522 /** 1523 * cds_sys_probe_thread_cback() - probe mc thread callback 1524 * @pUserData: pointer to user data 1525 * 1526 * Return: none 1527 */ 1528 void cds_sys_probe_thread_cback(void *pUserData) 1529 { 1530 if (gp_cds_context != pUserData) { 1531 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1532 "%s: gp_cds_context != pUserData", __func__); 1533 return; 1534 } 1535 1536 if (qdf_event_set(&gp_cds_context->ProbeEvent) != QDF_STATUS_SUCCESS) { 1537 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1538 "%s: qdf_event_set failed", __func__); 1539 return; 1540 } 1541 } /* cds_sys_probe_thread_cback() */ 1542 1543 /** 1544 * cds_wma_complete_cback() - wma complete callback 1545 * @pUserData: pointer to user data 1546 * 1547 * Return: none 1548 */ 1549 void cds_wma_complete_cback(void *pUserData) 1550 { 1551 if (gp_cds_context != pUserData) { 1552 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1553 "%s: gp_cds_context != pUserData", __func__); 1554 return; 1555 } 1556 1557 if (qdf_event_set(&gp_cds_context->wmaCompleteEvent) != 1558 QDF_STATUS_SUCCESS) { 1559 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1560 "%s: qdf_event_set failed", __func__); 1561 return; 1562 } 1563 } /* cds_wma_complete_cback() */ 1564 1565 /** 1566 * cds_core_return_msg() - return core message 1567 * @pVContext: pointer to cds context 1568 * @pMsgWrapper: pointer to message wrapper 1569 * 1570 * Return: none 1571 */ 1572 void cds_core_return_msg(void *pVContext, p_cds_msg_wrapper pMsgWrapper) 1573 { 1574 p_cds_contextType p_cds_context = (p_cds_contextType) pVContext; 1575 1576 QDF_ASSERT(gp_cds_context == p_cds_context); 1577 1578 if (gp_cds_context != p_cds_context) { 1579 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1580 "%s: gp_cds_context != p_cds_context", __func__); 1581 return; 1582 } 1583 1584 QDF_ASSERT(NULL != pMsgWrapper); 1585 1586 if (pMsgWrapper == NULL) { 1587 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1588 "%s: pMsgWrapper == NULL in function", __func__); 1589 return; 1590 } 1591 1592 /* 1593 ** Return the message on the free message queue 1594 */ 1595 INIT_LIST_HEAD(&pMsgWrapper->msgNode); 1596 cds_mq_put(&p_cds_context->freeVosMq, pMsgWrapper); 1597 } /* cds_core_return_msg() */ 1598 1599 /** 1600 * cds_get_vdev_types() - get vdev type 1601 * @mode: mode 1602 * @type: type 1603 * @sub_type: sub_type 1604 * 1605 * Return: WMI vdev type 1606 */ 1607 QDF_STATUS cds_get_vdev_types(enum tQDF_ADAPTER_MODE mode, uint32_t *type, 1608 uint32_t *sub_type) 1609 { 1610 QDF_STATUS status = QDF_STATUS_SUCCESS; 1611 *type = 0; 1612 *sub_type = 0; 1613 1614 switch (mode) { 1615 case QDF_STA_MODE: 1616 *type = WMI_VDEV_TYPE_STA; 1617 break; 1618 case QDF_SAP_MODE: 1619 *type = WMI_VDEV_TYPE_AP; 1620 break; 1621 case QDF_P2P_DEVICE_MODE: 1622 *type = WMI_VDEV_TYPE_AP; 1623 *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE; 1624 break; 1625 case QDF_P2P_CLIENT_MODE: 1626 *type = WMI_VDEV_TYPE_STA; 1627 *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT; 1628 break; 1629 case QDF_P2P_GO_MODE: 1630 *type = WMI_VDEV_TYPE_AP; 1631 *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO; 1632 break; 1633 case QDF_OCB_MODE: 1634 *type = WMI_VDEV_TYPE_OCB; 1635 break; 1636 case QDF_IBSS_MODE: 1637 *type = WMI_VDEV_TYPE_IBSS; 1638 break; 1639 case QDF_MONITOR_MODE: 1640 *type = WMI_VDEV_TYPE_MONITOR; 1641 break; 1642 case QDF_NDI_MODE: 1643 *type = WMI_VDEV_TYPE_NDI; 1644 break; 1645 default: 1646 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1647 "Invalid device mode %d", mode); 1648 status = QDF_STATUS_E_INVAL; 1649 break; 1650 } 1651 return status; 1652 } 1653 1654 /** 1655 * cds_flush_work() - flush pending works 1656 * @work: pointer to work 1657 * 1658 * Return: none 1659 */ 1660 void cds_flush_work(void *work) 1661 { 1662 cancel_work_sync(work); 1663 } 1664 1665 /** 1666 * cds_flush_delayed_work() - flush delayed works 1667 * @dwork: pointer to delayed work 1668 * 1669 * Return: none 1670 */ 1671 void cds_flush_delayed_work(void *dwork) 1672 { 1673 cancel_delayed_work_sync(dwork); 1674 } 1675 1676 /** 1677 * cds_is_packet_log_enabled() - check if packet log is enabled 1678 * 1679 * Return: true if packet log is enabled else false 1680 */ 1681 bool cds_is_packet_log_enabled(void) 1682 { 1683 hdd_context_t *pHddCtx; 1684 1685 pHddCtx = (hdd_context_t *) (gp_cds_context->pHDDContext); 1686 if ((NULL == pHddCtx) || (NULL == pHddCtx->config)) { 1687 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, 1688 "%s: Hdd Context is Null", __func__); 1689 return false; 1690 } 1691 1692 return pHddCtx->config->enablePacketLog; 1693 } 1694 1695 /** 1696 * cds_config_recovery_work() - configure self recovery 1697 * @qdf_ctx: pointer of qdf context 1698 * 1699 * Return: none 1700 */ 1701 1702 void cds_config_recovery_work(qdf_device_t qdf_ctx) 1703 { 1704 if (cds_is_driver_recovering()) { 1705 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1706 "Recovery is in progress, ignore!"); 1707 } else { 1708 cds_set_recovery_in_progress(true); 1709 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1710 "schedule recovery work!"); 1711 pld_schedule_recovery_work(qdf_ctx->dev); 1712 } 1713 } 1714 1715 /** 1716 * cds_trigger_recovery() - trigger self recovery 1717 * @skip_crash_inject: Boolean value to skip to send crash inject cmd 1718 * 1719 * Return: none 1720 */ 1721 void cds_trigger_recovery(bool skip_crash_inject) 1722 { 1723 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 1724 QDF_STATUS status = QDF_STATUS_SUCCESS; 1725 qdf_runtime_lock_t recovery_lock; 1726 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 1727 1728 if (!wma_handle) { 1729 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1730 "WMA context is invalid!"); 1731 return; 1732 } 1733 1734 recovery_lock = qdf_runtime_lock_init("cds_recovery"); 1735 if (!recovery_lock) { 1736 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1737 "Could not acquire runtime pm lock!"); 1738 return; 1739 } 1740 1741 qdf_runtime_pm_prevent_suspend(recovery_lock); 1742 1743 if (!skip_crash_inject) { 1744 1745 wma_crash_inject(wma_handle, RECOVERY_SIM_SELF_RECOVERY, 0); 1746 status = qdf_wait_single_event(&wma_handle->recovery_event, 1747 WMA_CRASH_INJECT_TIMEOUT); 1748 1749 if (QDF_STATUS_SUCCESS != status) { 1750 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1751 "CRASH_INJECT command is timed out!"); 1752 cds_config_recovery_work(qdf_ctx); 1753 } 1754 } else { 1755 cds_config_recovery_work(qdf_ctx); 1756 } 1757 1758 qdf_runtime_pm_allow_suspend(recovery_lock); 1759 qdf_runtime_lock_deinit(recovery_lock); 1760 } 1761 1762 /** 1763 * cds_get_monotonic_boottime() - Get kernel boot time. 1764 * 1765 * Return: Time in microseconds 1766 */ 1767 1768 uint64_t cds_get_monotonic_boottime(void) 1769 { 1770 struct timespec ts; 1771 1772 get_monotonic_boottime(&ts); 1773 return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); 1774 } 1775 1776 /** 1777 * cds_set_wakelock_logging() - Logging of wakelock enabled/disabled 1778 * @value: Boolean value 1779 * 1780 * This function is used to set the flag which will indicate whether 1781 * logging of wakelock is enabled or not 1782 * 1783 * Return: None 1784 */ 1785 void cds_set_wakelock_logging(bool value) 1786 { 1787 p_cds_contextType p_cds_context; 1788 1789 p_cds_context = cds_get_global_context(); 1790 if (!p_cds_context) { 1791 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1792 "cds context is Invald"); 1793 return; 1794 } 1795 p_cds_context->is_wakelock_log_enabled = value; 1796 } 1797 1798 /** 1799 * cds_is_wakelock_enabled() - Check if logging of wakelock is enabled/disabled 1800 * @value: Boolean value 1801 * 1802 * This function is used to check whether logging of wakelock is enabled or not 1803 * 1804 * Return: true if logging of wakelock is enabled 1805 */ 1806 bool cds_is_wakelock_enabled(void) 1807 { 1808 p_cds_contextType p_cds_context; 1809 1810 p_cds_context = cds_get_global_context(); 1811 if (!p_cds_context) { 1812 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1813 "cds context is Invald"); 1814 return false; 1815 } 1816 return p_cds_context->is_wakelock_log_enabled; 1817 } 1818 1819 /** 1820 * cds_set_ring_log_level() - Sets the log level of a particular ring 1821 * @ring_id: ring_id 1822 * @log_levelvalue: Log level specificed 1823 * 1824 * This function converts HLOS values to driver log levels and sets the log 1825 * level of a particular ring accordingly. 1826 * 1827 * Return: None 1828 */ 1829 void cds_set_ring_log_level(uint32_t ring_id, uint32_t log_level) 1830 { 1831 p_cds_contextType p_cds_context; 1832 uint32_t log_val; 1833 1834 p_cds_context = cds_get_global_context(); 1835 if (!p_cds_context) { 1836 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1837 "%s: cds context is Invald", __func__); 1838 return; 1839 } 1840 1841 switch (log_level) { 1842 case LOG_LEVEL_NO_COLLECTION: 1843 log_val = WLAN_LOG_LEVEL_OFF; 1844 break; 1845 case LOG_LEVEL_NORMAL_COLLECT: 1846 log_val = WLAN_LOG_LEVEL_NORMAL; 1847 break; 1848 case LOG_LEVEL_ISSUE_REPRO: 1849 log_val = WLAN_LOG_LEVEL_REPRO; 1850 break; 1851 case LOG_LEVEL_ACTIVE: 1852 default: 1853 log_val = WLAN_LOG_LEVEL_ACTIVE; 1854 break; 1855 } 1856 1857 if (ring_id == RING_ID_WAKELOCK) { 1858 p_cds_context->wakelock_log_level = log_val; 1859 return; 1860 } else if (ring_id == RING_ID_CONNECTIVITY) { 1861 p_cds_context->connectivity_log_level = log_val; 1862 return; 1863 } else if (ring_id == RING_ID_PER_PACKET_STATS) { 1864 p_cds_context->packet_stats_log_level = log_val; 1865 return; 1866 } else if (ring_id == RING_ID_DRIVER_DEBUG) { 1867 p_cds_context->driver_debug_log_level = log_val; 1868 return; 1869 } else if (ring_id == RING_ID_FIRMWARE_DEBUG) { 1870 p_cds_context->fw_debug_log_level = log_val; 1871 return; 1872 } 1873 } 1874 1875 /** 1876 * cds_get_ring_log_level() - Get the a ring id's log level 1877 * @ring_id: Ring id 1878 * 1879 * Fetch and return the log level corresponding to a ring id 1880 * 1881 * Return: Log level corresponding to the ring ID 1882 */ 1883 enum wifi_driver_log_level cds_get_ring_log_level(uint32_t ring_id) 1884 { 1885 p_cds_contextType p_cds_context; 1886 1887 p_cds_context = cds_get_global_context(); 1888 if (!p_cds_context) { 1889 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1890 "%s: cds context is Invald", __func__); 1891 return WLAN_LOG_LEVEL_OFF; 1892 } 1893 1894 if (ring_id == RING_ID_WAKELOCK) 1895 return p_cds_context->wakelock_log_level; 1896 else if (ring_id == RING_ID_CONNECTIVITY) 1897 return p_cds_context->connectivity_log_level; 1898 else if (ring_id == RING_ID_PER_PACKET_STATS) 1899 return p_cds_context->packet_stats_log_level; 1900 else if (ring_id == RING_ID_DRIVER_DEBUG) 1901 return p_cds_context->driver_debug_log_level; 1902 else if (ring_id == RING_ID_FIRMWARE_DEBUG) 1903 return p_cds_context->fw_debug_log_level; 1904 1905 return WLAN_LOG_LEVEL_OFF; 1906 } 1907 1908 /** 1909 * cds_set_multicast_logging() - Set mutlicast logging value 1910 * @value: Value of multicast logging 1911 * 1912 * Set the multicast logging value which will indicate 1913 * whether to multicast host and fw messages even 1914 * without any registration by userspace entity 1915 * 1916 * Return: None 1917 */ 1918 void cds_set_multicast_logging(uint8_t value) 1919 { 1920 cds_multicast_logging = value; 1921 } 1922 1923 /** 1924 * cds_is_multicast_logging() - Get multicast logging value 1925 * 1926 * Get the multicast logging value which will indicate 1927 * whether to multicast host and fw messages even 1928 * without any registration by userspace entity 1929 * 1930 * Return: 0 - Multicast logging disabled, 1 - Multicast logging enabled 1931 */ 1932 uint8_t cds_is_multicast_logging(void) 1933 { 1934 return cds_multicast_logging; 1935 } 1936 1937 /* 1938 * cds_init_log_completion() - Initialize log param structure 1939 * 1940 * This function is used to initialize the logging related 1941 * parameters 1942 * 1943 * Return: None 1944 */ 1945 void cds_init_log_completion(void) 1946 { 1947 p_cds_contextType p_cds_context; 1948 1949 p_cds_context = cds_get_global_context(); 1950 if (!p_cds_context) { 1951 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1952 "%s: cds context is Invalid", __func__); 1953 return; 1954 } 1955 1956 p_cds_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; 1957 p_cds_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; 1958 p_cds_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; 1959 p_cds_context->log_complete.is_report_in_progress = false; 1960 /* Attempting to initialize an already initialized lock 1961 * results in a failure. This must be ok here. 1962 */ 1963 qdf_spinlock_create(&p_cds_context->bug_report_lock); 1964 } 1965 1966 /** 1967 * cds_deinit_log_completion() - Deinitialize log param structure 1968 * 1969 * This function is used to deinitialize the logging related 1970 * parameters 1971 * 1972 * Return: None 1973 */ 1974 void cds_deinit_log_completion(void) 1975 { 1976 p_cds_contextType p_cds_context; 1977 1978 p_cds_context = cds_get_global_context(); 1979 if (!p_cds_context) { 1980 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 1981 "%s: cds context is Invalid", __func__); 1982 return; 1983 } 1984 1985 qdf_spinlock_destroy(&p_cds_context->bug_report_lock); 1986 } 1987 1988 /** 1989 * cds_set_log_completion() - Store the logging params 1990 * @is_fatal: Indicates if the event triggering bug report is fatal or not 1991 * @indicator: Source which trigerred the bug report 1992 * @reason_code: Reason for triggering bug report 1993 * @recovery_needed: If recovery is needed after bug report 1994 * 1995 * This function is used to set the logging parameters based on the 1996 * caller 1997 * 1998 * Return: 0 if setting of params is successful 1999 */ 2000 QDF_STATUS cds_set_log_completion(uint32_t is_fatal, 2001 uint32_t indicator, 2002 uint32_t reason_code, 2003 bool recovery_needed) 2004 { 2005 p_cds_contextType p_cds_context; 2006 2007 p_cds_context = cds_get_global_context(); 2008 if (!p_cds_context) { 2009 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2010 "%s: cds context is Invalid", __func__); 2011 return QDF_STATUS_E_FAILURE; 2012 } 2013 2014 qdf_spinlock_acquire(&p_cds_context->bug_report_lock); 2015 p_cds_context->log_complete.is_fatal = is_fatal; 2016 p_cds_context->log_complete.indicator = indicator; 2017 p_cds_context->log_complete.reason_code = reason_code; 2018 p_cds_context->log_complete.recovery_needed = recovery_needed; 2019 p_cds_context->log_complete.is_report_in_progress = true; 2020 qdf_spinlock_release(&p_cds_context->bug_report_lock); 2021 return QDF_STATUS_SUCCESS; 2022 } 2023 2024 /** 2025 * cds_get_and_reset_log_completion() - Get and reset logging related params 2026 * @is_fatal: Indicates if the event triggering bug report is fatal or not 2027 * @indicator: Source which trigerred the bug report 2028 * @reason_code: Reason for triggering bug report 2029 * @recovery_needed: If recovery is needed after bug report 2030 * 2031 * This function is used to get the logging related parameters 2032 * 2033 * Return: None 2034 */ 2035 void cds_get_and_reset_log_completion(uint32_t *is_fatal, 2036 uint32_t *indicator, 2037 uint32_t *reason_code, 2038 bool *recovery_needed) 2039 { 2040 p_cds_contextType p_cds_context; 2041 2042 p_cds_context = cds_get_global_context(); 2043 if (!p_cds_context) { 2044 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2045 "%s: cds context is Invalid", __func__); 2046 return; 2047 } 2048 2049 qdf_spinlock_acquire(&p_cds_context->bug_report_lock); 2050 *is_fatal = p_cds_context->log_complete.is_fatal; 2051 *indicator = p_cds_context->log_complete.indicator; 2052 *reason_code = p_cds_context->log_complete.reason_code; 2053 *recovery_needed = p_cds_context->log_complete.recovery_needed; 2054 2055 /* reset */ 2056 p_cds_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; 2057 p_cds_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; 2058 p_cds_context->log_complete.is_report_in_progress = false; 2059 p_cds_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; 2060 p_cds_context->log_complete.recovery_needed = false; 2061 qdf_spinlock_release(&p_cds_context->bug_report_lock); 2062 } 2063 2064 /** 2065 * cds_is_log_report_in_progress() - Check if bug reporting is in progress 2066 * 2067 * This function is used to check if the bug reporting is already in progress 2068 * 2069 * Return: true if the bug reporting is in progress 2070 */ 2071 bool cds_is_log_report_in_progress(void) 2072 { 2073 p_cds_contextType p_cds_context; 2074 2075 p_cds_context = cds_get_global_context(); 2076 if (!p_cds_context) { 2077 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2078 "%s: cds context is Invalid", __func__); 2079 return true; 2080 } 2081 return p_cds_context->log_complete.is_report_in_progress; 2082 } 2083 2084 /** 2085 * cds_is_fatal_event_enabled() - Return if fatal event is enabled 2086 * 2087 * Return true if fatal event is enabled. 2088 */ 2089 bool cds_is_fatal_event_enabled(void) 2090 { 2091 p_cds_contextType p_cds_context; 2092 2093 p_cds_context = cds_get_global_context(); 2094 if (!p_cds_context) { 2095 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2096 "%s: cds context is Invalid", __func__); 2097 return false; 2098 } 2099 2100 2101 return p_cds_context->enable_fatal_event; 2102 } 2103 2104 /** 2105 * cds_get_log_indicator() - Get the log flush indicator 2106 * 2107 * This function is used to get the log flush indicator 2108 * 2109 * Return: log indicator 2110 */ 2111 uint32_t cds_get_log_indicator(void) 2112 { 2113 p_cds_contextType p_cds_context; 2114 uint32_t indicator; 2115 2116 p_cds_context = cds_get_global_context(); 2117 if (!p_cds_context) { 2118 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2119 "%s: cds context is Invalid", __func__); 2120 return WLAN_LOG_INDICATOR_UNUSED; 2121 } 2122 2123 if (cds_is_load_or_unload_in_progress() || 2124 cds_is_driver_recovering()) { 2125 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2126 "%s: vos context initialization is in progress" 2127 , __func__); 2128 return WLAN_LOG_INDICATOR_UNUSED; 2129 } 2130 2131 qdf_spinlock_acquire(&p_cds_context->bug_report_lock); 2132 indicator = p_cds_context->log_complete.indicator; 2133 qdf_spinlock_release(&p_cds_context->bug_report_lock); 2134 return indicator; 2135 } 2136 2137 /** 2138 * cds_wlan_flush_host_logs_for_fatal() - Wrapper to flush host logs 2139 * 2140 * This function is used to send signal to the logger thread to 2141 * flush the host logs. 2142 * 2143 * Return: None 2144 * 2145 */ 2146 void cds_wlan_flush_host_logs_for_fatal(void) 2147 { 2148 wlan_flush_host_logs_for_fatal(); 2149 } 2150 2151 /** 2152 * cds_flush_logs() - Report fatal event to userspace 2153 * @is_fatal: Indicates if the event triggering bug report is fatal or not 2154 * @indicator: Source which trigerred the bug report 2155 * @reason_code: Reason for triggering bug report 2156 * @dump_mac_trace: If mac trace are needed in logs. 2157 * @recovery_needed: If recovery is needed after bug report 2158 * 2159 * This function sets the log related params and send the WMI command to the 2160 * FW to flush its logs. On receiving the flush completion event from the FW 2161 * the same will be conveyed to userspace 2162 * 2163 * Return: 0 on success 2164 */ 2165 QDF_STATUS cds_flush_logs(uint32_t is_fatal, 2166 uint32_t indicator, 2167 uint32_t reason_code, 2168 bool dump_mac_trace, 2169 bool recovery_needed) 2170 { 2171 uint32_t ret; 2172 QDF_STATUS status; 2173 2174 p_cds_contextType p_cds_context; 2175 2176 p_cds_context = cds_get_global_context(); 2177 if (!p_cds_context) { 2178 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2179 "%s: cds context is Invalid", __func__); 2180 return QDF_STATUS_E_FAILURE; 2181 } 2182 if (!p_cds_context->enable_fatal_event) { 2183 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2184 "%s: Fatal event not enabled", __func__); 2185 return QDF_STATUS_E_FAILURE; 2186 } 2187 if (cds_is_load_or_unload_in_progress() || 2188 cds_is_driver_recovering()) { 2189 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2190 "%s: un/Load/SSR in progress", __func__); 2191 return QDF_STATUS_E_FAILURE; 2192 } 2193 2194 if (cds_is_log_report_in_progress() == true) { 2195 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2196 "%s: Bug report already in progress - dropping! type:%d, indicator=%d reason_code=%d", 2197 __func__, is_fatal, indicator, reason_code); 2198 return QDF_STATUS_E_FAILURE; 2199 } 2200 2201 status = cds_set_log_completion(is_fatal, indicator, 2202 reason_code, recovery_needed); 2203 if (QDF_STATUS_SUCCESS != status) { 2204 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2205 "%s: Failed to set log trigger params", __func__); 2206 return QDF_STATUS_E_FAILURE; 2207 } 2208 2209 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2210 "%s: Triggering bug report: type:%d, indicator=%d reason_code=%d", 2211 __func__, is_fatal, indicator, reason_code); 2212 2213 if (dump_mac_trace) 2214 qdf_trace_dump_all(p_cds_context->pMACContext, 0, 0, 500, 0); 2215 2216 if (WLAN_LOG_INDICATOR_HOST_ONLY == indicator) { 2217 cds_wlan_flush_host_logs_for_fatal(); 2218 return QDF_STATUS_SUCCESS; 2219 } 2220 2221 ret = sme_send_flush_logs_cmd_to_fw(p_cds_context->pMACContext); 2222 if (0 != ret) { 2223 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2224 "%s: Failed to send flush FW log", __func__); 2225 cds_init_log_completion(); 2226 return QDF_STATUS_E_FAILURE; 2227 } 2228 2229 return QDF_STATUS_SUCCESS; 2230 } 2231 2232 /** 2233 * cds_logging_set_fw_flush_complete() - Wrapper for FW log flush completion 2234 * 2235 * This function is used to send signal to the logger thread to indicate 2236 * that the flushing of FW logs is complete by the FW 2237 * 2238 * Return: None 2239 * 2240 */ 2241 void cds_logging_set_fw_flush_complete(void) 2242 { 2243 wlan_logging_set_fw_flush_complete(); 2244 } 2245 2246 /** 2247 * cds_set_fatal_event() - set fatal event status 2248 * @value: pending statue to set 2249 * 2250 * Return: None 2251 */ 2252 void cds_set_fatal_event(bool value) 2253 { 2254 p_cds_contextType p_cds_context; 2255 2256 p_cds_context = cds_get_global_context(); 2257 if (!p_cds_context) { 2258 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2259 "%s: cds context is Invalid", __func__); 2260 return; 2261 } 2262 p_cds_context->enable_fatal_event = value; 2263 } 2264 2265 /** 2266 * cds_get_radio_index() - get radio index 2267 * 2268 * Return: radio index otherwise, -EINVAL 2269 */ 2270 int cds_get_radio_index(void) 2271 { 2272 p_cds_contextType p_cds_context; 2273 2274 p_cds_context = cds_get_global_context(); 2275 if (!p_cds_context) { 2276 /* 2277 * To avoid recursive call, this should not change to 2278 * QDF_TRACE(). 2279 */ 2280 pr_err("%s: cds context is invalid\n", __func__); 2281 return -EINVAL; 2282 } 2283 2284 return p_cds_context->radio_index; 2285 } 2286 2287 /** 2288 * cds_set_radio_index() - set radio index 2289 * @radio_index: the radio index to set 2290 * 2291 * Return: QDF status 2292 */ 2293 QDF_STATUS cds_set_radio_index(int radio_index) 2294 { 2295 p_cds_contextType p_cds_context; 2296 2297 p_cds_context = cds_get_global_context(); 2298 if (!p_cds_context) { 2299 pr_err("%s: cds context is invalid\n", __func__); 2300 return QDF_STATUS_E_FAILURE; 2301 } 2302 2303 p_cds_context->radio_index = radio_index; 2304 2305 return QDF_STATUS_SUCCESS; 2306 } 2307 2308 /** 2309 * cds_init_ini_config() - API to initialize CDS configuration parameters 2310 * @cfg: CDS Configuration 2311 * 2312 * Return: void 2313 */ 2314 2315 void cds_init_ini_config(struct cds_config_info *cfg) 2316 { 2317 cds_context_type *cds_ctx; 2318 2319 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); 2320 if (!cds_ctx) { 2321 cds_err("Invalid CDS Context"); 2322 return; 2323 } 2324 2325 cds_ctx->cds_cfg = cfg; 2326 } 2327 2328 /** 2329 * cds_deinit_ini_config() - API to free CDS configuration parameters 2330 * 2331 * Return: void 2332 */ 2333 void cds_deinit_ini_config(void) 2334 { 2335 cds_context_type *cds_ctx; 2336 2337 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); 2338 if (!cds_ctx) { 2339 cds_err("Invalid CDS Context"); 2340 return; 2341 } 2342 2343 if (cds_ctx->cds_cfg) 2344 qdf_mem_free(cds_ctx->cds_cfg); 2345 2346 cds_ctx->cds_cfg = NULL; 2347 } 2348 2349 /** 2350 * cds_get_ini_config() - API to get CDS configuration parameters 2351 * 2352 * Return: cds config structure 2353 */ 2354 struct cds_config_info *cds_get_ini_config(void) 2355 { 2356 cds_context_type *cds_ctx; 2357 2358 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); 2359 if (!cds_ctx) { 2360 cds_err("Invalid CDS Context"); 2361 return NULL; 2362 } 2363 2364 return cds_ctx->cds_cfg; 2365 } 2366 2367 /** 2368 * cds_is_5_mhz_enabled() - API to get 5MHZ enabled 2369 * 2370 * Return: true if 5 mhz is enabled, false otherwise 2371 */ 2372 bool cds_is_5_mhz_enabled(void) 2373 { 2374 p_cds_contextType p_cds_context; 2375 2376 p_cds_context = cds_get_context(QDF_MODULE_ID_QDF); 2377 if (!p_cds_context) { 2378 cds_err("%s: cds context is invalid", __func__); 2379 return false; 2380 } 2381 2382 if (p_cds_context->cds_cfg) 2383 return (p_cds_context->cds_cfg->sub_20_channel_width == 2384 WLAN_SUB_20_CH_WIDTH_5); 2385 2386 return false; 2387 } 2388 2389 /** 2390 * cds_is_10_mhz_enabled() - API to get 10-MHZ enabled 2391 * 2392 * Return: true if 10 mhz is enabled, false otherwise 2393 */ 2394 bool cds_is_10_mhz_enabled(void) 2395 { 2396 p_cds_contextType p_cds_context; 2397 2398 p_cds_context = cds_get_context(QDF_MODULE_ID_QDF); 2399 if (!p_cds_context) { 2400 cds_err("%s: cds context is invalid", __func__); 2401 return false; 2402 } 2403 2404 if (p_cds_context->cds_cfg) 2405 return (p_cds_context->cds_cfg->sub_20_channel_width == 2406 WLAN_SUB_20_CH_WIDTH_10); 2407 2408 return false; 2409 } 2410 2411 /** 2412 * cds_is_sub_20_mhz_enabled() - API to get sub 20-MHZ enabled 2413 * 2414 * Return: true if 5 or 10 mhz is enabled, false otherwise 2415 */ 2416 bool cds_is_sub_20_mhz_enabled(void) 2417 { 2418 p_cds_contextType p_cds_context; 2419 2420 p_cds_context = cds_get_context(QDF_MODULE_ID_QDF); 2421 if (!p_cds_context) { 2422 cds_err("%s: cds context is invalid", __func__); 2423 return false; 2424 } 2425 2426 if (p_cds_context->cds_cfg) 2427 return p_cds_context->cds_cfg->sub_20_channel_width; 2428 2429 return false; 2430 } 2431 2432 /** 2433 * cds_is_self_recovery_enabled() - API to get self recovery enabled 2434 * 2435 * Return: true if self recovery enabled, false otherwise 2436 */ 2437 bool cds_is_self_recovery_enabled(void) 2438 { 2439 p_cds_contextType p_cds_context; 2440 2441 p_cds_context = cds_get_context(QDF_MODULE_ID_QDF); 2442 if (!p_cds_context) { 2443 cds_err("%s: cds context is invalid", __func__); 2444 return false; 2445 } 2446 2447 if (p_cds_context->cds_cfg) 2448 return p_cds_context->cds_cfg->self_recovery_enabled; 2449 2450 return false; 2451 } 2452 2453 /** 2454 * cds_svc_fw_shutdown_ind() - API to send userspace about FW crash 2455 * 2456 * @dev: Device Pointer 2457 * 2458 * Return: None 2459 */ 2460 void cds_svc_fw_shutdown_ind(struct device *dev) 2461 { 2462 hdd_svc_fw_shutdown_ind(dev); 2463 } 2464 2465 /* 2466 * cds_pkt_stats_to_logger_thread() - send pktstats to user 2467 * @pl_hdr: Pointer to pl_hdr 2468 * @pkt_dump: Pointer to pkt_dump data structure. 2469 * @data: Pointer to data 2470 * 2471 * This function is used to send the pkt stats to SVC module. 2472 * 2473 * Return: None 2474 */ 2475 inline void cds_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, 2476 void *data) 2477 { 2478 if (cds_get_ring_log_level(RING_ID_PER_PACKET_STATS) != 2479 WLAN_LOG_LEVEL_ACTIVE) 2480 return; 2481 2482 wlan_pkt_stats_to_logger_thread(pl_hdr, pkt_dump, data); 2483 } 2484