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