xref: /wlan-dirver/qcacld-3.0/core/cds/src/cds_api.c (revision 5f87c0b118df8e541f3051a13b7414c1dd79020b)
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