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