blob: ffcb5edb7513438da11386aea95758bd0a4cb29e [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2014-2015 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 "wlan_hdd_misc.h"
44#include "i_cds_packet.h"
45#include "cds_reg_service.h"
46#include "wma_types.h"
47#include "wlan_hdd_main.h"
48#include <linux/vmalloc.h>
49#ifdef CONFIG_CNSS
50#include <net/cnss.h>
51#endif
52
53#include "sap_api.h"
54#include "cdf_trace.h"
55#include "bmi.h"
56#include "ol_fw.h"
57#include "ol_if_athvar.h"
58#include "hif.h"
59
60#include "cds_utils.h"
61#include "wlan_logging_sock_svc.h"
62#include "wma.h"
63
64#include "wlan_hdd_ipa.h"
65/* Preprocessor Definitions and Constants */
66
67/* Maximum number of cds message queue get wrapper failures to cause panic */
68#define CDS_WRAPPER_MAX_FAIL_COUNT (CDS_CORE_MAX_MESSAGES * 3)
69
70#ifdef IPA_OFFLOAD
71#define CDS_IPA_CE_SR_BASE_PADDR \
72 (&((hdd_context_t *)(gp_cds_context->pHDDContext))->ce_sr_base_paddr)
73#define CDS_IPA_CE_RING_SIZE \
74 (&((hdd_context_t *)(gp_cds_context->pHDDContext))->ce_sr_ring_size)
75#define CDS_IPA_CE_REG_PADDR \
76 (&((hdd_context_t *)(gp_cds_context->pHDDContext))->ce_reg_paddr)
77#define CDS_IPA_TX_COMP_BASE_PADDR \
78 (&((hdd_context_t *) \
79 (gp_cds_context->pHDDContext))->tx_comp_ring_base_paddr)
80#define CDS_IPA_TX_COMP_RING_SIZE \
81 (&((hdd_context_t *)(gp_cds_context->pHDDContext))->tx_comp_ring_size)
82#define CDS_IPA_TX_NUM_BUFF \
83 (&((hdd_context_t *)(gp_cds_context->pHDDContext))->tx_num_alloc_buffer)
84#define CDS_IPA_RX_RDY_RING_BASE_PADDR \
85 (&((hdd_context_t *) \
86 (gp_cds_context->pHDDContext))->rx_rdy_ring_base_paddr)
87#define CDS_IPA_RX_RDY_RING_SIZE \
88 (&((hdd_context_t *)(gp_cds_context->pHDDContext))->rx_rdy_ring_size)
89#define CDS_IPA_RX_PROC_DONE_IDX_PADDR \
90 (&((hdd_context_t *) \
91 (gp_cds_context->pHDDContext))->rx_proc_done_idx_paddr)
92#else
93#define CDS_IPA_CE_SR_BASE_PADDR (NULL)
94#define CDS_IPA_CE_RING_SIZE (NULL)
95#define CDS_IPA_CE_REG_PADDR (NULL)
96#define CDS_IPA_TX_COMP_BASE_PADDR (NULL)
97#define CDS_IPA_TX_COMP_RING_SIZE (NULL)
98#define CDS_IPA_TX_NUM_BUFF (NULL)
99#define CDS_IPA_RX_RDY_RING_BASE_PADDR (NULL)
100#define CDS_IPA_RX_RDY_RING_SIZE (NULL)
101#define CDS_IPA_RX_PROC_DONE_IDX_PADDR (NULL)
102#endif /* IPA_OFFLOAD */
103
104/* Data definitions */
105static cds_context_type g_cds_context;
106static p_cds_contextType gp_cds_context;
107static struct __cdf_device g_cdf_ctx;
108
109/* Debug variable to detect MC thread stuck */
110static atomic_t cds_wrapper_empty_count;
111
112static uint8_t cds_multicast_logging;
113
114void cds_sys_probe_thread_cback(void *pUserData);
115
116/**
117 * cds_alloc_global_context() - allocate CDS global context
118 * @p_cds_context: A pointer to where to store the CDS Context
119 *
120 * cds_alloc_global_context() function allocates the CDS global Context,
121 * but does not initialize all the members. This overal initialization will
122 * happen at cds_open().
123 *
124 * Return: CDF status
125 */
126CDF_STATUS cds_alloc_global_context(v_CONTEXT_t *p_cds_context)
127{
128 if (p_cds_context == NULL)
129 return CDF_STATUS_E_FAILURE;
130
131 /* allocate the CDS Context */
132 *p_cds_context = NULL;
133 gp_cds_context = &g_cds_context;
134
135 cdf_mem_zero(gp_cds_context, sizeof(cds_context_type));
136 *p_cds_context = gp_cds_context;
137
138 gp_cds_context->cdf_ctx = &g_cdf_ctx;
139 cdf_mem_zero(&g_cdf_ctx, sizeof(g_cdf_ctx));
140
141 /* initialize the spinlock */
142 cdf_trace_spin_lock_init();
143 /* it is the right time to initialize MTRACE structures */
144#if defined(TRACE_RECORD)
145 cdf_trace_init();
146#endif
147
148 cdf_dp_trace_init();
149 return CDF_STATUS_SUCCESS;
150} /* cds_alloc_global_context() */
151
152/**
153 * cds_free_global_context() - free CDS global context
154 * @p_cds_context: A pointer to where the CDS Context was stored
155 *
156 * cds_free_global_context() function frees the CDS Context.
157 *
158 * Return: CDF status
159 */
160CDF_STATUS cds_free_global_context(v_CONTEXT_t *p_cds_context)
161{
162 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO,
163 "%s: De-allocating the CDS Context", __func__);
164
165 if ((p_cds_context == NULL) || (*p_cds_context == NULL)) {
166 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
167 "%s: vOS Context is Null", __func__);
168 return CDF_STATUS_E_FAILURE;
169 }
170
171 if (gp_cds_context != *p_cds_context) {
172 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
173 "%s: Context mismatch", __func__);
174 return CDF_STATUS_E_FAILURE;
175 }
176 gp_cds_context->cdf_ctx = NULL;
177 *p_cds_context = gp_cds_context = NULL;
178
179 return CDF_STATUS_SUCCESS;
180} /* cds_free_global_context() */
181
182#ifdef WLAN_FEATURE_NAN
183/**
184 * cds_set_nan_enable() - set nan enable flag in mac open param
185 * @wma_handle: Pointer to mac open param
186 * @hdd_ctx: Pointer to hdd context
187 *
188 * Return: none
189 */
190static void cds_set_nan_enable(tMacOpenParameters *param,
191 hdd_context_t *hdd_ctx)
192{
193 param->is_nan_enabled = hdd_ctx->config->enable_nan_support;
194}
195#else
196static void cds_set_nan_enable(tMacOpenParameters *param,
197 hdd_context_t *pHddCtx)
198{
199}
200#endif
201
202/**
203 * cds_open() - open the CDS Module
204 * @p_cds_context: A pointer to where the CDS Context was stored
205 * @hddContextSize: Size of the HDD context to allocate.
206 *
207 * cds_open() function opens the CDS Scheduler
208 * Upon successful initialization:
209 * - All CDS submodules should have been initialized
210 *
211 * - The CDS scheduler should have opened
212 *
213 * - All the WLAN SW components should have been opened. This includes
214 * SYS, MAC, SME, WMA and TL.
215 *
216 * Return: CDF status
217 */
218CDF_STATUS cds_open(v_CONTEXT_t *p_cds_context, uint32_t hddContextSize)
219{
220 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
221 int iter = 0;
222 tSirRetStatus sirStatus = eSIR_SUCCESS;
223 tMacOpenParameters mac_openParms;
224 cdf_device_t cdf_ctx;
225 HTC_INIT_INFO htcInfo;
226 struct ol_softc *scn;
227 void *HTCHandle;
228 hdd_context_t *pHddCtx;
229
230 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH,
231 "%s: Opening CDS", __func__);
232
233 if (NULL == gp_cds_context) {
234 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
235 "%s: Trying to open CDS without a PreOpen", __func__);
236 CDF_ASSERT(0);
237 return CDF_STATUS_E_FAILURE;
238 }
239
240 /* Initialize the timer module */
241 cdf_timer_module_init();
242
243 /* Initialize bug reporting structure */
244 cds_init_log_completion();
245
246 /* Initialize the probe event */
247 if (cdf_event_init(&gp_cds_context->ProbeEvent) != CDF_STATUS_SUCCESS) {
248 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
249 "%s: Unable to init probeEvent", __func__);
250 CDF_ASSERT(0);
251 return CDF_STATUS_E_FAILURE;
252 }
253 if (cdf_event_init(&(gp_cds_context->wmaCompleteEvent)) !=
254 CDF_STATUS_SUCCESS) {
255 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
256 "%s: Unable to init wmaCompleteEvent", __func__);
257 CDF_ASSERT(0);
258 goto err_probe_event;
259 }
260
261 /* Initialize the free message queue */
262 cdf_status = cds_mq_init(&gp_cds_context->freeVosMq);
263 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
264 /* Critical Error ... Cannot proceed further */
265 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
266 "%s: Failed to initialize CDS free message queue",
267 __func__);
268 CDF_ASSERT(0);
269 goto err_wma_complete_event;
270 }
271
272 for (iter = 0; iter < CDS_CORE_MAX_MESSAGES; iter++) {
273 (gp_cds_context->aMsgWrappers[iter]).pVosMsg =
274 &(gp_cds_context->aMsgBuffers[iter]);
275 INIT_LIST_HEAD(&gp_cds_context->aMsgWrappers[iter].msgNode);
276 cds_mq_put(&gp_cds_context->freeVosMq,
277 &(gp_cds_context->aMsgWrappers[iter]));
278 }
279
280 /* Now Open the CDS Scheduler */
281 cdf_status = cds_sched_open(gp_cds_context, &gp_cds_context->cdf_sched,
282 sizeof(cds_sched_context));
283
284 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
285 /* Critical Error ... Cannot proceed further */
286 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
287 "%s: Failed to open CDS Scheduler", __func__);
288 CDF_ASSERT(0);
289 goto err_msg_queue;
290 }
291
292 pHddCtx = (hdd_context_t *) (gp_cds_context->pHDDContext);
293 if ((NULL == pHddCtx) || (NULL == pHddCtx->config)) {
294 /* Critical Error ... Cannot proceed further */
295 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
296 "%s: Hdd Context is Null", __func__);
297 CDF_ASSERT(0);
298 goto err_sched_close;
299 }
300
301 scn = cds_get_context(CDF_MODULE_ID_HIF);
302 if (!scn) {
303 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
304 "%s: scn is null!", __func__);
305 goto err_sched_close;
306 }
307 scn->enableuartprint = pHddCtx->config->enablefwprint;
308 scn->enablefwlog = pHddCtx->config->enablefwlog;
309 scn->max_no_of_peers = pHddCtx->config->maxNumberOfPeers;
310#ifdef WLAN_FEATURE_LPSS
311 scn->enablelpasssupport = pHddCtx->config->enablelpasssupport;
312#endif
313 scn->enable_ramdump_collection =
314 pHddCtx->config->is_ramdump_enabled;
315 scn->enable_self_recovery = pHddCtx->config->enableSelfRecovery;
316
317 /* Initialize BMI and Download firmware */
318 cdf_status = bmi_download_firmware(scn);
319 if (cdf_status != CDF_STATUS_SUCCESS) {
320 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
321 "BMI FIALED status:%d", cdf_status);
322 goto err_bmi_close;
323 }
324
325 htcInfo.pContext = gp_cds_context->pHIFContext;
326 htcInfo.TargetFailure = ol_target_failure;
327 htcInfo.TargetSendSuspendComplete = wma_target_suspend_acknowledge;
328 cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE);
329
330 /* Create HTC */
331 gp_cds_context->htc_ctx =
332 htc_create(htcInfo.pContext, &htcInfo, cdf_ctx);
333 if (!gp_cds_context->htc_ctx) {
334 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
335 "%s: Failed to Create HTC", __func__);
336 goto err_bmi_close;
337 }
338
339 if (bmi_done(scn)) {
340 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
341 "%s: Failed to complete BMI phase", __func__);
342 goto err_htc_close;
343 }
344
345 /*
346 ** Need to open WMA first because it calls WDI_Init, which calls wpalOpen
347 ** The reason that is needed becasue cds_packet_open need to use PAL APIs
348 */
349
350 /*Open the WMA module */
351 cdf_mem_set(&mac_openParms, sizeof(mac_openParms), 0);
352 /* UMA is supported in hardware for performing the
353 ** frame translation 802.11 <-> 802.3
354 */
355 mac_openParms.frameTransRequired = 1;
356 mac_openParms.driverType = eDRIVER_TYPE_PRODUCTION;
357 mac_openParms.powersaveOffloadEnabled =
358 pHddCtx->config->enablePowersaveOffload;
359 mac_openParms.staDynamicDtim = pHddCtx->config->enableDynamicDTIM;
360 mac_openParms.staModDtim = pHddCtx->config->enableModulatedDTIM;
361 mac_openParms.staMaxLIModDtim = pHddCtx->config->fMaxLIModulatedDTIM;
362 mac_openParms.wowEnable = pHddCtx->config->wowEnable;
363 mac_openParms.maxWoWFilters = pHddCtx->config->maxWoWFilters;
364 /* Here olIniInfo is used to store ini status of arp offload
365 * ns offload and others. Currently 1st bit is used for arp
366 * off load and 2nd bit for ns offload currently, rest bits are unused
367 */
368 if (pHddCtx->config->fhostArpOffload)
369 mac_openParms.olIniInfo = mac_openParms.olIniInfo | 0x1;
370 if (pHddCtx->config->fhostNSOffload)
371 mac_openParms.olIniInfo = mac_openParms.olIniInfo | 0x2;
372 /*
373 * Copy the DFS Phyerr Filtering Offload status.
374 * This parameter reflects the value of the
375 * dfsPhyerrFilterOffload flag as set in the ini.
376 */
377 mac_openParms.dfsPhyerrFilterOffload =
378 pHddCtx->config->fDfsPhyerrFilterOffload;
379 if (pHddCtx->config->ssdp)
380 mac_openParms.ssdp = pHddCtx->config->ssdp;
381#ifdef FEATURE_WLAN_RA_FILTERING
382 mac_openParms.RArateLimitInterval =
383 pHddCtx->config->RArateLimitInterval;
384 mac_openParms.IsRArateLimitEnabled =
385 pHddCtx->config->IsRArateLimitEnabled;
386#endif
387
388 mac_openParms.apMaxOffloadPeers = pHddCtx->config->apMaxOffloadPeers;
389
390 mac_openParms.apMaxOffloadReorderBuffs =
391 pHddCtx->config->apMaxOffloadReorderBuffs;
392
393 mac_openParms.apDisableIntraBssFwd =
394 pHddCtx->config->apDisableIntraBssFwd;
395
396 mac_openParms.dfsRadarPriMultiplier =
397 pHddCtx->config->dfsRadarPriMultiplier;
398 mac_openParms.reorderOffload = pHddCtx->config->reorderOffloadSupport;
399
400 /* IPA micro controller data path offload resource config item */
401 mac_openParms.ucOffloadEnabled = hdd_ipa_uc_is_enabled(pHddCtx);
402 mac_openParms.ucTxBufCount = pHddCtx->config->IpaUcTxBufCount;
403 mac_openParms.ucTxBufSize = pHddCtx->config->IpaUcTxBufSize;
404 mac_openParms.ucRxIndRingCount = pHddCtx->config->IpaUcRxIndRingCount;
405 mac_openParms.ucTxPartitionBase = pHddCtx->config->IpaUcTxPartitionBase;
406 mac_openParms.max_scan = pHddCtx->config->max_scan_count;
407
408 mac_openParms.ip_tcp_udp_checksum_offload =
409 pHddCtx->config->enable_ip_tcp_udp_checksum_offload;
410 mac_openParms.enable_rxthread = pHddCtx->config->enableRxThread;
411 mac_openParms.ce_classify_enabled =
412 pHddCtx->config->ce_classify_enabled;
413
414#ifdef QCA_LL_TX_FLOW_CONTROL_V2
415 mac_openParms.tx_flow_stop_queue_th =
416 pHddCtx->config->TxFlowStopQueueThreshold;
417 mac_openParms.tx_flow_start_queue_offset =
418 pHddCtx->config->TxFlowStartQueueOffset;
419#endif
420 cds_set_nan_enable(&mac_openParms, pHddCtx);
421
422 mac_openParms.tx_chain_mask_cck = pHddCtx->config->tx_chain_mask_cck;
423 mac_openParms.self_gen_frm_pwr = pHddCtx->config->self_gen_frm_pwr;
424
425 cdf_status = wma_open(gp_cds_context,
426 hdd_update_tgt_cfg,
427 hdd_dfs_indicate_radar, &mac_openParms);
428
429 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
430 /* Critical Error ... Cannot proceed further */
431 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
432 "%s: Failed to open WMA module", __func__);
433 CDF_ASSERT(0);
434 goto err_htc_close;
435 }
436
437 /* Number of peers limit differs in each chip version. If peer max
438 * limit configured in ini exceeds more than supported, WMA adjusts
439 * and keeps correct limit in mac_openParms.maxStation. So, make sure
440 * config entry pHddCtx->config->maxNumberOfPeers has adjusted value
441 */
442 pHddCtx->config->maxNumberOfPeers = mac_openParms.maxStation;
443 HTCHandle = cds_get_context(CDF_MODULE_ID_HTC);
444 if (!HTCHandle) {
445 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
446 "%s: HTCHandle is null!", __func__);
447 goto err_wma_close;
448 }
449 if (htc_wait_target(HTCHandle)) {
450 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
451 "%s: Failed to complete BMI phase", __func__);
452 goto err_wma_close;
453 }
454
455 /* Now proceed to open the MAC */
456
457 /* UMA is supported in hardware for performing the
458 * frame translation 802.11 <-> 802.3
459 */
460 mac_openParms.frameTransRequired = 1;
461
462 sirStatus =
463 mac_open(&(gp_cds_context->pMACContext), gp_cds_context->pHDDContext,
464 &mac_openParms);
465
466 if (eSIR_SUCCESS != sirStatus) {
467 /* Critical Error ... Cannot proceed further */
468 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
469 "%s: Failed to open MAC", __func__);
470 CDF_ASSERT(0);
471 goto err_wma_close;
472 }
473
474 /* Now proceed to open the SME */
475 cdf_status = sme_open(gp_cds_context->pMACContext);
476 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
477 /* Critical Error ... Cannot proceed further */
478 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
479 "%s: Failed to open SME", __func__);
480 CDF_ASSERT(0);
481 goto err_mac_close;
482 }
483
484 gp_cds_context->pdev_txrx_ctx =
485 ol_txrx_pdev_alloc(gp_cds_context->cfg_ctx,
486 gp_cds_context->htc_ctx,
487 gp_cds_context->cdf_ctx);
488 if (!gp_cds_context->pdev_txrx_ctx) {
489 /* Critical Error ... Cannot proceed further */
490 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
491 "%s: Failed to open TXRX", __func__);
492 CDF_ASSERT(0);
493 goto err_sme_close;
494 }
495
496 ol_txrx_ipa_uc_get_resource(gp_cds_context->pdev_txrx_ctx,
497 CDS_IPA_CE_SR_BASE_PADDR,
498 CDS_IPA_CE_RING_SIZE,
499 CDS_IPA_CE_REG_PADDR,
500 CDS_IPA_TX_COMP_BASE_PADDR,
501 CDS_IPA_TX_COMP_RING_SIZE,
502 CDS_IPA_TX_NUM_BUFF,
503 CDS_IPA_RX_RDY_RING_BASE_PADDR,
504 CDS_IPA_RX_RDY_RING_SIZE,
505 CDS_IPA_RX_PROC_DONE_IDX_PADDR);
506
507 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH,
508 "%s: CDS successfully Opened", __func__);
509
510 *p_cds_context = gp_cds_context;
511
512 return CDF_STATUS_SUCCESS;
513
514err_sme_close:
515 sme_close(gp_cds_context->pMACContext);
516
517err_mac_close:
518 mac_close(gp_cds_context->pMACContext);
519
520err_wma_close:
521 wma_close(gp_cds_context);
522
523 wma_wmi_service_close(gp_cds_context);
524
525err_htc_close:
526 if (gp_cds_context->htc_ctx) {
527 htc_destroy(gp_cds_context->htc_ctx);
528 gp_cds_context->htc_ctx = NULL;
529 }
530
531err_bmi_close:
532 bmi_cleanup(scn);
533
534err_sched_close:
535 cds_sched_close(gp_cds_context);
536
537err_msg_queue:
538 cds_mq_deinit(&gp_cds_context->freeVosMq);
539
540err_wma_complete_event:
541 cdf_event_destroy(&gp_cds_context->wmaCompleteEvent);
542
543err_probe_event:
544 cdf_event_destroy(&gp_cds_context->ProbeEvent);
545
546 return CDF_STATUS_E_FAILURE;
547} /* cds_open() */
548
549/**
550 * cds_pre_enable() - pre enable cds
551 * @cds_context: CDS context
552 *
553 * Return: CDF status
554 */
555CDF_STATUS cds_pre_enable(v_CONTEXT_t cds_context)
556{
557 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
558 p_cds_contextType p_cds_context = (p_cds_contextType) cds_context;
559 void *scn;
560 CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_INFO, "cds prestart");
561
562 if (gp_cds_context != p_cds_context) {
563 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
564 "%s: Context mismatch", __func__);
565 CDF_ASSERT(0);
566 return CDF_STATUS_E_INVAL;
567 }
568
569 if (p_cds_context->pMACContext == NULL) {
570 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
571 "%s: MAC NULL context", __func__);
572 CDF_ASSERT(0);
573 return CDF_STATUS_E_INVAL;
574 }
575
576 if (p_cds_context->pWMAContext == NULL) {
577 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
578 "%s: WMA NULL context", __func__);
579 CDF_ASSERT(0);
580 return CDF_STATUS_E_INVAL;
581 }
582
583 scn = cds_get_context(CDF_MODULE_ID_HIF);
584 if (!scn) {
585 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
586 "%s: scn is null!", __func__);
587 return CDF_STATUS_E_FAILURE;
588 }
589
590 /* Reset wma wait event */
591 cdf_event_reset(&gp_cds_context->wmaCompleteEvent);
592
593 /*call WMA pre start */
594 cdf_status = wma_pre_start(gp_cds_context);
595 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
596 CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_FATAL,
597 "Failed to WMA prestart");
598 CDF_ASSERT(0);
599 return CDF_STATUS_E_FAILURE;
600 }
601
602 /* Need to update time out of complete */
603 cdf_status = cdf_wait_single_event(&gp_cds_context->wmaCompleteEvent,
604 CDS_WMA_TIMEOUT);
605 if (cdf_status != CDF_STATUS_SUCCESS) {
606 if (cdf_status == CDF_STATUS_E_TIMEOUT) {
607 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
608 "%s: Timeout occurred before WMA complete",
609 __func__);
610 } else {
611 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
612 "%s: wma_pre_start reporting other error",
613 __func__);
614 }
615 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
616 "%s: Test MC thread by posting a probe message to SYS",
617 __func__);
618 wlan_sys_probe();
619
620 CDF_ASSERT(0);
621 return CDF_STATUS_E_FAILURE;
622 }
623
624 cdf_status = htc_start(gp_cds_context->htc_ctx);
625 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
626 CDF_TRACE(CDF_MODULE_ID_SYS, CDF_TRACE_LEVEL_FATAL,
627 "Failed to Start HTC");
628 CDF_ASSERT(0);
629 return CDF_STATUS_E_FAILURE;
630 }
631 cdf_status = wma_wait_for_ready_event(gp_cds_context->pWMAContext);
632 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
633 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
634 "Failed to get ready event from target firmware");
635 htc_set_target_to_sleep(scn);
636 htc_stop(gp_cds_context->htc_ctx);
637 CDF_ASSERT(0);
638 return CDF_STATUS_E_FAILURE;
639 }
640
641 if (ol_txrx_pdev_attach(gp_cds_context->pdev_txrx_ctx)) {
642 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
643 "Failed to attach pdev");
644 htc_set_target_to_sleep(scn);
645 htc_stop(gp_cds_context->htc_ctx);
646 CDF_ASSERT(0);
647 return CDF_STATUS_E_FAILURE;
648 }
649
650 htc_set_target_to_sleep(scn);
651
652 return CDF_STATUS_SUCCESS;
653}
654
655/**
656 * cds_enable() - start/enable cds module
657 * @cds_context: CDS context
658 *
659 * Return: CDF status
660 */
661CDF_STATUS cds_enable(v_CONTEXT_t cds_context)
662{
663 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
664 tSirRetStatus sirStatus = eSIR_SUCCESS;
665 p_cds_contextType p_cds_context = (p_cds_contextType) cds_context;
666 tHalMacStartParameters halStartParams;
667
668 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO,
669 "%s: Starting Libra SW", __func__);
670
671 /* We support only one instance for now ... */
672 if (gp_cds_context != p_cds_context) {
673 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
674 "%s: mismatch in context", __func__);
675 return CDF_STATUS_E_FAILURE;
676 }
677
678 if ((p_cds_context->pWMAContext == NULL) ||
679 (p_cds_context->pMACContext == NULL)) {
680 if (p_cds_context->pWMAContext == NULL)
681 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
682 "%s: WMA NULL context", __func__);
683 else
684 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
685 "%s: MAC NULL context", __func__);
686
687 return CDF_STATUS_E_FAILURE;
688 }
689
690 /* Start the wma */
691 cdf_status = wma_start(p_cds_context);
692 if (cdf_status != CDF_STATUS_SUCCESS) {
693 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
694 "%s: Failed to start wma", __func__);
695 return CDF_STATUS_E_FAILURE;
696 }
697 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO,
698 "%s: wma correctly started", __func__);
699
700 /* Start the MAC */
701 cdf_mem_zero(&halStartParams,
702 sizeof(tHalMacStartParameters));
703
704 /* Start the MAC */
705 sirStatus =
706 mac_start(p_cds_context->pMACContext, &halStartParams);
707
708 if (eSIR_SUCCESS != sirStatus) {
709 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
710 "%s: Failed to start MAC", __func__);
711 goto err_wma_stop;
712 }
713
714 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO,
715 "%s: MAC correctly started", __func__);
716
717 /* START SME */
718 cdf_status = sme_start(p_cds_context->pMACContext);
719
720 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
721 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
722 "%s: Failed to start SME", __func__);
723 goto err_mac_stop;
724 }
725
726 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO,
727 "%s: SME correctly started", __func__);
728
729 if (ol_txrx_pdev_attach_target
730 (p_cds_context->pdev_txrx_ctx) != A_OK) {
731 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
732 "%s: Failed attach target", __func__);
733 goto err_sme_stop;
734 }
735
736 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO,
737 "TL correctly started");
738 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO,
739 "%s: CDS Start is successful!!", __func__);
740
741 return CDF_STATUS_SUCCESS;
742
743err_sme_stop:
744 sme_stop(p_cds_context->pMACContext, HAL_STOP_TYPE_SYS_RESET);
745
746err_mac_stop:
747 mac_stop(p_cds_context->pMACContext, HAL_STOP_TYPE_SYS_RESET);
748
749err_wma_stop:
750 cdf_event_reset(&(gp_cds_context->wmaCompleteEvent));
751 cdf_status = wma_stop(p_cds_context, HAL_STOP_TYPE_RF_KILL);
752 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
753 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
754 "%s: Failed to stop wma", __func__);
755 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
756 wma_setneedshutdown(cds_context);
757 } else {
758 cdf_status =
759 cdf_wait_single_event(&(gp_cds_context->wmaCompleteEvent),
760 CDS_WMA_TIMEOUT);
761 if (cdf_status != CDF_STATUS_SUCCESS) {
762 if (cdf_status == CDF_STATUS_E_TIMEOUT) {
763 CDF_TRACE(CDF_MODULE_ID_CDF,
764 CDF_TRACE_LEVEL_FATAL,
765 "%s: Timeout occurred before WMA_stop complete",
766 __func__);
767 } else {
768 CDF_TRACE(CDF_MODULE_ID_CDF,
769 CDF_TRACE_LEVEL_FATAL,
770 "%s: WMA_stop reporting other error",
771 __func__);
772 }
773 CDF_ASSERT(0);
774 wma_setneedshutdown(cds_context);
775 }
776 }
777
778 return CDF_STATUS_E_FAILURE;
779} /* cds_enable() */
780
781/**
782 * cds_disable() - stop/disable cds module
783 * @cds_context: CDS context
784 *
785 * Return: CDF status
786 */
787CDF_STATUS cds_disable(v_CONTEXT_t cds_context)
788{
789 CDF_STATUS cdf_status;
790
791 /* wma_stop is called before the SYS so that the processing of target
792 * pending responses will not be handled during uninitialization of
793 * WLAN driver
794 */
795 cdf_event_reset(&(gp_cds_context->wmaCompleteEvent));
796
797 cdf_status = wma_stop(cds_context, HAL_STOP_TYPE_RF_KILL);
798
799 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
800 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
801 "%s: Failed to stop wma", __func__);
802 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
803 wma_setneedshutdown(cds_context);
804 }
805
806 hif_disable_isr(((cds_context_type *) cds_context)->pHIFContext);
807 hif_reset_soc(((cds_context_type *) cds_context)->pHIFContext);
808
809 /* SYS STOP will stop SME and MAC */
810 cdf_status = sys_stop(cds_context);
811 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
812 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
813 "%s: Failed to stop SYS", __func__);
814 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
815 }
816
817 return CDF_STATUS_SUCCESS;
818}
819
820/**
821 * cds_close() - close cds module
822 * @cds_context: CDS context
823 *
824 * Return: CDF status
825 */
826CDF_STATUS cds_close(v_CONTEXT_t cds_context)
827{
828 CDF_STATUS cdf_status;
829
830 if (gp_cds_context->htc_ctx) {
831 htc_stop(gp_cds_context->htc_ctx);
832 htc_destroy(gp_cds_context->htc_ctx);
833 gp_cds_context->htc_ctx = NULL;
834 }
835
836 ol_txrx_pdev_detach(gp_cds_context->pdev_txrx_ctx, 1);
837 cds_free_context(cds_context, CDF_MODULE_ID_TXRX,
838 gp_cds_context->pdev_txrx_ctx);
839
840 cdf_status = sme_close(((p_cds_contextType) cds_context)->pMACContext);
841 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
842 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
843 "%s: Failed to close SME", __func__);
844 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
845 }
846
847 cdf_status = mac_close(((p_cds_contextType) cds_context)->pMACContext);
848 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
849 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
850 "%s: Failed to close MAC", __func__);
851 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
852 }
853
854 ((p_cds_contextType) cds_context)->pMACContext = NULL;
855
856 if (true == wma_needshutdown(cds_context)) {
857 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
858 "%s: Failed to shutdown wma", __func__);
859 } else {
860 cdf_status = wma_close(cds_context);
861 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
862 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
863 "%s: Failed to close wma", __func__);
864 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
865 }
866 }
867
868 cdf_status = wma_wmi_service_close(cds_context);
869 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
870 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
871 "%s: Failed to close wma_wmi_service", __func__);
872 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
873 }
874
875 cds_mq_deinit(&((p_cds_contextType) cds_context)->freeVosMq);
876
877 cdf_status = cdf_event_destroy(&gp_cds_context->wmaCompleteEvent);
878 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
879 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
880 "%s: failed to destroy wmaCompleteEvent", __func__);
881 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
882 }
883
884 cdf_status = cdf_event_destroy(&gp_cds_context->ProbeEvent);
885 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
886 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
887 "%s: failed to destroy ProbeEvent", __func__);
888 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
889 }
890
891 cds_deinit_log_completion();
892 return CDF_STATUS_SUCCESS;
893}
894
895/**
896 * cds_get_context() - get context data area
897 *
898 * @moduleId: ID of the module who's context data is being retrived.
899 *
900 * Each module in the system has a context / data area that is allocated
901 * and managed by CDS. This API allows any user to get a pointer to its
902 * allocated context data area from the CDS global context.
903 *
904 * Return: pointer to the context data area of the module ID
905 * specified, or NULL if the context data is not allocated for
906 * the module ID specified
907 */
908void *cds_get_context(CDF_MODULE_ID moduleId)
909{
910 void *pModContext = NULL;
911
912 if (gp_cds_context == NULL) {
913 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
914 "%s: cds context pointer is null", __func__);
915 return NULL;
916 }
917
918 switch (moduleId) {
919#ifndef WLAN_FEATURE_MBSSID
920 case CDF_MODULE_ID_SAP:
921 {
922 pModContext = gp_cds_context->pSAPContext;
923 break;
924 }
925#endif
926
927 case CDF_MODULE_ID_HDD:
928 {
929 pModContext = gp_cds_context->pHDDContext;
930 break;
931 }
932
933 case CDF_MODULE_ID_SME:
934 case CDF_MODULE_ID_PE:
935 {
936 /* In all these cases, we just return the MAC Context */
937 pModContext = gp_cds_context->pMACContext;
938 break;
939 }
940
941 case CDF_MODULE_ID_WMA:
942 {
943 /* For wma module */
944 pModContext = gp_cds_context->pWMAContext;
945 break;
946 }
947
948 case CDF_MODULE_ID_CDF:
949 {
950 /* For SYS this is CDS itself */
951 pModContext = gp_cds_context;
952 break;
953 }
954
955 case CDF_MODULE_ID_HIF:
956 {
957 pModContext = gp_cds_context->pHIFContext;
958 break;
959 }
960
961 case CDF_MODULE_ID_HTC:
962 {
963 pModContext = gp_cds_context->htc_ctx;
964 break;
965 }
966
967 case CDF_MODULE_ID_CDF_DEVICE:
968 {
969 pModContext = gp_cds_context->cdf_ctx;
970 break;
971 }
972
973 case CDF_MODULE_ID_TXRX:
974 {
975 pModContext = gp_cds_context->pdev_txrx_ctx;
976 break;
977 }
978
979 case CDF_MODULE_ID_CFG:
980 {
981 pModContext = gp_cds_context->cfg_ctx;
982 break;
983 }
984
985 default:
986 {
987 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
988 "%s: Module ID %i does not have its context maintained by CDS",
989 __func__, moduleId);
990 CDF_ASSERT(0);
991 return NULL;
992 }
993 }
994
995 if (pModContext == NULL) {
996 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
997 "%s: Module ID %i context is Null", __func__,
998 moduleId);
999 }
1000
1001 return pModContext;
1002} /* cds_get_context() */
1003
1004/**
1005 * cds_get_global_context() - get CDS global Context
1006 *
1007 * This API allows any user to get the CDS Global Context pointer from a
1008 * module context data area.
1009 *
1010 * Return: pointer to the CDS global context, NULL if the function is
1011 * unable to retreive the CDS context.
1012 */
1013v_CONTEXT_t cds_get_global_context(void)
1014{
1015 if (gp_cds_context == NULL) {
1016 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1017 "%s: global cds context is NULL", __func__);
1018 }
1019
1020 return gp_cds_context;
1021} /* cds_get_global_context() */
1022
1023/**
1024 * cds_is_logp_in_progress() - check if ssr/self recovery is going on
1025 *
1026 * Return: true if ssr/self recvoery is going on else false
1027 */
1028uint8_t cds_is_logp_in_progress(void)
1029{
1030 if (gp_cds_context == NULL) {
1031 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1032 "%s: global cds context is NULL", __func__);
1033 return 1;
1034 }
1035
1036 return gp_cds_context->isLogpInProgress;
1037}
1038
1039/**
1040 * cds_set_logp_in_progress() - set ssr/self recovery in progress
1041 * @value: value to set
1042 *
1043 * Return: none
1044 */
1045void cds_set_logp_in_progress(uint8_t value)
1046{
1047 hdd_context_t *pHddCtx = NULL;
1048
1049 if (gp_cds_context == NULL) {
1050 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1051 "%s: global cds context is NULL", __func__);
1052 return;
1053 }
1054 gp_cds_context->isLogpInProgress = value;
1055
1056 /* HDD uses it's own context variable to check if SSR in progress,
1057 * instead of modifying all HDD APIs set the HDD context variable
1058 * here
1059 */
1060 pHddCtx = cds_get_context(CDF_MODULE_ID_HDD);
1061 if (!pHddCtx) {
1062 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
1063 "%s: HDD context is Null", __func__);
1064 return;
1065 }
1066 pHddCtx->isLogpInProgress = value;
1067}
1068
1069/**
1070 * cds_is_load_unload_in_progress() - check if driver load/unload in progress
1071 *
1072 * Return: true if load/unload is going on else false
1073 */
1074uint8_t cds_is_load_unload_in_progress(void)
1075{
1076 if (gp_cds_context == NULL) {
1077 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1078 "%s: global cds context is NULL", __func__);
1079 return 0;
1080 }
1081
1082 return gp_cds_context->isLoadUnloadInProgress;
1083}
1084
1085/**
1086 * cds_set_load_unload_in_progress() - set load/unload in progress
1087 * @value: value to set
1088 *
1089 * Return: none
1090 */
1091void cds_set_load_unload_in_progress(uint8_t value)
1092{
1093 if (gp_cds_context == NULL) {
1094 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1095 "%s: global cds context is NULL", __func__);
1096 return;
1097 }
1098 gp_cds_context->isLoadUnloadInProgress = value;
1099
1100#ifdef CONFIG_CNSS
1101 if (value)
1102 cnss_set_driver_status(CNSS_LOAD_UNLOAD);
1103 else
1104 cnss_set_driver_status(CNSS_INITIALIZED);
1105#endif
1106}
1107
1108/**
1109 * cds_alloc_context() - allocate a context within the CDS global Context
1110 * @p_cds_context: pointer to the global Vos context
1111 * @moduleId: module ID who's context area is being allocated.
1112 * @ppModuleContext: pointer to location where the pointer to the
1113 * allocated context is returned. Note this output pointer
1114 * is valid only if the API returns CDF_STATUS_SUCCESS
1115 * @param size: size of the context area to be allocated.
1116 *
1117 * This API allows any user to allocate a user context area within the
1118 * CDS Global Context.
1119 *
1120 * Return: CDF status
1121 */
1122CDF_STATUS cds_alloc_context(void *p_cds_context, CDF_MODULE_ID moduleID,
1123 void **ppModuleContext, uint32_t size)
1124{
1125 void **pGpModContext = NULL;
1126
1127 if (p_cds_context == NULL) {
1128 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1129 "%s: cds context is null", __func__);
1130 return CDF_STATUS_E_FAILURE;
1131 }
1132
1133 if ((gp_cds_context != p_cds_context) || (ppModuleContext == NULL)) {
1134 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1135 "%s: context mismatch or null param passed",
1136 __func__);
1137 return CDF_STATUS_E_FAILURE;
1138 }
1139
1140 switch (moduleID) {
1141
1142#ifndef WLAN_FEATURE_MBSSID
1143 case CDF_MODULE_ID_SAP:
1144 {
1145 pGpModContext = &(gp_cds_context->pSAPContext);
1146 break;
1147 }
1148#endif
1149
1150 case CDF_MODULE_ID_WMA:
1151 {
1152 pGpModContext = &(gp_cds_context->pWMAContext);
1153 break;
1154 }
1155
1156 case CDF_MODULE_ID_HIF:
1157 {
1158 pGpModContext = &(gp_cds_context->pHIFContext);
1159 break;
1160 }
1161
1162 case CDF_MODULE_ID_EPPING:
1163 {
1164 pGpModContext = &(gp_cds_context->epping_ctx);
1165 break;
1166 }
1167 case CDF_MODULE_ID_SME:
1168 case CDF_MODULE_ID_PE:
1169 case CDF_MODULE_ID_HDD:
1170 case CDF_MODULE_ID_HDD_SOFTAP:
1171 default:
1172 {
1173 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1174 "%s: Module ID %i "
1175 "does not have its context allocated by CDS",
1176 __func__, moduleID);
1177 CDF_ASSERT(0);
1178 return CDF_STATUS_E_INVAL;
1179 }
1180 }
1181
1182 if (NULL != *pGpModContext) {
1183 /* Context has already been allocated!
1184 * Prevent double allocation
1185 */
1186 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1187 "%s: Module ID %i context has already been allocated",
1188 __func__, moduleID);
1189 return CDF_STATUS_E_EXISTS;
1190 }
1191
1192 /* Dynamically allocate the context for module */
1193
1194 *ppModuleContext = cdf_mem_malloc(size);
1195
1196 if (*ppModuleContext == NULL) {
1197 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1198 "%s: Failed to " "allocate Context for module ID %i",
1199 __func__, moduleID);
1200 CDF_ASSERT(0);
1201 return CDF_STATUS_E_NOMEM;
1202 }
1203
1204 if (moduleID == CDF_MODULE_ID_TLSHIM)
1205 cdf_mem_zero(*ppModuleContext, size);
1206
1207 *pGpModContext = *ppModuleContext;
1208
1209 return CDF_STATUS_SUCCESS;
1210} /* cds_alloc_context() */
1211
1212/**
1213 * cds_free_context() - free an allocated context within the
1214 * CDS global Context
1215 * @p_cds_context: pointer to the global Vos context
1216 * @moduleId: module ID who's context area is being free
1217 * @pModuleContext: pointer to module context area to be free'd.
1218 *
1219 * This API allows a user to free the user context area within the
1220 * CDS Global Context.
1221 *
1222 * Return: CDF status
1223 */
1224CDF_STATUS cds_free_context(void *p_cds_context, CDF_MODULE_ID moduleID,
1225 void *pModuleContext)
1226{
1227 void **pGpModContext = NULL;
1228
1229 if ((p_cds_context == NULL) || (gp_cds_context != p_cds_context) ||
1230 (pModuleContext == NULL)) {
1231 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1232 "%s: Null params or context mismatch", __func__);
1233 return CDF_STATUS_E_FAILURE;
1234 }
1235
1236 switch (moduleID) {
1237#ifndef WLAN_FEATURE_MBSSID
1238 case CDF_MODULE_ID_SAP:
1239 {
1240 pGpModContext = &(gp_cds_context->pSAPContext);
1241 break;
1242 }
1243#endif
1244
1245 case CDF_MODULE_ID_WMA:
1246 {
1247 pGpModContext = &(gp_cds_context->pWMAContext);
1248 break;
1249 }
1250
1251 case CDF_MODULE_ID_HIF:
1252 {
1253 pGpModContext = &(gp_cds_context->pHIFContext);
1254 break;
1255 }
1256
1257 case CDF_MODULE_ID_EPPING:
1258 {
1259 pGpModContext = &(gp_cds_context->epping_ctx);
1260 break;
1261 }
1262
1263 case CDF_MODULE_ID_TXRX:
1264 {
1265 pGpModContext = &(gp_cds_context->pdev_txrx_ctx);
1266 break;
1267 }
1268
1269 case CDF_MODULE_ID_HDD:
1270 case CDF_MODULE_ID_SME:
1271 case CDF_MODULE_ID_PE:
1272 case CDF_MODULE_ID_HDD_SOFTAP:
1273 default:
1274 {
1275 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1276 "%s: Module ID %i "
1277 "does not have its context allocated by CDS",
1278 __func__, moduleID);
1279 CDF_ASSERT(0);
1280 return CDF_STATUS_E_INVAL;
1281 }
1282 }
1283
1284 if (NULL == *pGpModContext) {
1285 /* Context has not been allocated or freed already! */
1286 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1287 "%s: Module ID %i "
1288 "context has not been allocated or freed already",
1289 __func__, moduleID);
1290 return CDF_STATUS_E_FAILURE;
1291 }
1292
1293 if (*pGpModContext != pModuleContext) {
1294 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1295 "%s: pGpModContext != pModuleContext", __func__);
1296 return CDF_STATUS_E_FAILURE;
1297 }
1298
1299 if (pModuleContext != NULL)
1300 cdf_mem_free(pModuleContext);
1301
1302 *pGpModContext = NULL;
1303
1304 return CDF_STATUS_SUCCESS;
1305} /* cds_free_context() */
1306
1307/**
1308 * cds_mq_post_message() - post a message to a message queue
1309 * @msgQueueId: identifies the message queue upon which the message
1310 * will be posted.
1311 * @message: a pointer to a message buffer. Memory for this message
1312 * buffer is allocated by the caller and free'd by the CDF after the
1313 * message is posted to the message queue. If the consumer of the
1314 * message needs anything in this message, it needs to copy the contents
1315 * before returning from the message queue handler.
1316 *
1317 * Return: CDF status
1318 */
1319CDF_STATUS cds_mq_post_message(CDS_MQ_ID msgQueueId, cds_msg_t *pMsg)
1320{
1321 p_cds_mq_type pTargetMq = NULL;
1322 p_cds_msg_wrapper pMsgWrapper = NULL;
1323 uint32_t debug_count = 0;
1324
1325 if ((gp_cds_context == NULL) || (pMsg == NULL)) {
1326 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1327 "%s: Null params or global cds context is null",
1328 __func__);
1329 CDF_ASSERT(0);
1330 return CDF_STATUS_E_FAILURE;
1331 }
1332
1333 switch (msgQueueId) {
1334 /* Message Queue ID for messages bound for SME */
1335 case CDS_MQ_ID_SME:
1336 {
1337 pTargetMq = &(gp_cds_context->cdf_sched.smeMcMq);
1338 break;
1339 }
1340
1341 /* Message Queue ID for messages bound for PE */
1342 case CDS_MQ_ID_PE:
1343 {
1344 pTargetMq = &(gp_cds_context->cdf_sched.peMcMq);
1345 break;
1346 }
1347
1348 /* Message Queue ID for messages bound for wma */
1349 case CDS_MQ_ID_WMA:
1350 {
1351 pTargetMq = &(gp_cds_context->cdf_sched.wmaMcMq);
1352 break;
1353 }
1354
1355 /* Message Queue ID for messages bound for the SYS module */
1356 case CDS_MQ_ID_SYS:
1357 {
1358 pTargetMq = &(gp_cds_context->cdf_sched.sysMcMq);
1359 break;
1360 }
1361
1362 default:
1363 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1364 ("%s: Trying to queue msg into unknown MC Msg queue ID %d"),
1365 __func__, msgQueueId);
1366
1367 return CDF_STATUS_E_FAILURE;
1368 }
1369
1370 CDF_ASSERT(NULL != pTargetMq);
1371 if (pTargetMq == NULL) {
1372 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1373 "%s: pTargetMq == NULL", __func__);
1374 return CDF_STATUS_E_FAILURE;
1375 }
1376
1377 /* Try and get a free Msg wrapper */
1378 pMsgWrapper = cds_mq_get(&gp_cds_context->freeVosMq);
1379
1380 if (NULL == pMsgWrapper) {
1381 debug_count = atomic_inc_return(&cds_wrapper_empty_count);
1382 if (1 == debug_count)
1383 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1384 "%s: CDS Core run out of message wrapper %d",
1385 __func__, debug_count);
1386
1387 if (CDS_WRAPPER_MAX_FAIL_COUNT == debug_count)
1388 CDF_BUG(0);
1389
1390 return CDF_STATUS_E_RESOURCES;
1391 }
1392
1393 atomic_set(&cds_wrapper_empty_count, 0);
1394
1395 /* Copy the message now */
1396 cdf_mem_copy((void *)pMsgWrapper->pVosMsg,
1397 (void *)pMsg, sizeof(cds_msg_t));
1398
1399 cds_mq_put(pTargetMq, pMsgWrapper);
1400
1401 set_bit(MC_POST_EVENT_MASK, &gp_cds_context->cdf_sched.mcEventFlag);
1402 wake_up_interruptible(&gp_cds_context->cdf_sched.mcWaitQueue);
1403
1404 return CDF_STATUS_SUCCESS;
1405} /* cds_mq_post_message() */
1406
1407/**
1408 * cds_sys_probe_thread_cback() - probe mc thread callback
1409 * @pUserData: pointer to user data
1410 *
1411 * Return: none
1412 */
1413void cds_sys_probe_thread_cback(void *pUserData)
1414{
1415 if (gp_cds_context != pUserData) {
1416 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1417 "%s: gp_cds_context != pUserData", __func__);
1418 return;
1419 }
1420
1421 if (cdf_event_set(&gp_cds_context->ProbeEvent) != CDF_STATUS_SUCCESS) {
1422 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1423 "%s: cdf_event_set failed", __func__);
1424 return;
1425 }
1426} /* cds_sys_probe_thread_cback() */
1427
1428/**
1429 * cds_wma_complete_cback() - wma complete callback
1430 * @pUserData: pointer to user data
1431 *
1432 * Return: none
1433 */
1434void cds_wma_complete_cback(void *pUserData)
1435{
1436 if (gp_cds_context != pUserData) {
1437 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1438 "%s: gp_cds_context != pUserData", __func__);
1439 return;
1440 }
1441
1442 if (cdf_event_set(&gp_cds_context->wmaCompleteEvent) !=
1443 CDF_STATUS_SUCCESS) {
1444 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1445 "%s: cdf_event_set failed", __func__);
1446 return;
1447 }
1448} /* cds_wma_complete_cback() */
1449
1450/**
1451 * cds_core_return_msg() - return core message
1452 * @pVContext: pointer to cds context
1453 * @pMsgWrapper: pointer to message wrapper
1454 *
1455 * Return: none
1456 */
1457void cds_core_return_msg(void *pVContext, p_cds_msg_wrapper pMsgWrapper)
1458{
1459 p_cds_contextType p_cds_context = (p_cds_contextType) pVContext;
1460
1461 CDF_ASSERT(gp_cds_context == p_cds_context);
1462
1463 if (gp_cds_context != p_cds_context) {
1464 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1465 "%s: gp_cds_context != p_cds_context", __func__);
1466 return;
1467 }
1468
1469 CDF_ASSERT(NULL != pMsgWrapper);
1470
1471 if (pMsgWrapper == NULL) {
1472 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1473 "%s: pMsgWrapper == NULL in function", __func__);
1474 return;
1475 }
1476
1477 /*
1478 ** Return the message on the free message queue
1479 */
1480 INIT_LIST_HEAD(&pMsgWrapper->msgNode);
1481 cds_mq_put(&p_cds_context->freeVosMq, pMsgWrapper);
1482} /* cds_core_return_msg() */
1483
1484
1485/**
1486 * cds_shutdown() - shutdown CDS
1487 * @cds_context: global cds context
1488 *
1489 * Return: CDF status
1490 */
1491CDF_STATUS cds_shutdown(v_CONTEXT_t cds_context)
1492{
1493 CDF_STATUS cdf_status;
1494 tpAniSirGlobal pmac = (((p_cds_contextType)cds_context)->pMACContext);
1495
1496 ol_txrx_pdev_detach(gp_cds_context->pdev_txrx_ctx, 1);
1497 cds_free_context(cds_context, CDF_MODULE_ID_TXRX,
1498 gp_cds_context->pdev_txrx_ctx);
1499
1500 cdf_status = sme_close(((p_cds_contextType) cds_context)->pMACContext);
1501 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1502 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1503 "%s: Failed to close SME", __func__);
1504 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
1505 }
1506 /*
1507 * CAC timer will be initiated and started only when SAP starts on
1508 * DFS channel and it will be stopped and destroyed immediately once the
1509 * radar detected or timedout. So as per design CAC timer should be
1510 * destroyed after stop
1511 */
1512 if (pmac->sap.SapDfsInfo.is_dfs_cac_timer_running) {
1513 cdf_mc_timer_stop(&pmac->sap.SapDfsInfo.sap_dfs_cac_timer);
1514 pmac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0;
1515 cdf_mc_timer_destroy(&pmac->sap.SapDfsInfo.sap_dfs_cac_timer);
1516 }
1517
1518 cdf_status = mac_close(((p_cds_contextType) cds_context)->pMACContext);
1519 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1520 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1521 "%s: Failed to close MAC", __func__);
1522 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
1523 }
1524
1525 ((p_cds_contextType) cds_context)->pMACContext = NULL;
1526
1527 if (false == wma_needshutdown(cds_context)) {
1528
1529 cdf_status = wma_close(cds_context);
1530 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1531 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1532 "%s: Failed to close wma!", __func__);
1533 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
1534 }
1535 }
1536
1537 if (gp_cds_context->htc_ctx) {
1538 htc_stop(gp_cds_context->htc_ctx);
1539 htc_destroy(gp_cds_context->htc_ctx);
1540 gp_cds_context->htc_ctx = NULL;
1541 }
1542
1543 cdf_status = wma_wmi_service_close(cds_context);
1544 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1545 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1546 "%s: Failed to close wma_wmi_service!", __func__);
1547 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
1548 }
1549
1550 cds_mq_deinit(&((p_cds_contextType) cds_context)->freeVosMq);
1551
1552 cdf_status = cdf_event_destroy(&gp_cds_context->wmaCompleteEvent);
1553 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1554 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1555 "%s: failed to destroy wmaCompleteEvent", __func__);
1556 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
1557 }
1558
1559 cdf_status = cdf_event_destroy(&gp_cds_context->ProbeEvent);
1560 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1561 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1562 "%s: failed to destroy ProbeEvent", __func__);
1563 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
1564 }
1565
1566 return CDF_STATUS_SUCCESS;
1567}
1568
1569/**
1570 * cds_get_vdev_types() - get vdev type
1571 * @mode: mode
1572 * @type: type
1573 * @sub_type: sub_type
1574 *
1575 * Return: WMI vdev type
1576 */
1577CDF_STATUS cds_get_vdev_types(tCDF_CON_MODE mode, uint32_t *type,
1578 uint32_t *sub_type)
1579{
1580 CDF_STATUS status = CDF_STATUS_SUCCESS;
1581 *type = 0;
1582 *sub_type = 0;
1583
1584 switch (mode) {
1585 case CDF_STA_MODE:
1586 *type = WMI_VDEV_TYPE_STA;
1587 break;
1588 case CDF_SAP_MODE:
1589 *type = WMI_VDEV_TYPE_AP;
1590 break;
1591 case CDF_P2P_DEVICE_MODE:
1592 *type = WMI_VDEV_TYPE_AP;
1593 *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE;
1594 break;
1595 case CDF_P2P_CLIENT_MODE:
1596 *type = WMI_VDEV_TYPE_STA;
1597 *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT;
1598 break;
1599 case CDF_P2P_GO_MODE:
1600 *type = WMI_VDEV_TYPE_AP;
1601 *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO;
1602 break;
1603 case CDF_OCB_MODE:
1604 *type = WMI_VDEV_TYPE_OCB;
1605 break;
1606 default:
1607 hddLog(CDF_TRACE_LEVEL_ERROR, "Invalid device mode %d", mode);
1608 status = CDF_STATUS_E_INVAL;
1609 break;
1610 }
1611 return status;
1612}
1613
1614/**
1615 * cds_flush_work() - flush pending works
1616 * @work: pointer to work
1617 *
1618 * Return: none
1619 */
1620void cds_flush_work(void *work)
1621{
1622#if defined (CONFIG_CNSS)
1623 cnss_flush_work(work);
1624#elif defined (WLAN_OPEN_SOURCE)
1625 cancel_work_sync(work);
1626#endif
1627}
1628
1629/**
1630 * cds_flush_delayed_work() - flush delayed works
1631 * @dwork: pointer to delayed work
1632 *
1633 * Return: none
1634 */
1635void cds_flush_delayed_work(void *dwork)
1636{
1637#if defined (CONFIG_CNSS)
1638 cnss_flush_delayed_work(dwork);
1639#elif defined (WLAN_OPEN_SOURCE)
1640 cancel_delayed_work_sync(dwork);
1641#endif
1642}
1643
1644/**
1645 * cds_is_packet_log_enabled() - check if packet log is enabled
1646 *
1647 * Return: true if packet log is enabled else false
1648 */
1649bool cds_is_packet_log_enabled(void)
1650{
1651 hdd_context_t *pHddCtx;
1652
1653 pHddCtx = (hdd_context_t *) (gp_cds_context->pHDDContext);
1654 if ((NULL == pHddCtx) || (NULL == pHddCtx->config)) {
1655 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_FATAL,
1656 "%s: Hdd Context is Null", __func__);
1657 return false;
1658 }
1659
1660 return pHddCtx->config->enablePacketLog;
1661}
1662
1663/**
1664 * cds_trigger_recovery() - trigger self recovery
1665 *
1666 * Return: none
1667 */
1668void cds_trigger_recovery(void)
1669{
1670 tp_wma_handle wma_handle = cds_get_context(CDF_MODULE_ID_WMA);
1671 CDF_STATUS status = CDF_STATUS_SUCCESS;
1672
1673 if (!wma_handle) {
1674 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1675 "WMA context is invald!");
1676 return;
1677 }
1678
1679 wma_crash_inject(wma_handle, RECOVERY_SIM_SELF_RECOVERY, 0);
1680
1681 status = cdf_wait_single_event(&wma_handle->recovery_event,
1682 WMA_CRASH_INJECT_TIMEOUT);
1683
1684 if (CDF_STATUS_SUCCESS != status) {
1685 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1686 "CRASH_INJECT command is timed out!");
1687 #ifdef CONFIG_CNSS
1688 if (cds_is_logp_in_progress()) {
1689 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1690 "LOGP is in progress, ignore!");
1691 return;
1692 }
1693 cds_set_logp_in_progress(true);
1694 cnss_schedule_recovery_work();
1695 #endif
1696
1697 return;
1698 }
1699}
1700
1701/**
1702 * cds_get_monotonic_boottime() - Get kernel boot time.
1703 *
1704 * Return: Time in microseconds
1705 */
1706
1707uint64_t cds_get_monotonic_boottime(void)
1708{
1709#ifdef CONFIG_CNSS
1710 struct timespec ts;
1711
1712 cnss_get_monotonic_boottime(&ts);
1713 return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
1714#else
1715 return ((uint64_t)cdf_system_ticks_to_msecs(cdf_system_ticks()) *
1716 1000);
1717#endif
1718}
1719
1720/**
1721 * cds_set_wakelock_logging() - Logging of wakelock enabled/disabled
1722 * @value: Boolean value
1723 *
1724 * This function is used to set the flag which will indicate whether
1725 * logging of wakelock is enabled or not
1726 *
1727 * Return: None
1728 */
1729void cds_set_wakelock_logging(bool value)
1730{
1731 p_cds_contextType p_cds_context;
1732
1733 p_cds_context = cds_get_global_context();
1734 if (!p_cds_context) {
1735 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1736 "cds context is Invald");
1737 return;
1738 }
1739 p_cds_context->is_wakelock_log_enabled = value;
1740}
1741
1742/**
1743 * cds_is_wakelock_enabled() - Check if logging of wakelock is enabled/disabled
1744 * @value: Boolean value
1745 *
1746 * This function is used to check whether logging of wakelock is enabled or not
1747 *
1748 * Return: true if logging of wakelock is enabled
1749 */
1750bool cds_is_wakelock_enabled(void)
1751{
1752 p_cds_contextType p_cds_context;
1753
1754 p_cds_context = cds_get_global_context();
1755 if (!p_cds_context) {
1756 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1757 "cds context is Invald");
1758 return false;
1759 }
1760 return p_cds_context->is_wakelock_log_enabled;
1761}
1762
1763/**
1764 * cds_set_ring_log_level() - Sets the log level of a particular ring
1765 * @ring_id: ring_id
1766 * @log_levelvalue: Log level specificed
1767 *
1768 * This function converts HLOS values to driver log levels and sets the log
1769 * level of a particular ring accordingly.
1770 *
1771 * Return: None
1772 */
1773void cds_set_ring_log_level(uint32_t ring_id, uint32_t log_level)
1774{
1775 p_cds_contextType p_cds_context;
1776 uint32_t log_val;
1777
1778 p_cds_context = cds_get_global_context();
1779 if (!p_cds_context) {
1780 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1781 "%s: cds context is Invald", __func__);
1782 return;
1783 }
1784
1785 switch (log_level) {
1786 case LOG_LEVEL_NO_COLLECTION:
1787 log_val = WLAN_LOG_LEVEL_OFF;
1788 break;
1789 case LOG_LEVEL_NORMAL_COLLECT:
1790 log_val = WLAN_LOG_LEVEL_NORMAL;
1791 break;
1792 case LOG_LEVEL_ISSUE_REPRO:
1793 log_val = WLAN_LOG_LEVEL_REPRO;
1794 break;
1795 case LOG_LEVEL_ACTIVE:
1796 default:
1797 log_val = WLAN_LOG_LEVEL_ACTIVE;
1798 break;
1799 }
1800
1801 if (ring_id == RING_ID_WAKELOCK) {
1802 p_cds_context->wakelock_log_level = log_val;
1803 return;
1804 } else if (ring_id == RING_ID_CONNECTIVITY) {
1805 p_cds_context->connectivity_log_level = log_val;
1806 return;
1807 } else if (ring_id == RING_ID_PER_PACKET_STATS) {
1808 p_cds_context->packet_stats_log_level = log_val;
1809 return;
1810 } else if (ring_id == RIND_ID_DRIVER_DEBUG) {
1811 p_cds_context->driver_debug_log_level = log_val;
1812 return;
1813 } else if (ring_id == RING_ID_FIRMWARE_DEBUG) {
1814 p_cds_context->fw_debug_log_level = log_val;
1815 return;
1816 }
1817}
1818
1819/**
1820 * cds_get_ring_log_level() - Get the a ring id's log level
1821 * @ring_id: Ring id
1822 *
1823 * Fetch and return the log level corresponding to a ring id
1824 *
1825 * Return: Log level corresponding to the ring ID
1826 */
1827enum wifi_driver_log_level cds_get_ring_log_level(uint32_t ring_id)
1828{
1829 p_cds_contextType p_cds_context;
1830
1831 p_cds_context = cds_get_global_context();
1832 if (!p_cds_context) {
1833 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1834 "%s: cds context is Invald", __func__);
1835 return WLAN_LOG_LEVEL_OFF;
1836 }
1837
1838 if (ring_id == RING_ID_WAKELOCK)
1839 return p_cds_context->wakelock_log_level;
1840 else if (ring_id == RING_ID_CONNECTIVITY)
1841 return p_cds_context->connectivity_log_level;
1842 else if (ring_id == RING_ID_PER_PACKET_STATS)
1843 return p_cds_context->packet_stats_log_level;
1844 else if (ring_id == RIND_ID_DRIVER_DEBUG)
1845 return p_cds_context->driver_debug_log_level;
1846 else if (ring_id == RING_ID_FIRMWARE_DEBUG)
1847 return p_cds_context->fw_debug_log_level;
1848
1849 return WLAN_LOG_LEVEL_OFF;
1850}
1851
1852/**
1853 * cds_set_multicast_logging() - Set mutlicast logging value
1854 * @value: Value of multicast logging
1855 *
1856 * Set the multicast logging value which will indicate
1857 * whether to multicast host and fw messages even
1858 * without any registration by userspace entity
1859 *
1860 * Return: None
1861 */
1862void cds_set_multicast_logging(uint8_t value)
1863{
1864 cds_multicast_logging = value;
1865}
1866
1867/**
1868 * cds_is_multicast_logging() - Get multicast logging value
1869 *
1870 * Get the multicast logging value which will indicate
1871 * whether to multicast host and fw messages even
1872 * without any registration by userspace entity
1873 *
1874 * Return: 0 - Multicast logging disabled, 1 - Multicast logging enabled
1875 */
1876uint8_t cds_is_multicast_logging(void)
1877{
1878 return cds_multicast_logging;
1879}
1880
1881/*
1882 * cds_init_log_completion() - Initialize log param structure
1883 *
1884 * This function is used to initialize the logging related
1885 * parameters
1886 *
1887 * Return: None
1888 */
1889void cds_init_log_completion(void)
1890{
1891 p_cds_contextType p_cds_context;
1892
1893 p_cds_context = cds_get_global_context();
1894 if (!p_cds_context) {
1895 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1896 "%s: cds context is Invalid", __func__);
1897 return;
1898 }
1899
1900 p_cds_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL;
1901 p_cds_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED;
1902 p_cds_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED;
1903 p_cds_context->log_complete.is_report_in_progress = false;
1904 /* Attempting to initialize an already initialized lock
1905 * results in a failure. This must be ok here.
1906 */
1907 cdf_spinlock_init(&p_cds_context->bug_report_lock);
1908}
1909
1910/**
1911 * cds_deinit_log_completion() - Deinitialize log param structure
1912 *
1913 * This function is used to deinitialize the logging related
1914 * parameters
1915 *
1916 * Return: None
1917 */
1918void cds_deinit_log_completion(void)
1919{
1920 p_cds_contextType p_cds_context;
1921
1922 p_cds_context = cds_get_global_context();
1923 if (!p_cds_context) {
1924 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1925 "%s: cds context is Invalid", __func__);
1926 return;
1927 }
1928
1929 cdf_spinlock_destroy(&p_cds_context->bug_report_lock);
1930}
1931
1932/**
1933 * cds_set_log_completion() - Store the logging params
1934 * @is_fatal: Indicates if the event triggering bug report is fatal or not
1935 * @indicator: Source which trigerred the bug report
1936 * @reason_code: Reason for triggering bug report
1937 *
1938 * This function is used to set the logging parameters based on the
1939 * caller
1940 *
1941 * Return: 0 if setting of params is successful
1942 */
1943CDF_STATUS cds_set_log_completion(uint32_t is_fatal,
1944 uint32_t indicator,
1945 uint32_t reason_code)
1946{
1947 p_cds_contextType p_cds_context;
1948
1949 p_cds_context = cds_get_global_context();
1950 if (!p_cds_context) {
1951 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1952 "%s: cds context is Invalid", __func__);
1953 return CDF_STATUS_E_FAILURE;
1954 }
1955
1956 cdf_spinlock_acquire(&p_cds_context->bug_report_lock);
1957 p_cds_context->log_complete.is_fatal = is_fatal;
1958 p_cds_context->log_complete.indicator = indicator;
1959 p_cds_context->log_complete.reason_code = reason_code;
1960 p_cds_context->log_complete.is_report_in_progress = true;
1961 cdf_spinlock_release(&p_cds_context->bug_report_lock);
1962 return CDF_STATUS_SUCCESS;
1963}
1964
1965/**
1966 * cds_get_log_completion() - Get the logging related params
1967 * @is_fatal: Indicates if the event triggering bug report is fatal or not
1968 * @indicator: Source which trigerred the bug report
1969 * @reason_code: Reason for triggering bug report
1970 *
1971 * This function is used to get the logging related parameters
1972 *
1973 * Return: None
1974 */
1975void cds_get_log_completion(uint32_t *is_fatal,
1976 uint32_t *indicator,
1977 uint32_t *reason_code)
1978{
1979 p_cds_contextType p_cds_context;
1980
1981 p_cds_context = cds_get_global_context();
1982 if (!p_cds_context) {
1983 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1984 "%s: cds context is Invalid", __func__);
1985 return;
1986 }
1987
1988 cdf_spinlock_acquire(&p_cds_context->bug_report_lock);
1989 *is_fatal = p_cds_context->log_complete.is_fatal;
1990 *indicator = p_cds_context->log_complete.indicator;
1991 *reason_code = p_cds_context->log_complete.reason_code;
1992 p_cds_context->log_complete.is_report_in_progress = false;
1993 cdf_spinlock_release(&p_cds_context->bug_report_lock);
1994}
1995
1996/**
1997 * cds_is_log_report_in_progress() - Check if bug reporting is in progress
1998 *
1999 * This function is used to check if the bug reporting is already in progress
2000 *
2001 * Return: true if the bug reporting is in progress
2002 */
2003bool cds_is_log_report_in_progress(void)
2004{
2005 p_cds_contextType p_cds_context;
2006
2007 p_cds_context = cds_get_global_context();
2008 if (!p_cds_context) {
2009 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
2010 "%s: cds context is Invalid", __func__);
2011 return true;
2012 }
2013 return p_cds_context->log_complete.is_report_in_progress;
2014}
2015
2016/**
2017 * cds_flush_logs() - Report fatal event to userspace
2018 * @is_fatal: Indicates if the event triggering bug report is fatal or not
2019 * @indicator: Source which trigerred the bug report
2020 * @reason_code: Reason for triggering bug report
2021 *
2022 * This function sets the log related params and send the WMI command to the
2023 * FW to flush its logs. On receiving the flush completion event from the FW
2024 * the same will be conveyed to userspace
2025 *
2026 * Return: 0 on success
2027 */
2028CDF_STATUS cds_flush_logs(uint32_t is_fatal,
2029 uint32_t indicator,
2030 uint32_t reason_code)
2031{
2032 uint32_t ret;
2033 CDF_STATUS status;
2034
2035 p_cds_contextType p_cds_context;
2036
2037 p_cds_context = cds_get_global_context();
2038 if (!p_cds_context) {
2039 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
2040 "%s: cds context is Invalid", __func__);
2041 return CDF_STATUS_E_FAILURE;
2042 }
2043
2044 if (cds_is_log_report_in_progress() == true) {
2045 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
2046 "%s: Bug report already in progress - dropping! type:%d, indicator=%d reason_code=%d",
2047 __func__, is_fatal, indicator, reason_code);
2048 return CDF_STATUS_E_FAILURE;
2049 }
2050
2051 status = cds_set_log_completion(is_fatal, indicator, reason_code);
2052 if (CDF_STATUS_SUCCESS != status) {
2053 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
2054 "%s: Failed to set log trigger params", __func__);
2055 return CDF_STATUS_E_FAILURE;
2056 }
2057
2058 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
2059 "%s: Triggering bug report: type:%d, indicator=%d reason_code=%d",
2060 __func__, is_fatal, indicator, reason_code);
2061
2062 ret = sme_send_flush_logs_cmd_to_fw(p_cds_context->pMACContext);
2063 if (0 != ret) {
2064 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
2065 "%s: Failed to send flush FW log", __func__);
2066 cds_init_log_completion();
2067 return CDF_STATUS_E_FAILURE;
2068 }
2069
2070 return CDF_STATUS_SUCCESS;
2071}
2072
2073/**
2074 * cds_logging_set_fw_flush_complete() - Wrapper for FW log flush completion
2075 *
2076 * This function is used to send signal to the logger thread to indicate
2077 * that the flushing of FW logs is complete by the FW
2078 *
2079 * Return: None
2080 *
2081 */
2082void cds_logging_set_fw_flush_complete(void)
2083{
2084 wlan_logging_set_fw_flush_complete();
2085}