1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: cds_api.c 22 * 23 * Connectivity driver services APIs 24 */ 25 26 #include <cds_api.h> 27 #include "sir_types.h" 28 #include "sir_api.h" 29 #include "sir_mac_prot_def.h" 30 #include "sme_api.h" 31 #include "mac_init_api.h" 32 #include "wlan_qct_sys.h" 33 #include "i_cds_packet.h" 34 #include "cds_reg_service.h" 35 #include "wma_types.h" 36 #include "wlan_hdd_main.h" 37 #include "wlan_hdd_power.h" 38 #include "wlan_hdd_tsf.h" 39 #include <linux/vmalloc.h> 40 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) && defined(MSM_PLATFORM) 41 #include <linux/qcom-iommu-util.h> 42 #endif 43 #include <scheduler_core.h> 44 45 #include "pld_common.h" 46 #include "sap_api.h" 47 #include "bmi.h" 48 #include "ol_fw.h" 49 #include "ol_if_athvar.h" 50 #include "hif.h" 51 #include "wlan_policy_mgr_api.h" 52 #include "cds_utils.h" 53 #include "wlan_logging_sock_svc.h" 54 #include "wma.h" 55 #include "pktlog_ac.h" 56 #include "wlan_policy_mgr_api.h" 57 58 #include <cdp_txrx_cmn_reg.h> 59 #include <cdp_txrx_cfg.h> 60 #include <cdp_txrx_misc.h> 61 #include <ol_defines.h> 62 #include <dispatcher_init_deinit.h> 63 #include <cdp_txrx_handle.h> 64 #include <cdp_txrx_host_stats.h> 65 #include "target_type.h" 66 #include "wlan_ocb_ucfg_api.h" 67 #include "wlan_ipa_ucfg_api.h" 68 69 #ifdef ENABLE_SMMU_S1_TRANSLATION 70 #include "pld_common.h" 71 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) 72 #include <asm/dma-iommu.h> 73 #endif 74 #include <linux/iommu.h> 75 #endif 76 77 #ifdef QCA_WIFI_QCA8074 78 #include <target_if_dp.h> 79 #endif 80 #include "wlan_mlme_ucfg_api.h" 81 #include "cfg_ucfg_api.h" 82 #include "wlan_cp_stats_mc_ucfg_api.h" 83 #include <qdf_hang_event_notifier.h> 84 #include <qdf_notifier.h> 85 #include <qwlan_version.h> 86 #include <qdf_trace.h> 87 #include <qdf_nbuf.h> 88 #include "wlan_dp_ucfg_api.h" 89 #include "wlan_dp_prealloc.h" 90 #include "wlan_dp_api.h" 91 #include "qdf_ipa.h" 92 93 /* Preprocessor Definitions and Constants */ 94 95 /* Preprocessor Definitions and Constants */ 96 97 /* Data definitions */ 98 static struct cds_context g_cds_context; 99 static struct cds_context *gp_cds_context; 100 static struct __qdf_device g_qdf_ctx; 101 102 static uint8_t cds_multicast_logging; 103 104 #define DRIVER_VER_LEN (11) 105 #define HANG_EVENT_VER_LEN (1) 106 107 struct cds_hang_event_fixed_param { 108 uint16_t tlv_header; 109 uint8_t recovery_reason; 110 char driver_version[DRIVER_VER_LEN]; 111 char hang_event_version[HANG_EVENT_VER_LEN]; 112 } qdf_packed; 113 114 #ifdef QCA_WIFI_QCA8074 115 static inline int 116 cds_send_delba(struct cdp_ctrl_objmgr_psoc *psoc, 117 uint8_t vdev_id, uint8_t *peer_macaddr, 118 uint8_t tid, uint8_t reason_code, 119 uint8_t cdp_reason_code) 120 { 121 return wma_dp_send_delba_ind(vdev_id, peer_macaddr, tid, 122 reason_code, cdp_reason_code); 123 } 124 125 static struct ol_if_ops dp_ol_if_ops = { 126 .peer_set_default_routing = target_if_peer_set_default_routing, 127 .peer_rx_reorder_queue_setup = target_if_peer_rx_reorder_queue_setup, 128 .peer_rx_reorder_queue_remove = target_if_peer_rx_reorder_queue_remove, 129 .peer_multi_rx_reorder_queue_setup = 130 target_if_peer_multi_rx_reorder_queue_setup, 131 .is_hw_dbs_capable = policy_mgr_is_dp_hw_dbs_capable, 132 .lro_hash_config = target_if_lro_hash_config, 133 .rx_invalid_peer = wma_rx_invalid_peer_ind, 134 .is_roam_inprogress = wma_is_roam_in_progress, 135 .get_con_mode = cds_get_conparam, 136 .send_delba = cds_send_delba, 137 .dp_rx_get_pending = dp_rx_tm_get_pending, 138 #ifdef DP_MEM_PRE_ALLOC 139 .dp_prealloc_get_context = dp_prealloc_get_context_memory, 140 .dp_prealloc_put_context = dp_prealloc_put_context_memory, 141 .dp_prealloc_get_consistent = dp_prealloc_get_coherent, 142 .dp_prealloc_put_consistent = dp_prealloc_put_coherent, 143 .dp_get_multi_pages = dp_prealloc_get_multi_pages, 144 .dp_put_multi_pages = dp_prealloc_put_multi_pages, 145 #endif 146 .dp_get_tx_inqueue = dp_get_tx_inqueue, 147 .dp_send_unit_test_cmd = wma_form_unit_test_cmd_and_send, 148 .dp_print_fisa_stats = wlan_dp_print_fisa_rx_stats, 149 /* TODO: Add any other control path calls required to OL_IF/WMA layer */ 150 }; 151 #else 152 static struct ol_if_ops dp_ol_if_ops = { 153 .dp_rx_get_pending = cds_get_rx_thread_pending, 154 }; 155 #endif 156 157 static void cds_trigger_recovery_work(void *param); 158 159 /** 160 * struct cds_recovery_call_info - caller information for cds_trigger_recovery 161 * @func: caller's function name 162 * @line: caller's line number 163 */ 164 struct cds_recovery_call_info { 165 const char *func; 166 uint32_t line; 167 } __cds_recovery_caller; 168 169 /** 170 * cds_recovery_work_init() - Initialize recovery work queue 171 * 172 * Return: none 173 */ 174 static QDF_STATUS cds_recovery_work_init(void) 175 { 176 qdf_create_work(0, &gp_cds_context->cds_recovery_work, 177 cds_trigger_recovery_work, &__cds_recovery_caller); 178 gp_cds_context->cds_recovery_wq = 179 qdf_create_workqueue("cds_recovery_workqueue"); 180 if (!gp_cds_context->cds_recovery_wq) { 181 cds_err("Failed to create cds_recovery_workqueue"); 182 return QDF_STATUS_E_FAILURE; 183 } 184 185 return QDF_STATUS_SUCCESS; 186 } 187 188 /** 189 * cds_recovery_work_deinit() - Initialize recovery work queue 190 * 191 * Return: none 192 */ 193 static void cds_recovery_work_deinit(void) 194 { 195 if (gp_cds_context->cds_recovery_wq) { 196 qdf_flush_workqueue(0, gp_cds_context->cds_recovery_wq); 197 qdf_destroy_workqueue(0, gp_cds_context->cds_recovery_wq); 198 } 199 } 200 201 static bool cds_is_drv_connected(void) 202 { 203 int ret; 204 qdf_device_t qdf_ctx; 205 206 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 207 if (!qdf_ctx) 208 return false; 209 210 ret = pld_is_drv_connected(qdf_ctx->dev); 211 212 return ((ret > 0) ? true : false); 213 } 214 215 static bool cds_is_drv_supported(void) 216 { 217 qdf_device_t qdf_ctx; 218 struct pld_platform_cap cap = {0}; 219 220 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 221 if (!qdf_ctx) 222 return false; 223 224 pld_get_platform_cap(qdf_ctx->dev, &cap); 225 226 return ((cap.cap_flag & PLD_HAS_DRV_SUPPORT) ? true : false); 227 } 228 229 static QDF_STATUS cds_wmi_send_recv_qmi(void *buf, uint32_t len, void * cb_ctx, 230 qdf_wmi_recv_qmi_cb wmi_rx_cb) 231 { 232 qdf_device_t qdf_ctx; 233 234 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 235 if (!qdf_ctx) 236 return QDF_STATUS_E_INVAL; 237 238 if (pld_qmi_send(qdf_ctx->dev, 0, buf, len, cb_ctx, wmi_rx_cb)) 239 return QDF_STATUS_E_INVAL; 240 241 return QDF_STATUS_SUCCESS; 242 } 243 244 /** 245 * cds_update_recovery_reason() - update the recovery reason code 246 * @recovery_reason: recovery reason 247 * 248 * Return: None 249 */ 250 static void cds_update_recovery_reason(enum qdf_hang_reason recovery_reason) 251 { 252 if (!gp_cds_context) { 253 cds_err("gp_cds_context is null"); 254 return; 255 } 256 257 gp_cds_context->recovery_reason = recovery_reason; 258 } 259 260 /** 261 * cds_sys_reboot_lock_init() - Create lock for system reboot 262 * 263 * Return: QDF_STATUS_SUCCESS if the lock was created and an error on failure 264 */ 265 static QDF_STATUS cds_sys_reboot_lock_init(void) 266 { 267 return qdf_mutex_create(&gp_cds_context->sys_reboot_lock); 268 } 269 270 /** 271 * cds_sys_reboot_lock_deinit() - destroy lock for system reboot 272 * 273 * Return: none 274 */ 275 static void cds_sys_reboot_lock_deinit(void) 276 { 277 qdf_mutex_destroy(&gp_cds_context->sys_reboot_lock); 278 } 279 280 void cds_set_sys_rebooting(void) 281 { 282 qdf_mutex_acquire(&gp_cds_context->sys_reboot_lock); 283 cds_set_driver_state(CDS_DRIVER_STATE_SYS_REBOOTING); 284 qdf_mutex_release(&gp_cds_context->sys_reboot_lock); 285 } 286 287 bool cds_sys_reboot_protect(void) 288 { 289 enum cds_driver_state state; 290 291 qdf_mutex_acquire(&gp_cds_context->sys_reboot_lock); 292 293 state = cds_get_driver_state(); 294 return __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_SYS_REBOOTING); 295 } 296 297 void cds_sys_reboot_unprotect(void) 298 { 299 qdf_mutex_release(&gp_cds_context->sys_reboot_lock); 300 } 301 302 QDF_STATUS cds_init(void) 303 { 304 QDF_STATUS status; 305 306 gp_cds_context = &g_cds_context; 307 308 status = cds_sys_reboot_lock_init(); 309 if (QDF_IS_STATUS_ERROR(status)) { 310 cds_err("Failed to init sys reboot lock; status:%u", status); 311 goto deinit; 312 } 313 314 status = cds_recovery_work_init(); 315 if (QDF_IS_STATUS_ERROR(status)) { 316 cds_err("Failed to init recovery work; status:%u", status); 317 goto destroy_lock; 318 } 319 320 cds_ssr_protect_init(); 321 322 gp_cds_context->qdf_ctx = &g_qdf_ctx; 323 324 qdf_register_self_recovery_callback(cds_trigger_recovery_psoc); 325 qdf_register_fw_down_callback(cds_is_fw_down); 326 qdf_register_is_driver_unloading_callback(cds_is_driver_unloading); 327 qdf_register_is_driver_state_module_stop_callback( 328 cds_is_driver_state_module_stop); 329 qdf_register_recovering_state_query_callback(cds_is_driver_recovering); 330 qdf_register_drv_connected_callback(cds_is_drv_connected); 331 qdf_register_drv_supported_callback(cds_is_drv_supported); 332 qdf_register_wmi_send_recv_qmi_callback(cds_wmi_send_recv_qmi); 333 qdf_register_recovery_reason_update(cds_update_recovery_reason); 334 qdf_register_get_bus_reg_dump(pld_get_bus_reg_dump); 335 336 return QDF_STATUS_SUCCESS; 337 338 destroy_lock: 339 cds_sys_reboot_lock_deinit(); 340 deinit: 341 gp_cds_context = NULL; 342 qdf_mem_zero(&g_cds_context, sizeof(g_cds_context)); 343 344 return status; 345 } 346 347 /** 348 * cds_deinit() - Deinitialize CDS 349 * 350 * This function frees the CDS resources 351 */ 352 void cds_deinit(void) 353 { 354 QDF_BUG(gp_cds_context); 355 if (!gp_cds_context) 356 return; 357 358 qdf_register_get_bus_reg_dump(NULL); 359 qdf_register_recovery_reason_update(NULL); 360 qdf_register_recovering_state_query_callback(NULL); 361 qdf_register_fw_down_callback(NULL); 362 qdf_register_is_driver_unloading_callback(NULL); 363 qdf_register_is_driver_state_module_stop_callback(NULL); 364 qdf_register_self_recovery_callback(NULL); 365 qdf_register_wmi_send_recv_qmi_callback(NULL); 366 367 gp_cds_context->qdf_ctx = NULL; 368 qdf_mem_zero(&g_qdf_ctx, sizeof(g_qdf_ctx)); 369 370 /* currently, no ssr_protect_deinit */ 371 372 cds_recovery_work_deinit(); 373 cds_sys_reboot_lock_deinit(); 374 375 gp_cds_context = NULL; 376 qdf_mem_zero(&g_cds_context, sizeof(g_cds_context)); 377 } 378 379 #ifdef FEATURE_WLAN_DIAG_SUPPORT 380 /** 381 * cds_tdls_tx_rx_mgmt_event()- send tdls mgmt rx tx event 382 * @event_id: event id 383 * @tx_rx: tx or rx 384 * @type: type of frame 385 * @action_sub_type: action frame type 386 * @peer_mac: peer mac 387 * 388 * This Function sends tdls mgmt rx tx diag event 389 * 390 * Return: void. 391 */ 392 void cds_tdls_tx_rx_mgmt_event(uint8_t event_id, uint8_t tx_rx, 393 uint8_t type, uint8_t action_sub_type, uint8_t *peer_mac) 394 { 395 WLAN_HOST_DIAG_EVENT_DEF(tdls_tx_rx_mgmt, 396 struct host_event_tdls_tx_rx_mgmt); 397 398 tdls_tx_rx_mgmt.event_id = event_id; 399 tdls_tx_rx_mgmt.tx_rx = tx_rx; 400 tdls_tx_rx_mgmt.type = type; 401 tdls_tx_rx_mgmt.action_sub_type = action_sub_type; 402 qdf_mem_copy(tdls_tx_rx_mgmt.peer_mac, 403 peer_mac, CDS_MAC_ADDRESS_LEN); 404 WLAN_HOST_DIAG_EVENT_REPORT(&tdls_tx_rx_mgmt, 405 EVENT_WLAN_TDLS_TX_RX_MGMT); 406 } 407 #endif 408 409 /** 410 * cds_cfg_update_ac_specs_params() - update ac_specs params 411 * @olcfg: cfg handle 412 * @cds_cfg: pointer to cds config 413 * 414 * Return: none 415 */ 416 static void 417 cds_cfg_update_ac_specs_params(struct txrx_pdev_cfg_param_t *olcfg, 418 struct cds_config_info *cds_cfg) 419 { 420 int i; 421 422 if (!olcfg) 423 return; 424 425 if (!cds_cfg) 426 return; 427 428 for (i = 0; i < QCA_WLAN_AC_ALL; i++) { 429 olcfg->ac_specs[i].wrr_skip_weight = 430 cds_cfg->ac_specs[i].wrr_skip_weight; 431 olcfg->ac_specs[i].credit_threshold = 432 cds_cfg->ac_specs[i].credit_threshold; 433 olcfg->ac_specs[i].send_limit = 434 cds_cfg->ac_specs[i].send_limit; 435 olcfg->ac_specs[i].credit_reserve = 436 cds_cfg->ac_specs[i].credit_reserve; 437 olcfg->ac_specs[i].discard_weight = 438 cds_cfg->ac_specs[i].discard_weight; 439 } 440 } 441 442 #if defined(QCA_LL_TX_FLOW_CONTROL_V2) || defined(QCA_LL_PDEV_TX_FLOW_CONTROL) 443 static inline void 444 cds_cdp_set_flow_control_params(struct wlan_objmgr_psoc *psoc, 445 struct txrx_pdev_cfg_param_t *cdp_cfg) 446 { 447 cdp_cfg->tx_flow_stop_queue_th = 448 cfg_get(psoc, CFG_DP_TX_FLOW_STOP_QUEUE_TH); 449 cdp_cfg->tx_flow_start_queue_offset = 450 cfg_get(psoc, CFG_DP_TX_FLOW_START_QUEUE_OFFSET); 451 } 452 #else 453 static inline void 454 cds_cdp_set_flow_control_params(struct wlan_objmgr_psoc *psoc, 455 struct txrx_pdev_cfg_param_t *cdp_cfg) 456 {} 457 #endif 458 459 #ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK 460 static inline void 461 cds_cdp_update_del_ack_params(struct wlan_objmgr_psoc *psoc, 462 struct txrx_pdev_cfg_param_t *cdp_cfg) 463 { 464 cdp_cfg->del_ack_enable = 465 cfg_get(psoc, CFG_DP_DRIVER_TCP_DELACK_ENABLE); 466 cdp_cfg->del_ack_pkt_count = 467 cfg_get(psoc, CFG_DP_DRIVER_TCP_DELACK_PKT_CNT); 468 cdp_cfg->del_ack_timer_value = 469 cfg_get(psoc, CFG_DP_DRIVER_TCP_DELACK_TIMER_VALUE); 470 } 471 #else 472 static inline void 473 cds_cdp_update_del_ack_params(struct wlan_objmgr_psoc *psoc, 474 struct txrx_pdev_cfg_param_t *cdp_cfg) 475 {} 476 #endif 477 478 #ifdef WLAN_SUPPORT_TXRX_HL_BUNDLE 479 static inline void 480 cds_cdp_update_bundle_params(struct wlan_objmgr_psoc *psoc, 481 struct txrx_pdev_cfg_param_t *cdp_cfg) 482 { 483 cdp_cfg->bundle_timer_value = 484 cfg_get(psoc, CFG_DP_HL_BUNDLE_TIMER_VALUE); 485 cdp_cfg->bundle_size = 486 cfg_get(psoc, CFG_DP_HL_BUNDLE_SIZE); 487 } 488 #else 489 static inline void 490 cds_cdp_update_bundle_params(struct wlan_objmgr_psoc *psoc, 491 struct txrx_pdev_cfg_param_t *cdp_cfg) 492 { 493 } 494 #endif 495 496 /** 497 * cds_cdp_cfg_attach() - attach data path config module 498 * @psoc: psoc handle 499 * 500 * Return: none 501 */ 502 static void cds_cdp_cfg_attach(struct wlan_objmgr_psoc *psoc) 503 { 504 struct txrx_pdev_cfg_param_t cdp_cfg = {0}; 505 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 506 uint32_t gro_bit_set; 507 508 cdp_cfg.is_full_reorder_offload = DP_REORDER_OFFLOAD_SUPPORT; 509 cdp_cfg.is_uc_offload_enabled = ucfg_ipa_uc_is_enabled(); 510 cdp_cfg.uc_tx_buffer_count = cfg_get(psoc, CFG_DP_IPA_UC_TX_BUF_COUNT); 511 cdp_cfg.uc_tx_buffer_size = 512 cfg_get(psoc, CFG_DP_IPA_UC_TX_BUF_SIZE); 513 cdp_cfg.uc_rx_indication_ring_count = 514 cfg_get(psoc, CFG_DP_IPA_UC_RX_IND_RING_COUNT); 515 cdp_cfg.uc_tx_partition_base = 516 cfg_get(psoc, CFG_DP_IPA_UC_TX_PARTITION_BASE); 517 cdp_cfg.enable_rxthread = ucfg_dp_is_rx_common_thread_enabled(psoc); 518 cdp_cfg.ip_tcp_udp_checksum_offload = 519 cfg_get(psoc, CFG_DP_TCP_UDP_CKSUM_OFFLOAD); 520 cdp_cfg.nan_ip_tcp_udp_checksum_offload = 521 cfg_get(psoc, CFG_DP_NAN_TCP_UDP_CKSUM_OFFLOAD); 522 cdp_cfg.p2p_ip_tcp_udp_checksum_offload = 523 cfg_get(psoc, CFG_DP_P2P_TCP_UDP_CKSUM_OFFLOAD); 524 cdp_cfg.legacy_mode_csum_disable = 525 cfg_get(psoc, CFG_DP_LEGACY_MODE_CSUM_DISABLE); 526 cdp_cfg.ce_classify_enabled = 527 cfg_get(psoc, CFG_DP_CE_CLASSIFY_ENABLE); 528 cdp_cfg.tso_enable = cfg_get(psoc, CFG_DP_TSO); 529 cdp_cfg.lro_enable = cfg_get(psoc, CFG_DP_LRO); 530 cdp_cfg.sg_enable = cfg_get(psoc, CFG_DP_SG); 531 cdp_cfg.enable_data_stall_detection = 532 cfg_get(psoc, CFG_DP_ENABLE_DATA_STALL_DETECTION); 533 gro_bit_set = cfg_get(psoc, CFG_DP_GRO); 534 if (gro_bit_set & DP_GRO_ENABLE_BIT_SET) 535 cdp_cfg.gro_enable = true; 536 cdp_cfg.enable_flow_steering = 537 cfg_get(psoc, CFG_DP_FLOW_STEERING_ENABLED); 538 cdp_cfg.disable_intra_bss_fwd = 539 cfg_get(psoc, CFG_DP_AP_STA_SECURITY_SEPERATION); 540 cdp_cfg.pktlog_buffer_size = 541 cfg_get(psoc, CFG_DP_PKTLOG_BUFFER_SIZE); 542 543 cds_cdp_update_del_ack_params(psoc, &cdp_cfg); 544 545 cds_cdp_update_bundle_params(psoc, &cdp_cfg); 546 547 gp_cds_context->cfg_ctx = cdp_cfg_attach(soc, gp_cds_context->qdf_ctx, 548 (void *)(&cdp_cfg)); 549 if (!gp_cds_context->cfg_ctx) { 550 cds_debug("failed to init cfg handle"); 551 return; 552 } 553 554 /* Configure Receive flow steering */ 555 cdp_cfg_set_flow_steering(soc, gp_cds_context->cfg_ctx, 556 cfg_get(psoc, CFG_DP_FLOW_STEERING_ENABLED)); 557 558 cds_cdp_set_flow_control_params(psoc, &cdp_cfg); 559 cdp_cfg_set_flow_control_parameters(soc, gp_cds_context->cfg_ctx, 560 (void *)&cdp_cfg); 561 562 /* adjust the cfg_ctx default value based on setting */ 563 cdp_cfg_set_rx_fwd_disabled(soc, gp_cds_context->cfg_ctx, 564 cfg_get(psoc, 565 CFG_DP_AP_STA_SECURITY_SEPERATION)); 566 567 /* 568 * adjust the packet log enable default value 569 * based on CFG INI setting 570 */ 571 cdp_cfg_set_packet_log_enabled(soc, gp_cds_context->cfg_ctx, 572 (uint8_t)cds_is_packet_log_enabled()); 573 574 /* adjust the ptp rx option default value based on CFG INI setting */ 575 cdp_cfg_set_ptp_rx_opt_enabled(soc, gp_cds_context->cfg_ctx, 576 (uint8_t)cds_is_ptp_rx_opt_enabled()); 577 } 578 static QDF_STATUS cds_register_all_modules(void) 579 { 580 QDF_STATUS status; 581 582 scheduler_register_wma_legacy_handler(&wma_mc_process_handler); 583 scheduler_register_sys_legacy_handler(&sys_mc_process_handler); 584 585 /* Register message queues in given order such that queue priority is 586 * intact: 587 * 1) QDF_MODULE_ID_SYS: Timer queue(legacy SYS queue) 588 * 2) QDF_MODULE_ID_TARGET_IF: Target interface queue 589 * 3) QDF_MODULE_ID_PE: Legacy PE message queue 590 * 4) QDF_MODULE_ID_SME: Legacy SME message queue 591 * 5) QDF_MODULE_ID_OS_IF: OS IF message queue for new components 592 */ 593 status = scheduler_register_module(QDF_MODULE_ID_SYS, 594 &scheduler_timer_q_mq_handler); 595 status = scheduler_register_module(QDF_MODULE_ID_TARGET_IF, 596 &scheduler_target_if_mq_handler); 597 status = scheduler_register_module(QDF_MODULE_ID_PE, 598 &pe_mc_process_handler); 599 status = scheduler_register_module(QDF_MODULE_ID_SME, 600 &sme_mc_process_handler); 601 status = scheduler_register_module(QDF_MODULE_ID_OS_IF, 602 &scheduler_os_if_mq_handler); 603 status = scheduler_register_module(QDF_MODULE_ID_SCAN, 604 &scheduler_scan_mq_handler); 605 return status; 606 } 607 608 static QDF_STATUS cds_deregister_all_modules(void) 609 { 610 QDF_STATUS status; 611 612 scheduler_deregister_wma_legacy_handler(); 613 scheduler_deregister_sys_legacy_handler(); 614 status = scheduler_deregister_module(QDF_MODULE_ID_SCAN); 615 status = scheduler_deregister_module(QDF_MODULE_ID_SYS); 616 status = scheduler_deregister_module(QDF_MODULE_ID_TARGET_IF); 617 status = scheduler_deregister_module(QDF_MODULE_ID_PE); 618 status = scheduler_deregister_module(QDF_MODULE_ID_SME); 619 status = scheduler_deregister_module(QDF_MODULE_ID_OS_IF); 620 621 return status; 622 } 623 624 /** 625 * cds_set_ac_specs_params() - set ac_specs params in cds_config_info 626 * @cds_cfg: Pointer to cds_config_info 627 * 628 * Return: none 629 */ 630 static void 631 cds_set_ac_specs_params(struct cds_config_info *cds_cfg) 632 { 633 int i; 634 struct cds_context *cds_ctx; 635 636 if (!cds_cfg) 637 return; 638 639 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); 640 if (!cds_ctx) 641 return; 642 643 for (i = 0; i < QCA_WLAN_AC_ALL; i++) { 644 cds_cfg->ac_specs[i] = cds_ctx->ac_specs[i]; 645 } 646 } 647 648 static int cds_hang_event_notifier_call(struct notifier_block *block, 649 unsigned long state, 650 void *data) 651 { 652 struct qdf_notifer_data *cds_hang_data = data; 653 uint32_t total_len; 654 struct cds_hang_event_fixed_param *cmd; 655 uint8_t *cds_hang_evt_buff; 656 657 if (!cds_hang_data) 658 return NOTIFY_STOP_MASK; 659 660 cds_hang_evt_buff = cds_hang_data->hang_data; 661 662 if (!cds_hang_evt_buff) 663 return NOTIFY_STOP_MASK; 664 665 total_len = sizeof(*cmd); 666 if (cds_hang_data->offset + total_len > QDF_WLAN_HANG_FW_OFFSET) 667 return NOTIFY_STOP_MASK; 668 669 cds_hang_evt_buff = cds_hang_data->hang_data + cds_hang_data->offset; 670 cmd = (struct cds_hang_event_fixed_param *)cds_hang_evt_buff; 671 QDF_HANG_EVT_SET_HDR(&cmd->tlv_header, HANG_EVT_TAG_CDS, 672 QDF_HANG_GET_STRUCT_TLVLEN(*cmd)); 673 674 cmd->recovery_reason = gp_cds_context->recovery_reason; 675 676 /* userspace expects a fixed format */ 677 qdf_mem_set(&cmd->driver_version, DRIVER_VER_LEN, ' '); 678 qdf_mem_copy(&cmd->driver_version, QWLAN_VERSIONSTR, 679 qdf_min(sizeof(QWLAN_VERSIONSTR) - 1, 680 (size_t)DRIVER_VER_LEN)); 681 682 /* userspace expects a fixed format */ 683 qdf_mem_set(&cmd->hang_event_version, HANG_EVENT_VER_LEN, ' '); 684 qdf_mem_copy(&cmd->hang_event_version, QDF_HANG_EVENT_VERSION, 685 qdf_min(sizeof(QDF_HANG_EVENT_VERSION) - 1, 686 (size_t)HANG_EVENT_VER_LEN)); 687 688 cds_hang_data->offset += total_len; 689 return NOTIFY_OK; 690 } 691 692 static qdf_notif_block cds_hang_event_notifier = { 693 .notif_block.notifier_call = cds_hang_event_notifier_call, 694 }; 695 696 /** 697 * cds_set_exclude_selftx_from_cca_busy_time() - Set exclude self tx time 698 * from cca busy time bool in cds config 699 * @exclude_selftx_from_cca_busy: Bool to be stored in cds config 700 * @cds_cfg: Pointer to cds config 701 * 702 * Return: None 703 */ 704 static void 705 cds_set_exclude_selftx_from_cca_busy_time(bool exclude_selftx_from_cca_busy, 706 struct cds_config_info *cds_cfg) 707 { 708 cds_cfg->exclude_selftx_from_cca_busy = exclude_selftx_from_cca_busy; 709 } 710 711 /** 712 * cds_open() - open the CDS Module 713 * 714 * cds_open() function opens the CDS Scheduler 715 * Upon successful initialization: 716 * - All CDS submodules should have been initialized 717 * 718 * - The CDS scheduler should have opened 719 * 720 * - All the WLAN SW components should have been opened. This includes 721 * SYS, MAC, SME, WMA and TL. 722 * @psoc: psoc handle 723 * 724 * Return: QDF status 725 */ 726 QDF_STATUS cds_open(struct wlan_objmgr_psoc *psoc) 727 { 728 QDF_STATUS status; 729 struct cds_config_info *cds_cfg; 730 qdf_device_t qdf_ctx; 731 struct htc_init_info htcInfo = { 0 }; 732 struct dp_txrx_soc_attach_params soc_attach_params = {0}; 733 struct ol_context *ol_ctx; 734 struct hif_opaque_softc *scn; 735 void *HTCHandle; 736 struct hdd_context *hdd_ctx; 737 struct cds_context *cds_ctx; 738 mac_handle_t mac_handle; 739 740 cds_debug("Opening CDS"); 741 742 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); 743 if (!cds_ctx) 744 return QDF_STATUS_E_FAILURE; 745 746 /* Initialize the timer module */ 747 qdf_timer_module_init(); 748 749 /* Initialize bug reporting structure */ 750 cds_init_log_completion(); 751 752 hdd_ctx = gp_cds_context->hdd_context; 753 if (!hdd_ctx || !hdd_ctx->config) { 754 cds_err("Hdd Context is Null"); 755 756 status = QDF_STATUS_E_FAILURE; 757 return status; 758 } 759 760 status = dispatcher_enable(); 761 if (QDF_IS_STATUS_ERROR(status)) { 762 cds_err("Failed to enable dispatcher; status:%d", status); 763 return status; 764 } 765 766 /* Now Open the CDS Scheduler */ 767 status = cds_sched_open(gp_cds_context, 768 &gp_cds_context->qdf_sched, 769 sizeof(cds_sched_context)); 770 if (QDF_IS_STATUS_ERROR(status)) { 771 cds_alert("Failed to open CDS Scheduler"); 772 goto err_dispatcher_disable; 773 } 774 775 scn = cds_get_context(QDF_MODULE_ID_HIF); 776 if (!scn) { 777 status = QDF_STATUS_E_FAILURE; 778 goto err_sched_close; 779 } 780 781 cds_cfg = cds_get_ini_config(); 782 if (!cds_cfg) { 783 cds_err("Cds config is NULL"); 784 785 status = QDF_STATUS_E_FAILURE; 786 goto err_sched_close; 787 } 788 789 hdd_enable_fastpath(hdd_ctx, scn); 790 791 /* Initialize BMI and Download firmware */ 792 ol_ctx = cds_get_context(QDF_MODULE_ID_BMI); 793 status = bmi_download_firmware(ol_ctx); 794 if (QDF_IS_STATUS_ERROR(status)) { 795 cds_alert("BMI FIALED status:%d", status); 796 goto err_bmi_close; 797 } 798 799 hdd_wlan_update_target_info(hdd_ctx, scn); 800 801 htcInfo.pContext = ol_ctx; 802 htcInfo.TargetFailure = ol_target_failure; 803 htcInfo.TargetSendSuspendComplete = 804 ucfg_pmo_psoc_target_suspend_acknowledge; 805 htcInfo.target_initial_wakeup_cb = ucfg_pmo_psoc_handle_initial_wake_up; 806 htcInfo.target_psoc = (void *)psoc; 807 htcInfo.cfg_wmi_credit_cnt = hdd_ctx->config->cfg_wmi_credit_cnt; 808 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 809 810 /* Create HTC */ 811 gp_cds_context->htc_ctx = 812 htc_create(scn, &htcInfo, qdf_ctx, cds_get_conparam()); 813 if (!gp_cds_context->htc_ctx) { 814 cds_alert("Failed to Create HTC"); 815 816 status = QDF_STATUS_E_FAILURE; 817 goto err_bmi_close; 818 } 819 ucfg_pmo_psoc_update_htc_handle(psoc, (void *)gp_cds_context->htc_ctx); 820 821 status = bmi_done(ol_ctx); 822 if (QDF_IS_STATUS_ERROR(status)) { 823 cds_alert("Failed to complete BMI phase"); 824 goto err_htc_close; 825 } 826 827 cds_set_exclude_selftx_from_cca_busy_time( 828 hdd_ctx->config->exclude_selftx_from_cca_busy, 829 cds_cfg); 830 /*Open the WMA module */ 831 status = wma_open(psoc, hdd_update_tgt_cfg, cds_cfg, 832 hdd_ctx->target_type); 833 if (QDF_IS_STATUS_ERROR(status)) { 834 cds_alert("Failed to open WMA module"); 835 goto err_htc_close; 836 } 837 838 /* Number of peers limit differs in each chip version. If peer max 839 * limit configured in ini exceeds more than supported, WMA adjusts 840 * and keeps correct limit in cds_cfg.max_station. So, make sure 841 * config entry hdd_ctx->config->maxNumberOfPeers has adjusted value 842 */ 843 /* In FTM mode cds_cfg->max_stations will be zero. On updating same 844 * into hdd context config entry, leads to pe_open() to fail, if 845 * con_mode change happens from FTM mode to any other mode. 846 */ 847 if (QDF_DRIVER_TYPE_PRODUCTION == cds_cfg->driver_type) 848 ucfg_mlme_set_sap_max_peers(psoc, cds_cfg->max_station); 849 850 HTCHandle = cds_get_context(QDF_MODULE_ID_HTC); 851 gp_cds_context->cfg_ctx = NULL; 852 if (!HTCHandle) { 853 status = QDF_STATUS_E_FAILURE; 854 goto err_wma_close; 855 } 856 857 status = htc_wait_target(HTCHandle); 858 if (QDF_IS_STATUS_ERROR(status)) { 859 cds_alert("Failed to complete BMI phase. status: %d", status); 860 QDF_BUG(status == QDF_STATUS_E_NOMEM || cds_is_fw_down()); 861 862 goto err_wma_close; 863 } 864 865 cds_debug("target_type %d 8074:%d 6290:%d 6390: %d 6490: %d 6750: %d", 866 hdd_ctx->target_type, 867 TARGET_TYPE_QCA8074, 868 TARGET_TYPE_QCA6290, 869 TARGET_TYPE_QCA6390, 870 TARGET_TYPE_QCA6490, 871 TARGET_TYPE_QCA6750); 872 873 /* Set default value to false */ 874 hdd_ctx->is_wifi3_0_target = false; 875 876 soc_attach_params.target_type = hdd_ctx->target_type; 877 soc_attach_params.target_psoc = htcInfo.target_psoc; 878 soc_attach_params.dp_ol_if_ops = &dp_ol_if_ops; 879 gp_cds_context->dp_soc = 880 ucfg_dp_txrx_soc_attach(&soc_attach_params, 881 &hdd_ctx->is_wifi3_0_target); 882 if (!gp_cds_context->dp_soc) { 883 status = QDF_STATUS_E_FAILURE; 884 goto err_wma_close; 885 } 886 887 wlan_psoc_set_dp_handle(psoc, gp_cds_context->dp_soc); 888 ucfg_dp_set_cmn_dp_handle(psoc, gp_cds_context->dp_soc); 889 ucfg_pmo_psoc_update_dp_handle(psoc, gp_cds_context->dp_soc); 890 ucfg_ocb_update_dp_handle(psoc, gp_cds_context->dp_soc); 891 892 cds_set_ac_specs_params(cds_cfg); 893 cds_cfg_update_ac_specs_params((struct txrx_pdev_cfg_param_t *) 894 gp_cds_context->cfg_ctx, cds_cfg); 895 cds_cdp_cfg_attach(psoc); 896 897 bmi_target_ready(scn, gp_cds_context->cfg_ctx); 898 899 /* Now proceed to open the MAC */ 900 status = mac_open(psoc, &mac_handle, 901 gp_cds_context->hdd_context, cds_cfg); 902 903 if (QDF_STATUS_SUCCESS != status) { 904 cds_alert("Failed to open MAC"); 905 goto err_soc_detach; 906 } 907 gp_cds_context->mac_context = mac_handle; 908 909 /* Now proceed to open the SME */ 910 status = sme_open(mac_handle); 911 if (QDF_IS_STATUS_ERROR(status)) { 912 cds_alert("Failed to open SME"); 913 goto err_mac_close; 914 } 915 916 cds_register_all_modules(); 917 918 status = dispatcher_psoc_open(psoc); 919 if (QDF_IS_STATUS_ERROR(status)) { 920 cds_alert("Failed to open PSOC Components"); 921 goto deregister_modules; 922 } 923 924 ucfg_mc_cp_stats_register_pmo_handler(); 925 qdf_hang_event_register_notifier(&cds_hang_event_notifier); 926 927 return QDF_STATUS_SUCCESS; 928 929 deregister_modules: 930 cds_deregister_all_modules(); 931 sme_close(mac_handle); 932 933 err_mac_close: 934 mac_close(mac_handle); 935 gp_cds_context->mac_context = NULL; 936 937 err_soc_detach: 938 ucfg_dp_txrx_soc_detach(gp_cds_context->dp_soc); 939 gp_cds_context->dp_soc = NULL; 940 941 ucfg_ocb_update_dp_handle(psoc, NULL); 942 ucfg_pmo_psoc_update_dp_handle(psoc, NULL); 943 wlan_psoc_set_dp_handle(psoc, NULL); 944 945 err_wma_close: 946 cds_shutdown_notifier_purge(); 947 wma_close(); 948 wma_wmi_service_close(); 949 950 err_htc_close: 951 if (gp_cds_context->htc_ctx) { 952 htc_destroy(gp_cds_context->htc_ctx); 953 gp_cds_context->htc_ctx = NULL; 954 ucfg_pmo_psoc_update_htc_handle(psoc, NULL); 955 } 956 957 err_bmi_close: 958 bmi_cleanup(ol_ctx); 959 960 err_sched_close: 961 if (QDF_IS_STATUS_ERROR(cds_sched_close())) 962 QDF_DEBUG_PANIC("Failed to close CDS Scheduler"); 963 964 err_dispatcher_disable: 965 if (QDF_IS_STATUS_ERROR(dispatcher_disable())) 966 QDF_DEBUG_PANIC("Failed to disable dispatcher"); 967 968 return status; 969 } /* cds_open() */ 970 971 QDF_STATUS cds_dp_open(struct wlan_objmgr_psoc *psoc) 972 { 973 QDF_STATUS qdf_status; 974 struct dp_txrx_config dp_config; 975 struct hdd_context *hdd_ctx; 976 977 hdd_ctx = gp_cds_context->hdd_context; 978 if (!hdd_ctx) { 979 cds_err("HDD context is null"); 980 return QDF_STATUS_E_FAILURE; 981 } 982 983 qdf_status = 984 ucfg_dp_txrx_pdev_attach(cds_get_context(QDF_MODULE_ID_SOC)); 985 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 986 /* Critical Error ... Cannot proceed further */ 987 cds_alert("Failed to open TXRX"); 988 QDF_ASSERT(0); 989 goto close; 990 } 991 992 if (hdd_ctx->target_type == TARGET_TYPE_QCA6290 || 993 hdd_ctx->target_type == TARGET_TYPE_QCA6390 || 994 hdd_ctx->target_type == TARGET_TYPE_QCA6490 || 995 hdd_ctx->target_type == TARGET_TYPE_QCA6750 || 996 hdd_ctx->target_type == TARGET_TYPE_KIWI || 997 hdd_ctx->target_type == TARGET_TYPE_MANGO || 998 hdd_ctx->target_type == TARGET_TYPE_PEACH || 999 hdd_ctx->target_type == TARGET_TYPE_WCN6450) { 1000 qdf_status = cdp_pdev_init(cds_get_context(QDF_MODULE_ID_SOC), 1001 gp_cds_context->htc_ctx, 1002 gp_cds_context->qdf_ctx, 0); 1003 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1004 /* Critical Error ... Cannot proceed further */ 1005 cds_alert("Failed to init TXRX"); 1006 QDF_ASSERT(0); 1007 goto pdev_detach; 1008 } 1009 } 1010 1011 if (cdp_txrx_intr_attach(gp_cds_context->dp_soc) 1012 != QDF_STATUS_SUCCESS) { 1013 cds_alert("Failed to attach interrupts"); 1014 goto pdev_deinit; 1015 } 1016 1017 dp_config.enable_rx_threads = 1018 (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) ? 1019 false : gp_cds_context->cds_cfg->enable_dp_rx_threads; 1020 1021 qdf_status = ucfg_dp_txrx_init(cds_get_context(QDF_MODULE_ID_SOC), 1022 OL_TXRX_PDEV_ID, 1023 &dp_config); 1024 1025 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) 1026 goto intr_close; 1027 1028 ucfg_pmo_psoc_set_txrx_pdev_id(psoc, OL_TXRX_PDEV_ID); 1029 ucfg_ocb_set_txrx_pdev_id(psoc, OL_TXRX_PDEV_ID); 1030 1031 cdp_set_rtpm_tput_policy_requirement(cds_get_context(QDF_MODULE_ID_SOC), 1032 false); 1033 1034 cds_debug("CDS successfully Opened"); 1035 1036 if (cdp_cfg_get(gp_cds_context->dp_soc, cfg_dp_tc_based_dyn_gro_enable)) 1037 ucfg_dp_set_tc_based_dyn_gro(psoc, true); 1038 else 1039 ucfg_dp_set_tc_based_dyn_gro(psoc, false); 1040 1041 ucfg_dp_set_tc_ingress_prio(psoc, cdp_cfg_get(gp_cds_context->dp_soc, 1042 cfg_dp_tc_ingress_prio)); 1043 1044 return 0; 1045 1046 intr_close: 1047 cdp_txrx_intr_detach(gp_cds_context->dp_soc); 1048 1049 pdev_deinit: 1050 cdp_pdev_deinit(gp_cds_context->dp_soc, 1051 OL_TXRX_PDEV_ID, false); 1052 1053 pdev_detach: 1054 ucfg_dp_txrx_pdev_detach(gp_cds_context->dp_soc, OL_TXRX_PDEV_ID, 1055 false); 1056 1057 close: 1058 return QDF_STATUS_E_FAILURE; 1059 } 1060 1061 /** 1062 * cds_should_suspend_target() - Get value whether target can suspend 1063 * 1064 * Return: true if target can suspend, otherwise false 1065 */ 1066 static bool cds_should_suspend_target(void) 1067 { 1068 struct hif_opaque_softc *hif_ctx; 1069 struct hif_target_info *tgt_info; 1070 uint32_t target_type = TARGET_TYPE_UNKNOWN; 1071 1072 /* don't suspend during SSR */ 1073 if (cds_is_driver_recovering()) 1074 return false; 1075 1076 /* don't suspend if the driver is in a bad state */ 1077 if (cds_is_driver_in_bad_state()) 1078 return false; 1079 1080 /* if we are in any mode other than FTM we should suspend */ 1081 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) 1082 return true; 1083 1084 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 1085 if (hif_ctx) { 1086 tgt_info = hif_get_target_info_handle(hif_ctx); 1087 if (tgt_info) 1088 target_type = tgt_info->target_type; 1089 } 1090 1091 /* 1092 * for most target we also want to suspend in FTM mode, 1093 * but some targets do not support that. 1094 */ 1095 if (target_type == TARGET_TYPE_AR6320 || 1096 target_type == TARGET_TYPE_AR6320V1 || 1097 target_type == TARGET_TYPE_AR6320V2 || 1098 target_type == TARGET_TYPE_AR6320V3 || 1099 target_type == TARGET_TYPE_QCN7605) 1100 return false; 1101 1102 /* target should support suspend in FTM mode */ 1103 return true; 1104 } 1105 1106 #ifdef HIF_USB 1107 static inline void cds_suspend_target(tp_wma_handle wma_handle) 1108 { 1109 QDF_STATUS status; 1110 /* Suspend the target and disable interrupt */ 1111 status = ucfg_pmo_psoc_suspend_target(wma_handle->psoc, 0); 1112 if (status) 1113 cds_err("Failed to suspend target, status = %d", status); 1114 } 1115 #else 1116 static inline void cds_suspend_target(tp_wma_handle wma_handle) 1117 { 1118 QDF_STATUS status; 1119 /* Suspend the target and disable interrupt */ 1120 status = ucfg_pmo_psoc_suspend_target(wma_handle->psoc, 1); 1121 if (status) 1122 cds_err("Failed to suspend target, status = %d", status); 1123 } 1124 #endif /* HIF_USB */ 1125 1126 /** 1127 * cds_pre_enable() - pre enable cds 1128 * 1129 * Return: QDF status 1130 */ 1131 QDF_STATUS cds_pre_enable(void) 1132 { 1133 QDF_STATUS status; 1134 int errno; 1135 void *scn; 1136 void *soc; 1137 void *hif_ctx; 1138 1139 cds_enter(); 1140 1141 if (!gp_cds_context) { 1142 cds_err("cds context is null"); 1143 return QDF_STATUS_E_INVAL; 1144 } 1145 1146 if (!gp_cds_context->wma_context) { 1147 cds_err("wma context is null"); 1148 return QDF_STATUS_E_INVAL; 1149 } 1150 1151 scn = cds_get_context(QDF_MODULE_ID_HIF); 1152 if (!scn) 1153 return QDF_STATUS_E_INVAL; 1154 1155 soc = cds_get_context(QDF_MODULE_ID_SOC); 1156 if (!soc) 1157 return QDF_STATUS_E_INVAL; 1158 1159 /* call Packetlog connect service */ 1160 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam() && 1161 QDF_GLOBAL_EPPING_MODE != cds_get_conparam()) 1162 cdp_pkt_log_con_service(soc, OL_TXRX_PDEV_ID, 1163 scn); 1164 1165 /*call WMA pre start */ 1166 status = wma_pre_start(); 1167 if (QDF_IS_STATUS_ERROR(status)) { 1168 cds_err("Failed to WMA prestart"); 1169 goto exit_pkt_log; 1170 } 1171 1172 status = htc_start(gp_cds_context->htc_ctx); 1173 if (QDF_IS_STATUS_ERROR(status)) { 1174 cds_err("Failed to Start HTC"); 1175 goto exit_pkt_log; 1176 } 1177 1178 status = wma_wait_for_ready_event(gp_cds_context->wma_context); 1179 if (QDF_IS_STATUS_ERROR(status)) { 1180 cds_err("Failed to wait for ready event; status: %u", status); 1181 goto stop_wmi; 1182 } 1183 1184 errno = cdp_pdev_post_attach(soc, OL_TXRX_PDEV_ID); 1185 if (errno) { 1186 cds_err("Failed to attach pdev"); 1187 status = qdf_status_from_os_return(errno); 1188 goto stop_wmi; 1189 } 1190 1191 return QDF_STATUS_SUCCESS; 1192 1193 stop_wmi: 1194 /* Send pdev suspend to fw otherwise FW is not aware that 1195 * host is freeing resources. 1196 */ 1197 if (!(cds_is_driver_recovering() || cds_is_driver_in_bad_state())) 1198 cds_suspend_target(gp_cds_context->wma_context); 1199 1200 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 1201 1202 wma_wmi_stop(); 1203 1204 if (hif_ctx) { 1205 cds_err("Disable the isr & reset the soc!"); 1206 hif_disable_isr(hif_ctx); 1207 hif_reset_soc(hif_ctx); 1208 } 1209 htc_stop(gp_cds_context->htc_ctx); 1210 1211 wma_wmi_work_close(); 1212 1213 exit_pkt_log: 1214 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam() && 1215 QDF_GLOBAL_EPPING_MODE != cds_get_conparam()) 1216 cdp_pkt_log_exit(soc, OL_TXRX_PDEV_ID); 1217 1218 return status; 1219 } 1220 1221 QDF_STATUS cds_enable(struct wlan_objmgr_psoc *psoc) 1222 { 1223 QDF_STATUS qdf_status; 1224 struct mac_start_params mac_params; 1225 1226 /* We support only one instance for now ... */ 1227 if (!gp_cds_context) { 1228 cds_err("Invalid CDS context"); 1229 return QDF_STATUS_E_FAILURE; 1230 } 1231 1232 if (!gp_cds_context->wma_context) { 1233 cds_err("WMA NULL context"); 1234 return QDF_STATUS_E_FAILURE; 1235 } 1236 1237 if (!gp_cds_context->mac_context) { 1238 cds_err("MAC NULL context"); 1239 return QDF_STATUS_E_FAILURE; 1240 } 1241 1242 /* Start the wma */ 1243 qdf_status = wma_start(); 1244 if (qdf_status != QDF_STATUS_SUCCESS) { 1245 cds_err("Failed to start wma; status:%d", qdf_status); 1246 return QDF_STATUS_E_FAILURE; 1247 } 1248 1249 /* Start the MAC */ 1250 qdf_mem_zero(&mac_params, sizeof(mac_params)); 1251 mac_params.driver_type = QDF_DRIVER_TYPE_PRODUCTION; 1252 qdf_status = mac_start(gp_cds_context->mac_context, &mac_params); 1253 1254 if (QDF_STATUS_SUCCESS != qdf_status) { 1255 cds_err("Failed to start MAC; status:%d", qdf_status); 1256 goto err_wma_stop; 1257 } 1258 1259 /* START SME */ 1260 qdf_status = sme_start(gp_cds_context->mac_context); 1261 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1262 cds_err("Failed to start SME; status:%d", qdf_status); 1263 goto err_mac_stop; 1264 } 1265 1266 qdf_status = 1267 ucfg_dp_txrx_attach_target(cds_get_context(QDF_MODULE_ID_SOC), 1268 OL_TXRX_PDEV_ID); 1269 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1270 cds_err("Failed to attach DP target; status:%d", qdf_status); 1271 goto err_sme_stop; 1272 } 1273 1274 qdf_status = dispatcher_psoc_enable(psoc); 1275 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1276 cds_err("dispatcher_psoc_enable failed; status:%d", qdf_status); 1277 goto err_soc_target_detach; 1278 } 1279 1280 /* Trigger psoc enable for CLD components */ 1281 hdd_component_psoc_enable(psoc); 1282 1283 return QDF_STATUS_SUCCESS; 1284 1285 err_soc_target_detach: 1286 /* NOOP */ 1287 1288 err_sme_stop: 1289 sme_stop(gp_cds_context->mac_context); 1290 1291 err_mac_stop: 1292 mac_stop(gp_cds_context->mac_context); 1293 1294 err_wma_stop: 1295 qdf_status = wma_stop(); 1296 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1297 cds_err("Failed to stop wma"); 1298 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 1299 } 1300 1301 return QDF_STATUS_E_FAILURE; 1302 } /* cds_enable() */ 1303 1304 /** 1305 * cds_disable() - stop/disable cds module 1306 * @psoc: Psoc pointer 1307 * 1308 * Return: QDF status 1309 */ 1310 QDF_STATUS cds_disable(struct wlan_objmgr_psoc *psoc) 1311 { 1312 QDF_STATUS qdf_status; 1313 void *handle; 1314 1315 /* PSOC disable for all new components. It needs to happen before 1316 * target is PDEV suspended such that a component can abort all its 1317 * ongoing transaction with FW. Always keep it before wma_stop() as 1318 * wma_stop() does target PDEV suspend. 1319 */ 1320 1321 /* Trigger psoc disable for CLD components */ 1322 if (psoc) { 1323 hdd_component_psoc_disable(psoc); 1324 dispatcher_psoc_disable(psoc); 1325 } 1326 1327 qdf_status = wma_stop(); 1328 1329 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1330 cds_err("Failed to stop wma"); 1331 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 1332 } 1333 1334 handle = cds_get_context(QDF_MODULE_ID_PE); 1335 if (!handle) 1336 return QDF_STATUS_E_INVAL; 1337 1338 umac_stop(); 1339 1340 return qdf_status; 1341 } 1342 1343 /** 1344 * cds_post_disable() - post disable cds module 1345 * 1346 * Return: QDF status 1347 */ 1348 QDF_STATUS cds_post_disable(void) 1349 { 1350 tp_wma_handle wma_handle; 1351 struct hif_opaque_softc *hif_ctx; 1352 struct scheduler_ctx *sched_ctx; 1353 QDF_STATUS qdf_status; 1354 1355 wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 1356 if (!wma_handle) 1357 return QDF_STATUS_E_INVAL; 1358 1359 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); 1360 if (!hif_ctx) 1361 return QDF_STATUS_E_INVAL; 1362 1363 /* flush any unprocessed scheduler messages */ 1364 sched_ctx = scheduler_get_context(); 1365 if (sched_ctx) { 1366 qdf_status = scheduler_disable(); 1367 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1368 cds_err("Failed to disable scheduler"); 1369 return QDF_STATUS_E_INVAL; 1370 } 1371 } 1372 /* 1373 * With new state machine changes cds_close can be invoked without 1374 * cds_disable. So, send the following clean up prerequisites to fw, 1375 * So Fw and host are in sync for cleanup indication: 1376 * - Send PDEV_SUSPEND indication to firmware 1377 * - Disable HIF Interrupts. 1378 * - Clean up CE tasklets. 1379 */ 1380 1381 cds_debug("send deinit sequence to firmware"); 1382 if (cds_should_suspend_target()) 1383 cds_suspend_target(wma_handle); 1384 hif_disable_isr(hif_ctx); 1385 hif_reset_soc(hif_ctx); 1386 1387 if (gp_cds_context->htc_ctx) { 1388 wma_wmi_stop(); 1389 htc_stop(gp_cds_context->htc_ctx); 1390 } 1391 1392 qdf_status = cds_close_rx_thread(); 1393 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1394 cds_err("Failed to close RX thread!"); 1395 return QDF_STATUS_E_INVAL; 1396 } 1397 1398 cdp_pdev_pre_detach(cds_get_context(QDF_MODULE_ID_SOC), 1399 OL_TXRX_PDEV_ID, 1); 1400 1401 return QDF_STATUS_SUCCESS; 1402 } 1403 1404 /** 1405 * cds_close() - close cds module 1406 * @psoc: Psoc pointer 1407 * 1408 * This API allows user to close modules registered 1409 * with connectivity device services. 1410 * 1411 * Return: QDF status 1412 */ 1413 QDF_STATUS cds_close(struct wlan_objmgr_psoc *psoc) 1414 { 1415 QDF_STATUS qdf_status; 1416 1417 qdf_hang_event_unregister_notifier(&cds_hang_event_notifier); 1418 qdf_status = cds_sched_close(); 1419 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 1420 if (QDF_IS_STATUS_ERROR(qdf_status)) 1421 cds_err("Failed to close CDS Scheduler"); 1422 1423 dispatcher_psoc_close(psoc); 1424 1425 qdf_flush_work(&gp_cds_context->cds_recovery_work); 1426 1427 cds_shutdown_notifier_purge(); 1428 1429 qdf_status = wma_wmi_work_close(); 1430 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1431 cds_err("Failed to close wma_wmi_work"); 1432 QDF_ASSERT(0); 1433 } 1434 1435 if (gp_cds_context->htc_ctx) { 1436 htc_destroy(gp_cds_context->htc_ctx); 1437 ucfg_pmo_psoc_update_htc_handle(psoc, NULL); 1438 gp_cds_context->htc_ctx = NULL; 1439 } 1440 1441 qdf_status = sme_close(gp_cds_context->mac_context); 1442 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1443 cds_err("Failed to close SME"); 1444 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 1445 } 1446 1447 qdf_status = mac_close(gp_cds_context->mac_context); 1448 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1449 cds_err("Failed to close MAC"); 1450 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 1451 } 1452 1453 gp_cds_context->mac_context = NULL; 1454 1455 ucfg_dp_txrx_soc_detach(gp_cds_context->dp_soc); 1456 gp_cds_context->dp_soc = NULL; 1457 1458 ucfg_pmo_psoc_update_dp_handle(psoc, NULL); 1459 wlan_psoc_set_dp_handle(psoc, NULL); 1460 1461 1462 qdf_status = wma_close(); 1463 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1464 cds_err("Failed to close wma"); 1465 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 1466 } 1467 1468 qdf_status = wma_wmi_service_close(); 1469 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 1470 cds_err("Failed to close wma_wmi_service"); 1471 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); 1472 } 1473 1474 cds_deinit_ini_config(); 1475 qdf_timer_module_deinit(); 1476 1477 cds_deregister_all_modules(); 1478 1479 return QDF_STATUS_SUCCESS; 1480 } 1481 1482 QDF_STATUS cds_dp_close(struct wlan_objmgr_psoc *psoc) 1483 { 1484 cdp_txrx_intr_detach(gp_cds_context->dp_soc); 1485 1486 qdf_nbuf_stop_replenish_timer(); 1487 1488 ucfg_dp_txrx_deinit(cds_get_context(QDF_MODULE_ID_SOC)); 1489 1490 cdp_pdev_deinit(cds_get_context(QDF_MODULE_ID_SOC), OL_TXRX_PDEV_ID, 1); 1491 1492 ucfg_dp_txrx_pdev_detach(cds_get_context(QDF_MODULE_ID_SOC), 1493 OL_TXRX_PDEV_ID, 1); 1494 1495 ucfg_pmo_psoc_set_txrx_pdev_id(psoc, OL_TXRX_INVALID_PDEV_ID); 1496 1497 return QDF_STATUS_SUCCESS; 1498 } 1499 1500 void *__cds_get_context(QDF_MODULE_ID module_id, const char *func) 1501 { 1502 void *context = NULL; 1503 1504 if (!gp_cds_context) { 1505 cds_err("cds context pointer is null (via %s)", func); 1506 return NULL; 1507 } 1508 1509 switch (module_id) { 1510 case QDF_MODULE_ID_HDD: 1511 { 1512 context = gp_cds_context->hdd_context; 1513 break; 1514 } 1515 1516 case QDF_MODULE_ID_SME: 1517 case QDF_MODULE_ID_PE: 1518 { 1519 /* In all these cases, we just return the MAC Context */ 1520 context = gp_cds_context->mac_context; 1521 break; 1522 } 1523 1524 case QDF_MODULE_ID_WMA: 1525 { 1526 /* For wma module */ 1527 context = gp_cds_context->wma_context; 1528 break; 1529 } 1530 1531 case QDF_MODULE_ID_QDF: 1532 { 1533 /* For SYS this is CDS itself */ 1534 context = gp_cds_context; 1535 break; 1536 } 1537 1538 case QDF_MODULE_ID_HIF: 1539 { 1540 context = gp_cds_context->hif_context; 1541 break; 1542 } 1543 1544 case QDF_MODULE_ID_HTC: 1545 { 1546 context = gp_cds_context->htc_ctx; 1547 break; 1548 } 1549 1550 case QDF_MODULE_ID_QDF_DEVICE: 1551 { 1552 context = gp_cds_context->qdf_ctx; 1553 break; 1554 } 1555 1556 case QDF_MODULE_ID_BMI: 1557 { 1558 context = gp_cds_context->g_ol_context; 1559 break; 1560 } 1561 1562 case QDF_MODULE_ID_CFG: 1563 { 1564 context = gp_cds_context->cfg_ctx; 1565 break; 1566 } 1567 1568 case QDF_MODULE_ID_SOC: 1569 { 1570 context = gp_cds_context->dp_soc; 1571 break; 1572 } 1573 1574 default: 1575 { 1576 cds_err("Module ID %d does not have its context maintained by CDS (via %s)", 1577 module_id, func); 1578 QDF_ASSERT(0); 1579 return NULL; 1580 } 1581 } 1582 1583 if (!context) 1584 cds_err("Module ID %d context is Null (via %s)", 1585 module_id, func); 1586 1587 return context; 1588 } /* cds_get_context() */ 1589 1590 /** 1591 * cds_get_global_context() - get CDS global Context 1592 * 1593 * This API allows any user to get the CDS Global Context pointer from a 1594 * module context data area. 1595 * 1596 * Return: pointer to the CDS global context, NULL if the function is 1597 * unable to retrieve the CDS context. 1598 */ 1599 void *cds_get_global_context(void) 1600 { 1601 if (!gp_cds_context) { 1602 /* 1603 * To avoid recursive call, this should not change to 1604 * QDF_TRACE(). 1605 */ 1606 pr_err("%s: global cds context is NULL", __func__); 1607 } 1608 1609 return gp_cds_context; 1610 } /* cds_get_global_context() */ 1611 1612 /** 1613 * cds_get_driver_state() - Get current driver state 1614 * 1615 * This API returns current driver state stored in global context. 1616 * 1617 * Return: Driver state enum 1618 */ 1619 enum cds_driver_state cds_get_driver_state(void) 1620 { 1621 if (!gp_cds_context) { 1622 cds_err("global cds context is NULL"); 1623 1624 return CDS_DRIVER_STATE_UNINITIALIZED; 1625 } 1626 1627 return gp_cds_context->driver_state; 1628 } 1629 1630 /** 1631 * cds_set_driver_state() - Set current driver state 1632 * @state: Driver state to be set to. 1633 * 1634 * This API sets driver state to state. This API only sets the state and doesn't 1635 * clear states, please make sure to use cds_clear_driver_state to clear any 1636 * state if required. 1637 * 1638 * Return: None 1639 */ 1640 void cds_set_driver_state(enum cds_driver_state state) 1641 { 1642 if (!gp_cds_context) { 1643 cds_err("global cds context is NULL: %x", state); 1644 1645 return; 1646 } 1647 1648 gp_cds_context->driver_state |= state; 1649 } 1650 1651 /** 1652 * cds_clear_driver_state() - Clear current driver state 1653 * @state: Driver state to be cleared. 1654 * 1655 * This API clears driver state. This API only clears the state, please make 1656 * sure to use cds_set_driver_state to set any new states. 1657 * 1658 * Return: None 1659 */ 1660 void cds_clear_driver_state(enum cds_driver_state state) 1661 { 1662 if (!gp_cds_context) { 1663 cds_err("global cds context is NULL: %x", state); 1664 1665 return; 1666 } 1667 1668 gp_cds_context->driver_state &= ~state; 1669 } 1670 1671 /** 1672 * cds_alloc_context() - allocate a context within the CDS global Context 1673 * @module_id: module ID who's context area is being allocated. 1674 * @module_context: pointer to location where the pointer to the 1675 * allocated context is returned. Note this output pointer 1676 * is valid only if the API returns QDF_STATUS_SUCCESS 1677 * @size: size of the context area to be allocated. 1678 * 1679 * This API allows any user to allocate a user context area within the 1680 * CDS Global Context. 1681 * 1682 * Return: QDF status 1683 */ 1684 QDF_STATUS cds_alloc_context(QDF_MODULE_ID module_id, 1685 void **module_context, uint32_t size) 1686 { 1687 void **cds_mod_context = NULL; 1688 1689 if (!gp_cds_context) { 1690 cds_err("cds context is null"); 1691 return QDF_STATUS_E_FAILURE; 1692 } 1693 1694 if (!module_context) { 1695 cds_err("null param passed"); 1696 return QDF_STATUS_E_FAILURE; 1697 } 1698 1699 switch (module_id) { 1700 case QDF_MODULE_ID_WMA: 1701 cds_mod_context = &gp_cds_context->wma_context; 1702 break; 1703 1704 case QDF_MODULE_ID_HIF: 1705 cds_mod_context = &gp_cds_context->hif_context; 1706 break; 1707 1708 case QDF_MODULE_ID_BMI: 1709 cds_mod_context = &gp_cds_context->g_ol_context; 1710 break; 1711 1712 default: 1713 cds_err("Module ID %i does not have its context allocated by CDS", 1714 module_id); 1715 QDF_ASSERT(0); 1716 return QDF_STATUS_E_INVAL; 1717 } 1718 1719 if (*cds_mod_context) { 1720 /* Context has already been allocated! 1721 * Prevent double allocation 1722 */ 1723 cds_err("Module ID %i context has already been allocated", 1724 module_id); 1725 return QDF_STATUS_E_EXISTS; 1726 } 1727 1728 /* Dynamically allocate the context for module */ 1729 1730 *module_context = qdf_mem_malloc(size); 1731 1732 if (!*module_context) { 1733 cds_err("Failed to allocate Context for module ID %i", 1734 module_id); 1735 QDF_ASSERT(0); 1736 return QDF_STATUS_E_NOMEM; 1737 } 1738 1739 *cds_mod_context = *module_context; 1740 1741 return QDF_STATUS_SUCCESS; 1742 } /* cds_alloc_context() */ 1743 1744 /** 1745 * cds_set_context() - API to set context in global CDS Context 1746 * @module_id: Module ID 1747 * @context: Pointer to the Module Context 1748 * 1749 * API to set a MODULE Context in global CDS Context 1750 * 1751 * Return: QDF_STATUS 1752 */ 1753 QDF_STATUS cds_set_context(QDF_MODULE_ID module_id, void *context) 1754 { 1755 struct cds_context *p_cds_context = cds_get_global_context(); 1756 1757 if (!p_cds_context) { 1758 cds_err("cds context is Invalid"); 1759 return QDF_STATUS_NOT_INITIALIZED; 1760 } 1761 1762 switch (module_id) { 1763 case QDF_MODULE_ID_HDD: 1764 p_cds_context->hdd_context = context; 1765 break; 1766 case QDF_MODULE_ID_HIF: 1767 p_cds_context->hif_context = context; 1768 break; 1769 default: 1770 cds_err("Module ID %i does not have its context managed by CDS", 1771 module_id); 1772 QDF_ASSERT(0); 1773 return QDF_STATUS_E_INVAL; 1774 } 1775 1776 return QDF_STATUS_SUCCESS; 1777 } 1778 1779 /** 1780 * cds_free_context() - free an allocated context within the 1781 * CDS global Context 1782 * @module_id: module ID who's context area is being free 1783 * @module_context: pointer to module context area to be free'd. 1784 * 1785 * This API allows a user to free the user context area within the 1786 * CDS Global Context. 1787 * 1788 * Return: QDF status 1789 */ 1790 QDF_STATUS cds_free_context(QDF_MODULE_ID module_id, void *module_context) 1791 { 1792 void **cds_mod_context = NULL; 1793 1794 if (!gp_cds_context) { 1795 cds_err("cds context is null"); 1796 return QDF_STATUS_E_FAILURE; 1797 } 1798 1799 if (!module_context) { 1800 cds_err("Null param"); 1801 return QDF_STATUS_E_FAILURE; 1802 } 1803 1804 switch (module_id) { 1805 case QDF_MODULE_ID_WMA: 1806 cds_mod_context = &gp_cds_context->wma_context; 1807 break; 1808 1809 case QDF_MODULE_ID_HIF: 1810 cds_mod_context = &gp_cds_context->hif_context; 1811 break; 1812 1813 case QDF_MODULE_ID_BMI: 1814 cds_mod_context = &gp_cds_context->g_ol_context; 1815 break; 1816 1817 default: 1818 cds_err("Module ID %i does not have its context allocated by CDS", 1819 module_id); 1820 QDF_ASSERT(0); 1821 return QDF_STATUS_E_INVAL; 1822 } 1823 1824 if (!*cds_mod_context) { 1825 /* Context has not been allocated or freed already! */ 1826 cds_err("Module ID %i context has not been allocated or freed already", 1827 module_id); 1828 return QDF_STATUS_E_FAILURE; 1829 } 1830 1831 if (*cds_mod_context != module_context) { 1832 cds_err("cds_mod_context != module_context"); 1833 return QDF_STATUS_E_FAILURE; 1834 } 1835 1836 qdf_mem_free(module_context); 1837 1838 *cds_mod_context = NULL; 1839 1840 return QDF_STATUS_SUCCESS; 1841 } /* cds_free_context() */ 1842 1843 1844 /** 1845 * cds_flush_work() - flush pending works 1846 * @work: pointer to work 1847 * 1848 * Return: none 1849 */ 1850 void cds_flush_work(void *work) 1851 { 1852 cancel_work_sync(work); 1853 } 1854 1855 /** 1856 * cds_flush_delayed_work() - flush delayed works 1857 * @dwork: pointer to delayed work 1858 * 1859 * Return: none 1860 */ 1861 void cds_flush_delayed_work(void *dwork) 1862 { 1863 cancel_delayed_work_sync(dwork); 1864 } 1865 1866 #ifndef REMOVE_PKT_LOG 1867 /** 1868 * cds_is_packet_log_enabled() - check if packet log is enabled 1869 * 1870 * Return: true if packet log is enabled else false 1871 */ 1872 bool cds_is_packet_log_enabled(void) 1873 { 1874 struct hdd_context *hdd_ctx; 1875 1876 hdd_ctx = gp_cds_context->hdd_context; 1877 if ((!hdd_ctx) || (!hdd_ctx->config)) { 1878 cds_alert("Hdd Context is Null"); 1879 return false; 1880 } 1881 return hdd_ctx->config->enable_packet_log; 1882 } 1883 #endif 1884 1885 static int cds_force_assert_target_via_pld(qdf_device_t qdf) 1886 { 1887 int errno; 1888 1889 errno = pld_force_assert_target(qdf->dev); 1890 if (errno == -EOPNOTSUPP) 1891 cds_info("PLD does not support target force assert"); 1892 else if (errno) 1893 cds_err("Failed PLD target force assert; errno %d", errno); 1894 else 1895 cds_info("Target force assert triggered via PLD"); 1896 1897 return errno; 1898 } 1899 1900 static QDF_STATUS cds_force_assert_target_via_wmi(qdf_device_t qdf) 1901 { 1902 QDF_STATUS status; 1903 t_wma_handle *wma; 1904 1905 wma = cds_get_context(QDF_MODULE_ID_WMA); 1906 if (!wma) 1907 return QDF_STATUS_E_INVAL; 1908 1909 status = wma_crash_inject(wma, RECOVERY_SIM_SELF_RECOVERY, 0); 1910 if (QDF_IS_STATUS_ERROR(status)) { 1911 cds_err("Failed target force assert; status %d", status); 1912 return status; 1913 } 1914 1915 status = qdf_wait_for_event_completion(&wma->recovery_event, 1916 WMA_CRASH_INJECT_TIMEOUT); 1917 if (QDF_IS_STATUS_ERROR(status)) { 1918 cds_err("Failed target force assert wait; status %d", status); 1919 return status; 1920 } 1921 1922 return QDF_STATUS_SUCCESS; 1923 } 1924 1925 /** 1926 * cds_force_assert_target() - Send assert command to firmware 1927 * @qdf: QDF device instance to assert 1928 * 1929 * An out-of-band recovery mechanism will cleanup and restart the entire wlan 1930 * subsystem in the event of a firmware crash. This API injects a firmware 1931 * crash to start this process when the wlan driver is known to be in a bad 1932 * state. If a firmware assert inject fails, the wlan driver will schedule 1933 * the driver recovery anyway, as a best effort attempt to return to a working 1934 * state. 1935 * 1936 * Return: QDF_STATUS 1937 */ 1938 static QDF_STATUS cds_force_assert_target(qdf_device_t qdf) 1939 { 1940 int errno; 1941 QDF_STATUS status; 1942 1943 /* first, try target assert inject via pld */ 1944 errno = cds_force_assert_target_via_pld(qdf); 1945 if (!errno) 1946 return QDF_STATUS_SUCCESS; 1947 if (errno != -EOPNOTSUPP) 1948 return QDF_STATUS_E_FAILURE; 1949 1950 /* pld assert is not supported, try target assert inject via wmi */ 1951 status = cds_force_assert_target_via_wmi(qdf); 1952 if (QDF_IS_STATUS_SUCCESS(status)) 1953 return QDF_STATUS_SUCCESS; 1954 1955 /* wmi assert failed, start recovery without the firmware assert */ 1956 cds_err("Scheduling recovery work without firmware assert"); 1957 pld_schedule_recovery_work(qdf->dev, PLD_REASON_DEFAULT); 1958 1959 return status; 1960 } 1961 1962 /** 1963 * cds_trigger_recovery_handler() - handle a self recovery request 1964 * @func: the name of the function that called cds_trigger_recovery 1965 * @line: the line number of the call site which called cds_trigger_recovery 1966 * 1967 * Return: none 1968 */ 1969 static void cds_trigger_recovery_handler(const char *func, const uint32_t line) 1970 { 1971 QDF_STATUS status; 1972 qdf_runtime_lock_t rtl; 1973 qdf_device_t qdf; 1974 bool ssr_ini_enabled = cds_is_self_recovery_enabled(); 1975 1976 /* NOTE! This code path is delicate! Think very carefully before 1977 * modifying the content or order of the following. Please review any 1978 * potential changes with someone closely familiar with this feature. 1979 */ 1980 1981 if (cds_is_driver_recovering()) { 1982 cds_info("WLAN recovery already in progress"); 1983 return; 1984 } 1985 1986 if (cds_is_driver_in_bad_state()) { 1987 cds_info("WLAN has already failed recovery"); 1988 return; 1989 } 1990 1991 if (cds_is_fw_down()) { 1992 cds_info("Firmware has already initiated recovery"); 1993 return; 1994 } 1995 1996 qdf = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 1997 if (!qdf) 1998 return; 1999 2000 /* 2001 * if *wlan* recovery is disabled, crash here for debugging for 2002 * snoc/IPCI targets. 2003 */ 2004 if ((qdf->bus_type == QDF_BUS_TYPE_SNOC || 2005 qdf->bus_type == QDF_BUS_TYPE_IPCI) && !ssr_ini_enabled) { 2006 QDF_DEBUG_PANIC("WLAN recovery is not enabled (via %s:%d)", 2007 func, line); 2008 return; 2009 } 2010 2011 if (cds_is_driver_unloading()) { 2012 QDF_DEBUG_PANIC("WLAN is unloading recovery not expected(via %s:%d)", 2013 func, line); 2014 return; 2015 } 2016 2017 status = qdf_runtime_lock_init(&rtl); 2018 if (QDF_IS_STATUS_ERROR(status)) { 2019 cds_err("qdf_runtime_lock_init failed, status: %d", status); 2020 return; 2021 } 2022 2023 status = qdf_runtime_pm_prevent_suspend(&rtl); 2024 if (QDF_IS_STATUS_ERROR(status)) { 2025 cds_err("Failed to acquire runtime pm lock"); 2026 goto deinit_rtl; 2027 } 2028 2029 cds_err("critical host timeout trigger fw recovery for reason code %d", 2030 gp_cds_context->recovery_reason); 2031 2032 cds_set_recovery_in_progress(true); 2033 cds_set_assert_target_in_progress(true); 2034 if (pld_force_collect_target_dump(qdf->dev)) 2035 cds_force_assert_target(qdf); 2036 cds_set_assert_target_in_progress(false); 2037 2038 /* Do not wait for firmware down block wmi transactions */ 2039 wma_wmi_stop(); 2040 2041 /* 2042 * if *wlan* recovery is disabled, once all the required registers are 2043 * read via the platform driver check and crash the system. 2044 */ 2045 if (qdf->bus_type == QDF_BUS_TYPE_PCI && !ssr_ini_enabled) 2046 QDF_DEBUG_PANIC("WLAN recovery is not enabled (via %s:%d)", 2047 func, line); 2048 2049 status = qdf_runtime_pm_allow_suspend(&rtl); 2050 if (QDF_IS_STATUS_ERROR(status)) 2051 cds_err("Failed to release runtime pm lock"); 2052 2053 deinit_rtl: 2054 qdf_runtime_lock_deinit(&rtl); 2055 } 2056 2057 static void cds_trigger_recovery_work(void *context) 2058 { 2059 struct cds_recovery_call_info *call_info = context; 2060 2061 cds_trigger_recovery_handler(call_info->func, call_info->line); 2062 } 2063 2064 void __cds_trigger_recovery(enum qdf_hang_reason reason, const char *func, 2065 const uint32_t line) 2066 { 2067 if (!gp_cds_context) { 2068 cds_err("gp_cds_context is null"); 2069 return; 2070 } 2071 2072 gp_cds_context->recovery_reason = reason; 2073 2074 __cds_recovery_caller.func = func; 2075 __cds_recovery_caller.line = line; 2076 qdf_queue_work(0, gp_cds_context->cds_recovery_wq, 2077 &gp_cds_context->cds_recovery_work); 2078 } 2079 2080 void cds_trigger_recovery_psoc(void *psoc, enum qdf_hang_reason reason, 2081 const char *func, const uint32_t line) 2082 { 2083 __cds_trigger_recovery(reason, func, line); 2084 } 2085 2086 2087 /** 2088 * cds_get_recovery_reason() - get self recovery reason 2089 * @reason: recovery reason 2090 * 2091 * Return: None 2092 */ 2093 void cds_get_recovery_reason(enum qdf_hang_reason *reason) 2094 { 2095 if (!gp_cds_context) { 2096 cds_err("gp_cds_context is null"); 2097 return; 2098 } 2099 2100 *reason = gp_cds_context->recovery_reason; 2101 } 2102 2103 /** 2104 * cds_reset_recovery_reason() - reset the reason to unspecified 2105 * 2106 * Return: None 2107 */ 2108 void cds_reset_recovery_reason(void) 2109 { 2110 if (!gp_cds_context) { 2111 cds_err("gp_cds_context is null"); 2112 return; 2113 } 2114 2115 gp_cds_context->recovery_reason = QDF_REASON_UNSPECIFIED; 2116 } 2117 2118 /** 2119 * cds_set_wakelock_logging() - Logging of wakelock enabled/disabled 2120 * @value: Boolean value 2121 * 2122 * This function is used to set the flag which will indicate whether 2123 * logging of wakelock is enabled or not 2124 * 2125 * Return: None 2126 */ 2127 void cds_set_wakelock_logging(bool value) 2128 { 2129 struct cds_context *p_cds_context; 2130 2131 p_cds_context = cds_get_global_context(); 2132 if (!p_cds_context) { 2133 cds_err("cds context is Invalid"); 2134 return; 2135 } 2136 p_cds_context->is_wakelock_log_enabled = value; 2137 } 2138 2139 /** 2140 * cds_is_wakelock_enabled() - Check if logging of wakelock is enabled/disabled 2141 * 2142 * This function is used to check whether logging of wakelock is enabled or not 2143 * 2144 * Return: true if logging of wakelock is enabled 2145 */ 2146 bool cds_is_wakelock_enabled(void) 2147 { 2148 struct cds_context *p_cds_context; 2149 2150 p_cds_context = cds_get_global_context(); 2151 if (!p_cds_context) { 2152 cds_err("cds context is Invalid"); 2153 return false; 2154 } 2155 return p_cds_context->is_wakelock_log_enabled; 2156 } 2157 2158 /** 2159 * cds_set_ring_log_level() - Sets the log level of a particular ring 2160 * @ring_id: ring_id 2161 * @log_level: Log level specified 2162 * 2163 * This function converts HLOS values to driver log levels and sets the log 2164 * level of a particular ring accordingly. 2165 * 2166 * Return: None 2167 */ 2168 void cds_set_ring_log_level(uint32_t ring_id, uint32_t log_level) 2169 { 2170 struct cds_context *p_cds_context; 2171 uint32_t log_val; 2172 2173 p_cds_context = cds_get_global_context(); 2174 if (!p_cds_context) { 2175 cds_err("cds context is Invalid"); 2176 return; 2177 } 2178 2179 switch (log_level) { 2180 case LOG_LEVEL_NO_COLLECTION: 2181 log_val = WLAN_LOG_LEVEL_OFF; 2182 break; 2183 case LOG_LEVEL_NORMAL_COLLECT: 2184 log_val = WLAN_LOG_LEVEL_NORMAL; 2185 break; 2186 case LOG_LEVEL_ISSUE_REPRO: 2187 log_val = WLAN_LOG_LEVEL_REPRO; 2188 break; 2189 case LOG_LEVEL_ACTIVE: 2190 default: 2191 log_val = WLAN_LOG_LEVEL_ACTIVE; 2192 break; 2193 } 2194 2195 if (ring_id == RING_ID_WAKELOCK) { 2196 p_cds_context->wakelock_log_level = log_val; 2197 return; 2198 } else if (ring_id == RING_ID_CONNECTIVITY) { 2199 p_cds_context->connectivity_log_level = log_val; 2200 return; 2201 } else if (ring_id == RING_ID_PER_PACKET_STATS) { 2202 p_cds_context->packet_stats_log_level = log_val; 2203 return; 2204 } else if (ring_id == RING_ID_DRIVER_DEBUG) { 2205 p_cds_context->driver_debug_log_level = log_val; 2206 return; 2207 } else if (ring_id == RING_ID_FIRMWARE_DEBUG) { 2208 p_cds_context->fw_debug_log_level = log_val; 2209 return; 2210 } 2211 } 2212 2213 /** 2214 * cds_get_ring_log_level() - Get the a ring id's log level 2215 * @ring_id: Ring id 2216 * 2217 * Fetch and return the log level corresponding to a ring id 2218 * 2219 * Return: Log level corresponding to the ring ID 2220 */ 2221 enum wifi_driver_log_level cds_get_ring_log_level(uint32_t ring_id) 2222 { 2223 struct cds_context *p_cds_context; 2224 2225 p_cds_context = cds_get_global_context(); 2226 if (!p_cds_context) { 2227 cds_err("cds context is Invalid"); 2228 return WLAN_LOG_LEVEL_OFF; 2229 } 2230 2231 if (ring_id == RING_ID_WAKELOCK) 2232 return p_cds_context->wakelock_log_level; 2233 else if (ring_id == RING_ID_CONNECTIVITY) 2234 return p_cds_context->connectivity_log_level; 2235 else if (ring_id == RING_ID_PER_PACKET_STATS) 2236 return p_cds_context->packet_stats_log_level; 2237 else if (ring_id == RING_ID_DRIVER_DEBUG) 2238 return p_cds_context->driver_debug_log_level; 2239 else if (ring_id == RING_ID_FIRMWARE_DEBUG) 2240 return p_cds_context->fw_debug_log_level; 2241 2242 return WLAN_LOG_LEVEL_OFF; 2243 } 2244 2245 /** 2246 * cds_set_multicast_logging() - Set mutlicast logging value 2247 * @value: Value of multicast logging 2248 * 2249 * Set the multicast logging value which will indicate 2250 * whether to multicast host and fw messages even 2251 * without any registration by userspace entity 2252 * 2253 * Return: None 2254 */ 2255 void cds_set_multicast_logging(uint8_t value) 2256 { 2257 cds_multicast_logging = value; 2258 } 2259 2260 /** 2261 * cds_is_multicast_logging() - Get multicast logging value 2262 * 2263 * Get the multicast logging value which will indicate 2264 * whether to multicast host and fw messages even 2265 * without any registration by userspace entity 2266 * 2267 * Return: 0 - Multicast logging disabled, 1 - Multicast logging enabled 2268 */ 2269 uint8_t cds_is_multicast_logging(void) 2270 { 2271 return cds_multicast_logging; 2272 } 2273 2274 /* 2275 * cds_init_log_completion() - Initialize log param structure 2276 * 2277 * This function is used to initialize the logging related 2278 * parameters 2279 * 2280 * Return: None 2281 */ 2282 void cds_init_log_completion(void) 2283 { 2284 struct cds_context *p_cds_context; 2285 2286 p_cds_context = cds_get_global_context(); 2287 if (!p_cds_context) { 2288 cds_err("cds context is Invalid"); 2289 return; 2290 } 2291 2292 p_cds_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; 2293 p_cds_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; 2294 p_cds_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; 2295 p_cds_context->log_complete.is_report_in_progress = false; 2296 } 2297 2298 /** 2299 * cds_set_log_completion() - Store the logging params 2300 * @is_fatal: Indicates if the event triggering bug report is fatal or not 2301 * @indicator: Source which triggered the bug report 2302 * @reason_code: Reason for triggering bug report 2303 * @recovery_needed: If recovery is needed after bug report 2304 * 2305 * This function is used to set the logging parameters based on the 2306 * caller 2307 * 2308 * Return: 0 if setting of params is successful 2309 */ 2310 QDF_STATUS cds_set_log_completion(uint32_t is_fatal, 2311 uint32_t indicator, 2312 uint32_t reason_code, 2313 bool recovery_needed) 2314 { 2315 struct cds_context *p_cds_context; 2316 2317 p_cds_context = cds_get_global_context(); 2318 if (!p_cds_context) { 2319 cds_err("cds context is Invalid"); 2320 return QDF_STATUS_E_FAILURE; 2321 } 2322 2323 qdf_spinlock_acquire(&p_cds_context->bug_report_lock); 2324 p_cds_context->log_complete.is_fatal = is_fatal; 2325 p_cds_context->log_complete.indicator = indicator; 2326 p_cds_context->log_complete.reason_code = reason_code; 2327 p_cds_context->log_complete.recovery_needed = recovery_needed; 2328 p_cds_context->log_complete.is_report_in_progress = true; 2329 qdf_spinlock_release(&p_cds_context->bug_report_lock); 2330 cds_debug("is_fatal %d indicator %d reason_code %d recovery needed %d", 2331 is_fatal, indicator, reason_code, recovery_needed); 2332 2333 return QDF_STATUS_SUCCESS; 2334 } 2335 2336 /** 2337 * cds_get_and_reset_log_completion() - Get and reset logging related params 2338 * @is_fatal: Indicates if the event triggering bug report is fatal or not 2339 * @indicator: Source which triggered the bug report 2340 * @reason_code: Reason for triggering bug report 2341 * @recovery_needed: If recovery is needed after bug report 2342 * 2343 * This function is used to get the logging related parameters 2344 * 2345 * Return: None 2346 */ 2347 void cds_get_and_reset_log_completion(uint32_t *is_fatal, 2348 uint32_t *indicator, 2349 uint32_t *reason_code, 2350 bool *recovery_needed) 2351 { 2352 struct cds_context *p_cds_context; 2353 2354 p_cds_context = cds_get_global_context(); 2355 if (!p_cds_context) { 2356 cds_err("cds context is Invalid"); 2357 return; 2358 } 2359 2360 qdf_spinlock_acquire(&p_cds_context->bug_report_lock); 2361 *is_fatal = p_cds_context->log_complete.is_fatal; 2362 *indicator = p_cds_context->log_complete.indicator; 2363 *reason_code = p_cds_context->log_complete.reason_code; 2364 *recovery_needed = p_cds_context->log_complete.recovery_needed; 2365 2366 /* reset */ 2367 p_cds_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; 2368 p_cds_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; 2369 p_cds_context->log_complete.is_report_in_progress = false; 2370 p_cds_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; 2371 p_cds_context->log_complete.recovery_needed = false; 2372 qdf_spinlock_release(&p_cds_context->bug_report_lock); 2373 } 2374 2375 /** 2376 * cds_is_log_report_in_progress() - Check if bug reporting is in progress 2377 * 2378 * This function is used to check if the bug reporting is already in progress 2379 * 2380 * Return: true if the bug reporting is in progress 2381 */ 2382 bool cds_is_log_report_in_progress(void) 2383 { 2384 struct cds_context *p_cds_context; 2385 2386 p_cds_context = cds_get_global_context(); 2387 if (!p_cds_context) { 2388 cds_err("cds context is Invalid"); 2389 return true; 2390 } 2391 return p_cds_context->log_complete.is_report_in_progress; 2392 } 2393 2394 /** 2395 * cds_is_fatal_event_enabled() - Return if fatal event is enabled 2396 * 2397 * Return true if fatal event is enabled. 2398 */ 2399 bool cds_is_fatal_event_enabled(void) 2400 { 2401 struct cds_context *p_cds_context; 2402 2403 p_cds_context = cds_get_global_context(); 2404 if (!p_cds_context) { 2405 cds_err("cds context is Invalid"); 2406 return false; 2407 } 2408 2409 2410 return p_cds_context->enable_fatal_event; 2411 } 2412 2413 #ifdef WLAN_FEATURE_TSF_PLUS_SOCK_TS 2414 bool cds_is_ptp_rx_opt_enabled(void) 2415 { 2416 struct hdd_context *hdd_ctx; 2417 struct cds_context *p_cds_context; 2418 2419 p_cds_context = cds_get_global_context(); 2420 if (!p_cds_context) { 2421 cds_err("cds context is Invalid"); 2422 return false; 2423 } 2424 2425 hdd_ctx = (struct hdd_context *)(p_cds_context->hdd_context); 2426 if ((!hdd_ctx) || (!hdd_ctx->config)) { 2427 cds_err("Hdd Context is Null"); 2428 return false; 2429 } 2430 2431 return hdd_tsf_is_rx_set(hdd_ctx); 2432 } 2433 2434 bool cds_is_ptp_tx_opt_enabled(void) 2435 { 2436 struct hdd_context *hdd_ctx; 2437 struct cds_context *p_cds_context; 2438 2439 p_cds_context = cds_get_global_context(); 2440 if (!p_cds_context) { 2441 cds_err("cds context is Invalid"); 2442 return false; 2443 } 2444 2445 hdd_ctx = (struct hdd_context *)(p_cds_context->hdd_context); 2446 if ((!hdd_ctx) || (!hdd_ctx->config)) { 2447 cds_err("Hdd Context is Null"); 2448 return false; 2449 } 2450 2451 return hdd_tsf_is_tx_set(hdd_ctx); 2452 } 2453 #endif 2454 2455 /** 2456 * cds_get_log_indicator() - Get the log flush indicator 2457 * 2458 * This function is used to get the log flush indicator 2459 * 2460 * Return: log indicator 2461 */ 2462 uint32_t cds_get_log_indicator(void) 2463 { 2464 struct cds_context *p_cds_context; 2465 uint32_t indicator; 2466 2467 p_cds_context = cds_get_global_context(); 2468 if (!p_cds_context) { 2469 cds_err("cds context is Invalid"); 2470 return WLAN_LOG_INDICATOR_UNUSED; 2471 } 2472 2473 if (cds_is_load_or_unload_in_progress() || 2474 cds_is_driver_recovering() || cds_is_driver_in_bad_state()) { 2475 return WLAN_LOG_INDICATOR_UNUSED; 2476 } 2477 2478 qdf_spinlock_acquire(&p_cds_context->bug_report_lock); 2479 indicator = p_cds_context->log_complete.indicator; 2480 qdf_spinlock_release(&p_cds_context->bug_report_lock); 2481 return indicator; 2482 } 2483 2484 /** 2485 * cds_wlan_flush_host_logs_for_fatal() - Wrapper to flush host logs 2486 * 2487 * This function is used to send signal to the logger thread to 2488 * flush the host logs. 2489 * 2490 * Return: None 2491 * 2492 */ 2493 void cds_wlan_flush_host_logs_for_fatal(void) 2494 { 2495 if (cds_is_log_report_in_progress()) 2496 wlan_flush_host_logs_for_fatal(); 2497 } 2498 2499 /** 2500 * cds_flush_logs() - Report fatal event to userspace 2501 * @is_fatal: Indicates if the event triggering bug report is fatal or not 2502 * @indicator: Source which triggered the bug report 2503 * @reason_code: Reason for triggering bug report 2504 * @dump_mac_trace: If mac trace are needed in logs. 2505 * @recovery_needed: If recovery is needed after bug report 2506 * 2507 * This function sets the log related params and send the WMI command to the 2508 * FW to flush its logs. On receiving the flush completion event from the FW 2509 * the same will be conveyed to userspace 2510 * 2511 * Return: 0 on success 2512 */ 2513 QDF_STATUS cds_flush_logs(uint32_t is_fatal, 2514 uint32_t indicator, 2515 uint32_t reason_code, 2516 bool dump_mac_trace, 2517 bool recovery_needed) 2518 { 2519 QDF_STATUS status; 2520 2521 struct cds_context *p_cds_context; 2522 2523 p_cds_context = cds_get_global_context(); 2524 if (!p_cds_context) { 2525 cds_err("cds context is Invalid"); 2526 return QDF_STATUS_E_FAILURE; 2527 } 2528 if (!p_cds_context->enable_fatal_event) { 2529 cds_err("Fatal event not enabled"); 2530 return QDF_STATUS_E_FAILURE; 2531 } 2532 if (cds_is_load_or_unload_in_progress() || 2533 cds_is_driver_recovering() || cds_is_driver_in_bad_state()) { 2534 cds_err("un/Load/SSR in progress"); 2535 return QDF_STATUS_E_FAILURE; 2536 } 2537 2538 if (cds_is_log_report_in_progress()) { 2539 cds_err("Bug report already in progress - dropping! type:%d, indicator=%d reason_code=%d", 2540 is_fatal, indicator, reason_code); 2541 return QDF_STATUS_E_FAILURE; 2542 } 2543 2544 status = cds_set_log_completion(is_fatal, indicator, 2545 reason_code, recovery_needed); 2546 if (QDF_STATUS_SUCCESS != status) { 2547 cds_err("Failed to set log trigger params"); 2548 return QDF_STATUS_E_FAILURE; 2549 } 2550 2551 cds_debug("Triggering bug report: type:%d, indicator=%d reason_code=%d", 2552 is_fatal, indicator, reason_code); 2553 2554 if (dump_mac_trace) 2555 qdf_trace_dump_all(p_cds_context->mac_context, 0, 0, 100, 0); 2556 2557 if (WLAN_LOG_INDICATOR_HOST_ONLY == indicator) { 2558 cds_wlan_flush_host_logs_for_fatal(); 2559 return QDF_STATUS_SUCCESS; 2560 } 2561 2562 status = sme_send_flush_logs_cmd_to_fw(); 2563 if (QDF_IS_STATUS_ERROR(status)) { 2564 cds_err("Failed to send flush FW log"); 2565 cds_init_log_completion(); 2566 return QDF_STATUS_E_FAILURE; 2567 } 2568 2569 return QDF_STATUS_SUCCESS; 2570 } 2571 2572 /** 2573 * cds_logging_set_fw_flush_complete() - Wrapper for FW log flush completion 2574 * 2575 * This function is used to send signal to the logger thread to indicate 2576 * that the flushing of FW logs is complete by the FW 2577 * 2578 * Return: None 2579 * 2580 */ 2581 void cds_logging_set_fw_flush_complete(void) 2582 { 2583 if (cds_is_fatal_event_enabled()) 2584 wlan_logging_set_fw_flush_complete(); 2585 } 2586 2587 /** 2588 * cds_set_fatal_event() - set fatal event status 2589 * @value: pending statue to set 2590 * 2591 * Return: None 2592 */ 2593 void cds_set_fatal_event(bool value) 2594 { 2595 struct cds_context *p_cds_context; 2596 2597 p_cds_context = cds_get_global_context(); 2598 if (!p_cds_context) { 2599 cds_err("cds context is Invalid"); 2600 return; 2601 } 2602 p_cds_context->enable_fatal_event = value; 2603 } 2604 2605 /** 2606 * cds_get_radio_index() - get radio index 2607 * 2608 * Return: radio index otherwise, -EINVAL 2609 */ 2610 int cds_get_radio_index(void) 2611 { 2612 struct cds_context *p_cds_context; 2613 2614 p_cds_context = cds_get_global_context(); 2615 if (!p_cds_context) { 2616 /* 2617 * To avoid recursive call, this should not change to 2618 * QDF_TRACE(). 2619 */ 2620 pr_err("%s: cds context is invalid\n", __func__); 2621 return -EINVAL; 2622 } 2623 2624 return p_cds_context->radio_index; 2625 } 2626 2627 /** 2628 * cds_set_radio_index() - set radio index 2629 * @radio_index: the radio index to set 2630 * 2631 * Return: QDF status 2632 */ 2633 QDF_STATUS cds_set_radio_index(int radio_index) 2634 { 2635 struct cds_context *p_cds_context; 2636 2637 p_cds_context = cds_get_global_context(); 2638 if (!p_cds_context) { 2639 pr_err("%s: cds context is invalid\n", __func__); 2640 return QDF_STATUS_E_FAILURE; 2641 } 2642 2643 p_cds_context->radio_index = radio_index; 2644 2645 return QDF_STATUS_SUCCESS; 2646 } 2647 2648 /** 2649 * cds_init_ini_config() - API to initialize CDS configuration parameters 2650 * @cfg: CDS Configuration 2651 * 2652 * Return: void 2653 */ 2654 2655 void cds_init_ini_config(struct cds_config_info *cfg) 2656 { 2657 struct cds_context *cds_ctx; 2658 2659 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); 2660 if (!cds_ctx) 2661 return; 2662 2663 cds_ctx->cds_cfg = cfg; 2664 } 2665 2666 /** 2667 * cds_deinit_ini_config() - API to free CDS configuration parameters 2668 * 2669 * Return: void 2670 */ 2671 void cds_deinit_ini_config(void) 2672 { 2673 struct cds_context *cds_ctx; 2674 struct cds_config_info *cds_cfg; 2675 2676 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); 2677 if (!cds_ctx) 2678 return; 2679 2680 cds_cfg = cds_ctx->cds_cfg; 2681 cds_ctx->cds_cfg = NULL; 2682 2683 if (cds_cfg) 2684 qdf_mem_free(cds_cfg); 2685 } 2686 2687 /** 2688 * cds_get_ini_config() - API to get CDS configuration parameters 2689 * 2690 * Return: cds config structure 2691 */ 2692 struct cds_config_info *cds_get_ini_config(void) 2693 { 2694 struct cds_context *cds_ctx; 2695 2696 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); 2697 if (!cds_ctx) 2698 return NULL; 2699 2700 return cds_ctx->cds_cfg; 2701 } 2702 2703 /** 2704 * cds_is_5_mhz_enabled() - API to get 5MHZ enabled 2705 * 2706 * Return: true if 5 mhz is enabled, false otherwise 2707 */ 2708 bool cds_is_5_mhz_enabled(void) 2709 { 2710 struct cds_context *p_cds_context; 2711 2712 p_cds_context = cds_get_context(QDF_MODULE_ID_QDF); 2713 if (!p_cds_context) 2714 return false; 2715 2716 if (p_cds_context->cds_cfg) 2717 return (p_cds_context->cds_cfg->sub_20_channel_width == 2718 WLAN_SUB_20_CH_WIDTH_5); 2719 2720 return false; 2721 } 2722 2723 /** 2724 * cds_is_10_mhz_enabled() - API to get 10-MHZ enabled 2725 * 2726 * Return: true if 10 mhz is enabled, false otherwise 2727 */ 2728 bool cds_is_10_mhz_enabled(void) 2729 { 2730 struct cds_context *p_cds_context; 2731 2732 p_cds_context = cds_get_context(QDF_MODULE_ID_QDF); 2733 if (!p_cds_context) 2734 return false; 2735 2736 if (p_cds_context->cds_cfg) 2737 return (p_cds_context->cds_cfg->sub_20_channel_width == 2738 WLAN_SUB_20_CH_WIDTH_10); 2739 2740 return false; 2741 } 2742 2743 /** 2744 * cds_is_sub_20_mhz_enabled() - API to get sub 20-MHZ enabled 2745 * 2746 * Return: true if 5 or 10 mhz is enabled, false otherwise 2747 */ 2748 bool cds_is_sub_20_mhz_enabled(void) 2749 { 2750 struct cds_context *p_cds_context; 2751 2752 p_cds_context = cds_get_context(QDF_MODULE_ID_QDF); 2753 if (!p_cds_context) 2754 return false; 2755 2756 if (p_cds_context->cds_cfg) 2757 return p_cds_context->cds_cfg->sub_20_channel_width; 2758 2759 return false; 2760 } 2761 2762 /** 2763 * cds_is_self_recovery_enabled() - API to get self recovery enabled 2764 * 2765 * Return: true if self recovery enabled, false otherwise 2766 */ 2767 bool cds_is_self_recovery_enabled(void) 2768 { 2769 struct cds_context *p_cds_context; 2770 2771 p_cds_context = cds_get_context(QDF_MODULE_ID_QDF); 2772 if (!p_cds_context) 2773 return false; 2774 2775 if (p_cds_context->cds_cfg) 2776 return p_cds_context->cds_cfg->self_recovery_enabled; 2777 2778 return false; 2779 } 2780 2781 /** 2782 * cds_is_fw_down() - Is FW down or not 2783 * 2784 * Return: true if FW is down and false otherwise. 2785 */ 2786 bool cds_is_fw_down(void) 2787 { 2788 qdf_device_t qdf_ctx; 2789 2790 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 2791 if (!qdf_ctx) 2792 return false; 2793 2794 return pld_is_fw_down(qdf_ctx->dev); 2795 } 2796 2797 /** 2798 * cds_svc_fw_shutdown_ind() - API to send userspace about FW crash 2799 * 2800 * @dev: Device Pointer 2801 * 2802 * Return: None 2803 */ 2804 void cds_svc_fw_shutdown_ind(struct device *dev) 2805 { 2806 hdd_svc_fw_shutdown_ind(dev); 2807 } 2808 2809 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE 2810 /* 2811 * cds_pkt_stats_to_logger_thread() - send pktstats to user 2812 * @pl_hdr: Pointer to pl_hdr 2813 * @pkt_dump: Pointer to pkt_dump data structure. 2814 * @data: Pointer to data 2815 * 2816 * This function is used to send the pkt stats to SVC module. 2817 * 2818 * Return: None 2819 */ 2820 inline void cds_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, 2821 void *data) 2822 { 2823 if (cds_get_ring_log_level(RING_ID_PER_PACKET_STATS) != 2824 WLAN_LOG_LEVEL_ACTIVE) 2825 return; 2826 2827 wlan_pkt_stats_to_logger_thread(pl_hdr, pkt_dump, data); 2828 } 2829 #endif 2830 2831 /** 2832 * cds_get_conparam() - Get the connection mode parameters 2833 * 2834 * Return the connection mode parameter set by insmod or set during statically 2835 * linked driver 2836 * 2837 * Return: enum QDF_GLOBAL_MODE 2838 */ 2839 enum QDF_GLOBAL_MODE cds_get_conparam(void) 2840 { 2841 enum QDF_GLOBAL_MODE con_mode; 2842 2843 con_mode = hdd_get_conparam(); 2844 2845 return con_mode; 2846 } 2847 2848 #ifdef FEATURE_HTC_CREDIT_HISTORY 2849 inline void 2850 cds_print_htc_credit_history(uint32_t count, qdf_abstract_print *print, 2851 void *print_priv) 2852 { 2853 htc_print_credit_history(gp_cds_context->htc_ctx, count, 2854 print, print_priv); 2855 } 2856 #endif 2857 2858 #ifdef FEATURE_ALIGN_STATS_FROM_DP 2859 /** 2860 * cds_get_cdp_vdev_stats() - Function which retrieves cdp vdev stats 2861 * @vdev_id: vdev id 2862 * @vdev_stats: cdp vdev stats retrieves from DP 2863 * 2864 * Return: If get cdp vdev stats success return true, otherwise return false 2865 */ 2866 static bool 2867 cds_get_cdp_vdev_stats(uint8_t vdev_id, struct cdp_vdev_stats *vdev_stats) 2868 { 2869 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 2870 2871 if (!vdev_stats) 2872 return false; 2873 2874 if (cdp_host_get_vdev_stats(soc, vdev_id, vdev_stats, true)) 2875 return false; 2876 2877 return true; 2878 } 2879 2880 bool 2881 cds_dp_get_vdev_stats(uint8_t vdev_id, struct cds_vdev_dp_stats *stats) 2882 { 2883 struct cdp_vdev_stats *vdev_stats; 2884 bool ret = false; 2885 2886 vdev_stats = qdf_mem_malloc(sizeof(*vdev_stats)); 2887 if (!vdev_stats) 2888 return false; 2889 2890 if (cds_get_cdp_vdev_stats(vdev_id, vdev_stats)) { 2891 stats->tx_retries = vdev_stats->tx.retries; 2892 stats->tx_retries_mpdu = vdev_stats->tx.retries_mpdu; 2893 stats->tx_mpdu_success_with_retries = 2894 vdev_stats->tx.mpdu_success_with_retries; 2895 ret = true; 2896 } 2897 2898 qdf_mem_free(vdev_stats); 2899 return ret; 2900 } 2901 #endif 2902 2903 #ifdef ENABLE_SMMU_S1_TRANSLATION 2904 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) 2905 QDF_STATUS cds_smmu_mem_map_setup(qdf_device_t osdev, bool ipa_present) 2906 { 2907 struct iommu_domain *domain; 2908 bool ipa_smmu_enabled; 2909 bool wlan_smmu_enabled; 2910 2911 domain = pld_smmu_get_domain(osdev->dev); 2912 if (domain) { 2913 int attr = 0; 2914 int errno = qdf_iommu_domain_get_attr(domain, 2915 QDF_DOMAIN_ATTR_S1_BYPASS, 2916 &attr); 2917 2918 wlan_smmu_enabled = !errno && !attr; 2919 } else { 2920 cds_info("No SMMU mapping present"); 2921 wlan_smmu_enabled = false; 2922 } 2923 2924 if (!wlan_smmu_enabled) { 2925 osdev->smmu_s1_enabled = false; 2926 goto exit_with_success; 2927 } 2928 2929 if (!ipa_present) { 2930 osdev->smmu_s1_enabled = true; 2931 goto exit_with_success; 2932 } 2933 2934 ipa_smmu_enabled = qdf_get_ipa_smmu_enabled(); 2935 2936 osdev->smmu_s1_enabled = ipa_smmu_enabled && wlan_smmu_enabled; 2937 if (ipa_smmu_enabled != wlan_smmu_enabled) { 2938 cds_err("SMMU mismatch; IPA:%s, WLAN:%s", 2939 ipa_smmu_enabled ? "enabled" : "disabled", 2940 wlan_smmu_enabled ? "enabled" : "disabled"); 2941 return QDF_STATUS_E_FAILURE; 2942 } 2943 2944 exit_with_success: 2945 osdev->domain = domain; 2946 2947 cds_info("SMMU S1 %s", osdev->smmu_s1_enabled ? "enabled" : "disabled"); 2948 2949 return QDF_STATUS_SUCCESS; 2950 } 2951 2952 #else 2953 QDF_STATUS cds_smmu_mem_map_setup(qdf_device_t osdev, bool ipa_present) 2954 { 2955 struct dma_iommu_mapping *mapping; 2956 bool ipa_smmu_enabled; 2957 bool wlan_smmu_enabled; 2958 2959 mapping = pld_smmu_get_mapping(osdev->dev); 2960 if (mapping) { 2961 int attr = 0; 2962 int errno = qdf_iommu_domain_get_attr(mapping->domain, 2963 QDF_DOMAIN_ATTR_S1_BYPASS, 2964 &attr); 2965 2966 wlan_smmu_enabled = !errno && !attr; 2967 } else { 2968 cds_info("No SMMU mapping present"); 2969 wlan_smmu_enabled = false; 2970 } 2971 2972 if (!wlan_smmu_enabled) { 2973 osdev->smmu_s1_enabled = false; 2974 goto exit_with_success; 2975 } 2976 2977 if (!ipa_present) { 2978 osdev->smmu_s1_enabled = true; 2979 goto exit_with_success; 2980 } 2981 2982 ipa_smmu_enabled = qdf_get_ipa_smmu_enabled(); 2983 2984 osdev->smmu_s1_enabled = ipa_smmu_enabled && wlan_smmu_enabled; 2985 if (ipa_smmu_enabled != wlan_smmu_enabled) { 2986 cds_err("SMMU mismatch; IPA:%s, WLAN:%s", 2987 ipa_smmu_enabled ? "enabled" : "disabled", 2988 wlan_smmu_enabled ? "enabled" : "disabled"); 2989 return QDF_STATUS_E_FAILURE; 2990 } 2991 2992 exit_with_success: 2993 osdev->iommu_mapping = mapping; 2994 2995 cds_info("SMMU S1 %s", osdev->smmu_s1_enabled ? "enabled" : "disabled"); 2996 2997 return QDF_STATUS_SUCCESS; 2998 } 2999 #endif 3000 3001 #ifdef IPA_OFFLOAD 3002 int cds_smmu_map_unmap(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr) 3003 { 3004 return ucfg_ipa_uc_smmu_map(map, num_buf, buf_arr); 3005 } 3006 #else 3007 int cds_smmu_map_unmap(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr) 3008 { 3009 return 0; 3010 } 3011 #endif 3012 3013 #else 3014 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) 3015 QDF_STATUS cds_smmu_mem_map_setup(qdf_device_t osdev, bool ipa_present) 3016 { 3017 osdev->smmu_s1_enabled = false; 3018 osdev->domain = NULL; 3019 return QDF_STATUS_SUCCESS; 3020 } 3021 #else 3022 QDF_STATUS cds_smmu_mem_map_setup(qdf_device_t osdev, bool ipa_present) 3023 { 3024 osdev->smmu_s1_enabled = false; 3025 return QDF_STATUS_SUCCESS; 3026 } 3027 #endif 3028 3029 int cds_smmu_map_unmap(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr) 3030 { 3031 return 0; 3032 } 3033 #endif 3034