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