1  /*
2   * Copyright (c) 2015-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   * Host WMI unified implementation
22   */
23  #include "htc_api.h"
24  #include "htc_api.h"
25  #include "wmi_unified_priv.h"
26  #include "wmi_unified_api.h"
27  #include "qdf_module.h"
28  #include "qdf_platform.h"
29  #include "qdf_ssr_driver_dump.h"
30  #ifdef WMI_EXT_DBG
31  #include "qdf_list.h"
32  #include "qdf_atomic.h"
33  #endif
34  
35  #ifndef WMI_NON_TLV_SUPPORT
36  #include "wmi_tlv_helper.h"
37  #endif
38  
39  #include <linux/debugfs.h>
40  #include <target_if.h>
41  #include <qdf_debugfs.h>
42  #include "wmi_filtered_logging.h"
43  #include <wmi_hang_event.h>
44  
45  #ifdef DP_UMAC_HW_RESET_SUPPORT
46  #include <cdp_txrx_ctrl.h>
47  #endif
48  
49  /* This check for CONFIG_WIN temporary added due to redeclaration compilation
50  error in MCL. Error is caused due to inclusion of wmi.h in wmi_unified_api.h
51  which gets included here through ol_if_athvar.h. Eventually it is expected that
52  wmi.h will be removed from wmi_unified_api.h after cleanup, which will need
53  WMI_CMD_HDR to be defined here. */
54  /* Copied from wmi.h */
55  #undef MS
56  #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
57  #undef SM
58  #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
59  #undef WO
60  #define WO(_f)      ((_f##_OFFSET) >> 2)
61  
62  #undef GET_FIELD
63  #define GET_FIELD(_addr, _f) MS(*((uint32_t *)(_addr) + WO(_f)), _f)
64  #undef SET_FIELD
65  #define SET_FIELD(_addr, _f, _val)  \
66  	    (*((uint32_t *)(_addr) + WO(_f)) = \
67  		(*((uint32_t *)(_addr) + WO(_f)) & ~_f##_MASK) | SM(_val, _f))
68  
69  #define WMI_GET_FIELD(_msg_buf, _msg_type, _f) \
70  	    GET_FIELD(_msg_buf, _msg_type ## _ ## _f)
71  
72  #define WMI_SET_FIELD(_msg_buf, _msg_type, _f, _val) \
73  	    SET_FIELD(_msg_buf, _msg_type ## _ ## _f, _val)
74  
75  #define WMI_EP_APASS           0x0
76  #define WMI_EP_LPASS           0x1
77  #define WMI_EP_SENSOR          0x2
78  
79  #define WMI_INFOS_DBG_FILE_PERM (QDF_FILE_USR_READ | \
80  				 QDF_FILE_USR_WRITE | \
81  				 QDF_FILE_GRP_READ | \
82  				 QDF_FILE_OTH_READ)
83  
84  /*
85   *  * Control Path
86   *   */
87  typedef PREPACK struct {
88  	uint32_t	commandId:24,
89  			reserved:2, /* used for WMI endpoint ID */
90  			plt_priv:6; /* platform private */
91  } POSTPACK WMI_CMD_HDR;        /* used for commands and events */
92  
93  #define WMI_CMD_HDR_COMMANDID_LSB           0
94  #define WMI_CMD_HDR_COMMANDID_MASK          0x00ffffff
95  #define WMI_CMD_HDR_COMMANDID_OFFSET        0x00000000
96  #define WMI_CMD_HDR_WMI_ENDPOINTID_MASK        0x03000000
97  #define WMI_CMD_HDR_WMI_ENDPOINTID_OFFSET      24
98  #define WMI_CMD_HDR_PLT_PRIV_LSB               24
99  #define WMI_CMD_HDR_PLT_PRIV_MASK              0xff000000
100  #define WMI_CMD_HDR_PLT_PRIV_OFFSET            0x00000000
101  /* end of copy wmi.h */
102  
103  #define WMI_MIN_HEAD_ROOM 64
104  
105  /* WBUFF pool sizes for WMI */
106  /* Allocation of size 256 bytes */
107  #define WMI_WBUFF_POOL_0_SIZE 128
108  /* Allocation of size 512 bytes */
109  #define WMI_WBUFF_POOL_1_SIZE 16
110  /* Allocation of size 1024 bytes */
111  #define WMI_WBUFF_POOL_2_SIZE 8
112  /* Allocation of size 2048 bytes */
113  #define WMI_WBUFF_POOL_3_SIZE 8
114  
115  /* wbuff pool buffer lengths in bytes for WMI*/
116  #define WMI_WBUFF_LEN_POOL0 256
117  #define WMI_WBUFF_LEN_POOL1 512
118  #define WMI_WBUFF_LEN_POOL2 1024
119  #define WMI_WBUFF_LEN_POOL3 2048
120  
121  #define RX_DIAG_EVENT_WORK_PROCESS_MAX_COUNT 500
122  
123  #ifdef WMI_INTERFACE_EVENT_LOGGING
124  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0))
125  /* TODO Cleanup this backported function */
wmi_bp_seq_printf(qdf_debugfs_file_t m,const char * f,...)126  static int wmi_bp_seq_printf(qdf_debugfs_file_t m, const char *f, ...)
127  {
128  	va_list args;
129  
130  	va_start(args, f);
131  	seq_vprintf(m, f, args);
132  	va_end(args);
133  
134  	return 0;
135  }
136  #else
137  #define wmi_bp_seq_printf(m, fmt, ...) seq_printf((m), fmt, ##__VA_ARGS__)
138  #endif
139  
140  #ifndef MAX_WMI_INSTANCES
141  #define CUSTOM_MGMT_CMD_DATA_SIZE 4
142  #endif
143  
144  #ifndef WMI_INTERFACE_EVENT_LOGGING_DYNAMIC_ALLOC
145  /* WMI commands */
146  uint32_t g_wmi_command_buf_idx = 0;
147  struct wmi_command_debug wmi_command_log_buffer[WMI_CMD_DEBUG_MAX_ENTRY];
148  
149  /* WMI commands TX completed */
150  uint32_t g_wmi_command_tx_cmp_buf_idx = 0;
151  struct wmi_command_cmp_debug
152  	wmi_command_tx_cmp_log_buffer[WMI_CMD_CMPL_DEBUG_MAX_ENTRY];
153  
154  /* WMI events when processed */
155  uint32_t g_wmi_event_buf_idx = 0;
156  struct wmi_event_debug wmi_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
157  
158  /* WMI events when queued */
159  uint32_t g_wmi_rx_event_buf_idx = 0;
160  struct wmi_event_debug wmi_rx_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
161  #endif
162  
wmi_minidump_detach(struct wmi_unified * wmi_handle)163  static void wmi_minidump_detach(struct wmi_unified *wmi_handle)
164  {
165  	struct wmi_log_buf_t *info =
166  		&wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info;
167  	uint32_t buf_size = info->size * sizeof(struct wmi_command_cmp_debug);
168  
169  	qdf_ssr_driver_dump_unregister_region("wmi_debug_log_info");
170  	qdf_ssr_driver_dump_unregister_region("wmi_rx_event_idx");
171  	qdf_ssr_driver_dump_unregister_region("wmi_rx_event");
172  	qdf_ssr_driver_dump_unregister_region("wmi_event_log_idx");
173  	qdf_ssr_driver_dump_unregister_region("wmi_event_log");
174  	qdf_ssr_driver_dump_unregister_region("wmi_command_log_idx");
175  	qdf_ssr_driver_dump_unregister_region("wmi_command_log");
176  	qdf_ssr_driver_dump_unregister_region("wmi_tx_cmp_idx");
177  	qdf_ssr_driver_dump_unregister_region("wmi_tx_cmp");
178  	qdf_minidump_remove(info->buf, buf_size, "wmi_tx_cmp");
179  }
180  
wmi_minidump_attach(struct wmi_unified * wmi_handle)181  static void wmi_minidump_attach(struct wmi_unified *wmi_handle)
182  {
183  	struct wmi_log_buf_t *info =
184  		&wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info;
185  	uint32_t buf_size = info->size * sizeof(struct wmi_command_cmp_debug);
186  
187  	qdf_minidump_log(info->buf, buf_size, "wmi_tx_cmp");
188  
189  	qdf_ssr_driver_dump_register_region("wmi_tx_cmp", info->buf, buf_size);
190  	qdf_ssr_driver_dump_register_region("wmi_tx_cmp_idx",
191  					    info->p_buf_tail_idx,
192  					    sizeof(*info->p_buf_tail_idx));
193  
194  	info = &wmi_handle->log_info.wmi_command_log_buf_info;
195  	buf_size = info->size * sizeof(struct wmi_command_debug);
196  
197  	qdf_ssr_driver_dump_register_region("wmi_command_log", info->buf,
198  					    buf_size);
199  	qdf_ssr_driver_dump_register_region("wmi_command_log_idx",
200  					    info->p_buf_tail_idx,
201  					    sizeof(*info->p_buf_tail_idx));
202  
203  	info = &wmi_handle->log_info.wmi_event_log_buf_info;
204  	buf_size = info->size * sizeof(struct wmi_event_debug);
205  
206  	qdf_ssr_driver_dump_register_region("wmi_event_log", info->buf,
207  					    buf_size);
208  	qdf_ssr_driver_dump_register_region("wmi_event_log_idx",
209  					    info->p_buf_tail_idx,
210  					    sizeof(*info->p_buf_tail_idx));
211  
212  	info = &wmi_handle->log_info.wmi_rx_event_log_buf_info;
213  	buf_size = info->size * sizeof(struct wmi_event_debug);
214  
215  	qdf_ssr_driver_dump_register_region("wmi_rx_event", info->buf,
216  					    buf_size);
217  	qdf_ssr_driver_dump_register_region("wmi_rx_event_idx",
218  					    info->p_buf_tail_idx,
219  					    sizeof(*info->p_buf_tail_idx));
220  
221  	qdf_ssr_driver_dump_register_region("wmi_debug_log_info",
222  					    &wmi_handle->log_info,
223  					    sizeof(wmi_handle->log_info));
224  }
225  
226  #define WMI_COMMAND_RECORD(h, a, b) {					\
227  	if (wmi_cmd_log_max_entry <=					\
228  		*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx))	\
229  		*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx) = 0;\
230  	((struct wmi_command_debug *)h->log_info.wmi_command_log_buf_info.buf)\
231  		[*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)]\
232  						.command = a;		\
233  	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.		\
234  				wmi_command_log_buf_info.buf)		\
235  		[*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)].data,\
236  			b, wmi_record_max_length);			\
237  	((struct wmi_command_debug *)h->log_info.wmi_command_log_buf_info.buf)\
238  		[*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)].\
239  		time = qdf_get_log_timestamp();			\
240  	(*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx))++;	\
241  	h->log_info.wmi_command_log_buf_info.length++;			\
242  }
243  
244  #define WMI_COMMAND_TX_CMP_RECORD(h, a, b, da, pa) {			\
245  	if (wmi_cmd_cmpl_log_max_entry <=				\
246  		*(h->log_info.wmi_command_tx_cmp_log_buf_info.p_buf_tail_idx))\
247  		*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
248  				p_buf_tail_idx) = 0;			\
249  	((struct wmi_command_cmp_debug *)h->log_info.			\
250  		wmi_command_tx_cmp_log_buf_info.buf)			\
251  		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
252  				p_buf_tail_idx)].			\
253  							command	= a;	\
254  	qdf_mem_copy(((struct wmi_command_cmp_debug *)h->log_info.	\
255  				wmi_command_tx_cmp_log_buf_info.buf)	\
256  		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
257  			p_buf_tail_idx)].				\
258  		data, b, wmi_record_max_length);			\
259  	((struct wmi_command_cmp_debug *)h->log_info.			\
260  		wmi_command_tx_cmp_log_buf_info.buf)			\
261  		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
262  				p_buf_tail_idx)].			\
263  		time = qdf_get_log_timestamp();				\
264  	((struct wmi_command_cmp_debug *)h->log_info.			\
265  		wmi_command_tx_cmp_log_buf_info.buf)			\
266  		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
267  				p_buf_tail_idx)].			\
268  		dma_addr = da;						\
269  	((struct wmi_command_cmp_debug *)h->log_info.			\
270  		wmi_command_tx_cmp_log_buf_info.buf)			\
271  		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
272  				p_buf_tail_idx)].			\
273  		phy_addr = pa;						\
274  	(*(h->log_info.wmi_command_tx_cmp_log_buf_info.p_buf_tail_idx))++;\
275  	h->log_info.wmi_command_tx_cmp_log_buf_info.length++;		\
276  }
277  
278  #define WMI_EVENT_RECORD(h, a, b) {					\
279  	if (wmi_event_log_max_entry <=					\
280  		*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx))	\
281  		*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx) = 0;\
282  	((struct wmi_event_debug *)h->log_info.wmi_event_log_buf_info.buf)\
283  		[*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].	\
284  		event = a;						\
285  	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.		\
286  				wmi_event_log_buf_info.buf)		\
287  		[*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].data, b,\
288  		wmi_record_max_length);					\
289  	((struct wmi_event_debug *)h->log_info.wmi_event_log_buf_info.buf)\
290  		[*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].time =\
291  		qdf_get_log_timestamp();				\
292  	(*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx))++;	\
293  	h->log_info.wmi_event_log_buf_info.length++;			\
294  }
295  
296  #define WMI_RX_EVENT_RECORD(h, a, b) {					\
297  	if (wmi_event_log_max_entry <=					\
298  		*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx))\
299  		*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx) = 0;\
300  	((struct wmi_event_debug *)h->log_info.wmi_rx_event_log_buf_info.buf)\
301  		[*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\
302  		event = a;						\
303  	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.		\
304  				wmi_rx_event_log_buf_info.buf)		\
305  		[*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\
306  			data, b, wmi_record_max_length);		\
307  	((struct wmi_event_debug *)h->log_info.wmi_rx_event_log_buf_info.buf)\
308  		[*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\
309  		time =	qdf_get_log_timestamp();			\
310  	(*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx))++;	\
311  	h->log_info.wmi_rx_event_log_buf_info.length++;			\
312  }
313  
314  #ifndef WMI_INTERFACE_EVENT_LOGGING_DYNAMIC_ALLOC
315  uint32_t g_wmi_mgmt_command_buf_idx = 0;
316  struct
317  wmi_command_debug wmi_mgmt_command_log_buffer[WMI_MGMT_TX_DEBUG_MAX_ENTRY];
318  
319  /* wmi_mgmt commands TX completed */
320  uint32_t g_wmi_mgmt_command_tx_cmp_buf_idx = 0;
321  struct wmi_command_debug
322  wmi_mgmt_command_tx_cmp_log_buffer[WMI_MGMT_TX_CMPL_DEBUG_MAX_ENTRY];
323  
324  /* wmi_mgmt events when received */
325  uint32_t g_wmi_mgmt_rx_event_buf_idx = 0;
326  struct wmi_event_debug
327  wmi_mgmt_rx_event_log_buffer[WMI_MGMT_RX_DEBUG_MAX_ENTRY];
328  
329  /* wmi_diag events when received */
330  uint32_t g_wmi_diag_rx_event_buf_idx = 0;
331  struct wmi_event_debug
332  wmi_diag_rx_event_log_buffer[WMI_DIAG_RX_EVENT_DEBUG_MAX_ENTRY];
333  #endif
334  
335  #define WMI_MGMT_COMMAND_RECORD(h, a, b) {                              \
336  	if (wmi_mgmt_tx_log_max_entry <=                                   \
337  		*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)) \
338  		*(h->log_info.wmi_mgmt_command_log_buf_info.		\
339  				p_buf_tail_idx) = 0;			\
340  	((struct wmi_command_debug *)h->log_info.                       \
341  		 wmi_mgmt_command_log_buf_info.buf)                     \
342  		[*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\
343  			command = a;                                    \
344  	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.          \
345  				wmi_mgmt_command_log_buf_info.buf)      \
346  		[*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\
347  		data, b,                                                \
348  		wmi_record_max_length);                                	\
349  	((struct wmi_command_debug *)h->log_info.                       \
350  		 wmi_mgmt_command_log_buf_info.buf)                     \
351  		[*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\
352  			time =        qdf_get_log_timestamp();          \
353  	(*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx))++;\
354  	h->log_info.wmi_mgmt_command_log_buf_info.length++;             \
355  }
356  
357  #define WMI_MGMT_COMMAND_TX_CMP_RECORD(h, a, b) {			\
358  	if (wmi_mgmt_tx_cmpl_log_max_entry <=				\
359  		*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
360  			p_buf_tail_idx))				\
361  		*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
362  			p_buf_tail_idx) = 0;				\
363  	((struct wmi_command_debug *)h->log_info.			\
364  			wmi_mgmt_command_tx_cmp_log_buf_info.buf)	\
365  		[*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
366  				p_buf_tail_idx)].command = a;		\
367  	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.		\
368  				wmi_mgmt_command_tx_cmp_log_buf_info.buf)\
369  		[*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
370  			p_buf_tail_idx)].data, b,			\
371  			wmi_record_max_length);				\
372  	((struct wmi_command_debug *)h->log_info.			\
373  			wmi_mgmt_command_tx_cmp_log_buf_info.buf)	\
374  		[*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
375  				p_buf_tail_idx)].time =			\
376  		qdf_get_log_timestamp();				\
377  	(*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.		\
378  			p_buf_tail_idx))++;				\
379  	h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.length++;	\
380  }
381  
382  #define WMI_MGMT_RX_EVENT_RECORD(h, a, b) do {				\
383  	if (wmi_mgmt_rx_log_max_entry <=				\
384  		*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx))\
385  		*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx) = 0;\
386  	((struct wmi_event_debug *)h->log_info.wmi_mgmt_event_log_buf_info.buf)\
387  		[*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)]\
388  					.event = a;			\
389  	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.		\
390  				wmi_mgmt_event_log_buf_info.buf)	\
391  		[*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)].\
392  			data, b, wmi_record_max_length);		\
393  	((struct wmi_event_debug *)h->log_info.wmi_mgmt_event_log_buf_info.buf)\
394  		[*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)].\
395  			time = qdf_get_log_timestamp();			\
396  	(*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx))++;	\
397  	h->log_info.wmi_mgmt_event_log_buf_info.length++;		\
398  } while (0);
399  
400  #define WMI_DIAG_RX_EVENT_RECORD(h, a, b) do {                             \
401  	if (wmi_diag_log_max_entry <=                                   \
402  		*(h->log_info.wmi_diag_event_log_buf_info.p_buf_tail_idx))\
403  		*(h->log_info.wmi_diag_event_log_buf_info.p_buf_tail_idx) = 0;\
404  	((struct wmi_event_debug *)h->log_info.wmi_diag_event_log_buf_info.buf)\
405  		[*(h->log_info.wmi_diag_event_log_buf_info.p_buf_tail_idx)]\
406  					.event = a;                     \
407  	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.            \
408  				wmi_diag_event_log_buf_info.buf)        \
409  		[*(h->log_info.wmi_diag_event_log_buf_info.p_buf_tail_idx)].\
410  			data, b, wmi_record_max_length);                \
411  	((struct wmi_event_debug *)h->log_info.wmi_diag_event_log_buf_info.buf)\
412  		[*(h->log_info.wmi_diag_event_log_buf_info.p_buf_tail_idx)].\
413  			time = qdf_get_log_timestamp();                 \
414  	(*(h->log_info.wmi_diag_event_log_buf_info.p_buf_tail_idx))++;  \
415  	h->log_info.wmi_diag_event_log_buf_info.length++;               \
416  } while (0);
417  
418  /* These are defined to made it as module param, which can be configured */
419  /* WMI Commands */
420  uint32_t wmi_cmd_log_max_entry = WMI_CMD_DEBUG_MAX_ENTRY;
421  uint32_t wmi_cmd_cmpl_log_max_entry = WMI_CMD_CMPL_DEBUG_MAX_ENTRY;
422  /* WMI Events */
423  uint32_t wmi_event_log_max_entry = WMI_EVENT_DEBUG_MAX_ENTRY;
424  /* WMI MGMT Tx */
425  uint32_t wmi_mgmt_tx_log_max_entry = WMI_MGMT_TX_DEBUG_MAX_ENTRY;
426  uint32_t wmi_mgmt_tx_cmpl_log_max_entry = WMI_MGMT_TX_CMPL_DEBUG_MAX_ENTRY;
427  /* WMI MGMT Rx */
428  uint32_t wmi_mgmt_rx_log_max_entry = WMI_MGMT_RX_DEBUG_MAX_ENTRY;
429  /* WMI Diag Event */
430  uint32_t wmi_diag_log_max_entry = WMI_DIAG_RX_EVENT_DEBUG_MAX_ENTRY;
431  /* WMI capture size */
432  uint32_t wmi_record_max_length = WMI_DEBUG_ENTRY_MAX_LENGTH;
433  uint32_t wmi_display_size = 100;
434  
435  /**
436   * wmi_log_init() - Initialize WMI event logging
437   * @wmi_handle: WMI handle.
438   *
439   * Return: Initialization status
440   */
441  #ifndef WMI_INTERFACE_EVENT_LOGGING_DYNAMIC_ALLOC
wmi_log_init(struct wmi_unified * wmi_handle)442  static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle)
443  {
444  	struct wmi_log_buf_t *cmd_log_buf =
445  			&wmi_handle->log_info.wmi_command_log_buf_info;
446  	struct wmi_log_buf_t *cmd_tx_cmpl_log_buf =
447  			&wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info;
448  
449  	struct wmi_log_buf_t *event_log_buf =
450  			&wmi_handle->log_info.wmi_event_log_buf_info;
451  	struct wmi_log_buf_t *rx_event_log_buf =
452  			&wmi_handle->log_info.wmi_rx_event_log_buf_info;
453  
454  	struct wmi_log_buf_t *mgmt_cmd_log_buf =
455  			&wmi_handle->log_info.wmi_mgmt_command_log_buf_info;
456  	struct wmi_log_buf_t *mgmt_cmd_tx_cmp_log_buf =
457  		&wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info;
458  	struct wmi_log_buf_t *mgmt_event_log_buf =
459  			&wmi_handle->log_info.wmi_mgmt_event_log_buf_info;
460  	struct wmi_log_buf_t *diag_event_log_buf =
461  			&wmi_handle->log_info.wmi_diag_event_log_buf_info;
462  
463  	/* WMI commands */
464  	cmd_log_buf->length = 0;
465  	cmd_log_buf->buf_tail_idx = 0;
466  	cmd_log_buf->buf = wmi_command_log_buffer;
467  	cmd_log_buf->p_buf_tail_idx = &g_wmi_command_buf_idx;
468  	cmd_log_buf->size = WMI_CMD_DEBUG_MAX_ENTRY;
469  
470  	/* WMI commands TX completed */
471  	cmd_tx_cmpl_log_buf->length = 0;
472  	cmd_tx_cmpl_log_buf->buf_tail_idx = 0;
473  	cmd_tx_cmpl_log_buf->buf = wmi_command_tx_cmp_log_buffer;
474  	cmd_tx_cmpl_log_buf->p_buf_tail_idx = &g_wmi_command_tx_cmp_buf_idx;
475  	cmd_tx_cmpl_log_buf->size = WMI_CMD_CMPL_DEBUG_MAX_ENTRY;
476  
477  	/* WMI events when processed */
478  	event_log_buf->length = 0;
479  	event_log_buf->buf_tail_idx = 0;
480  	event_log_buf->buf = wmi_event_log_buffer;
481  	event_log_buf->p_buf_tail_idx = &g_wmi_event_buf_idx;
482  	event_log_buf->size = WMI_EVENT_DEBUG_MAX_ENTRY;
483  
484  	/* WMI events when queued */
485  	rx_event_log_buf->length = 0;
486  	rx_event_log_buf->buf_tail_idx = 0;
487  	rx_event_log_buf->buf = wmi_rx_event_log_buffer;
488  	rx_event_log_buf->p_buf_tail_idx = &g_wmi_rx_event_buf_idx;
489  	rx_event_log_buf->size = WMI_EVENT_DEBUG_MAX_ENTRY;
490  
491  	/* WMI Management commands */
492  	mgmt_cmd_log_buf->length = 0;
493  	mgmt_cmd_log_buf->buf_tail_idx = 0;
494  	mgmt_cmd_log_buf->buf = wmi_mgmt_command_log_buffer;
495  	mgmt_cmd_log_buf->p_buf_tail_idx = &g_wmi_mgmt_command_buf_idx;
496  	mgmt_cmd_log_buf->size = WMI_MGMT_TX_DEBUG_MAX_ENTRY;
497  
498  	/* WMI Management commands Tx completed*/
499  	mgmt_cmd_tx_cmp_log_buf->length = 0;
500  	mgmt_cmd_tx_cmp_log_buf->buf_tail_idx = 0;
501  	mgmt_cmd_tx_cmp_log_buf->buf = wmi_mgmt_command_tx_cmp_log_buffer;
502  	mgmt_cmd_tx_cmp_log_buf->p_buf_tail_idx =
503  		&g_wmi_mgmt_command_tx_cmp_buf_idx;
504  	mgmt_cmd_tx_cmp_log_buf->size = WMI_MGMT_TX_CMPL_DEBUG_MAX_ENTRY;
505  
506  	/* WMI Management events when received */
507  	mgmt_event_log_buf->length = 0;
508  	mgmt_event_log_buf->buf_tail_idx = 0;
509  	mgmt_event_log_buf->buf = wmi_mgmt_rx_event_log_buffer;
510  	mgmt_event_log_buf->p_buf_tail_idx = &g_wmi_mgmt_rx_event_buf_idx;
511  	mgmt_event_log_buf->size = WMI_MGMT_RX_DEBUG_MAX_ENTRY;
512  
513  	/* WMI diag events when received */
514  	diag_event_log_buf->length = 0;
515  	diag_event_log_buf->buf_tail_idx = 0;
516  	diag_event_log_buf->buf = wmi_diag_rx_event_log_buffer;
517  	diag_event_log_buf->p_buf_tail_idx = &g_wmi_diag_rx_event_buf_idx;
518  	diag_event_log_buf->size = WMI_DIAG_RX_EVENT_DEBUG_MAX_ENTRY;
519  
520  	qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock);
521  	wmi_handle->log_info.wmi_logging_enable = 1;
522  
523  	return QDF_STATUS_SUCCESS;
524  }
525  #else
wmi_log_init(struct wmi_unified * wmi_handle)526  static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle)
527  {
528  	struct wmi_log_buf_t *cmd_log_buf =
529  			&wmi_handle->log_info.wmi_command_log_buf_info;
530  	struct wmi_log_buf_t *cmd_tx_cmpl_log_buf =
531  			&wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info;
532  
533  	struct wmi_log_buf_t *event_log_buf =
534  			&wmi_handle->log_info.wmi_event_log_buf_info;
535  	struct wmi_log_buf_t *rx_event_log_buf =
536  			&wmi_handle->log_info.wmi_rx_event_log_buf_info;
537  
538  	struct wmi_log_buf_t *mgmt_cmd_log_buf =
539  			&wmi_handle->log_info.wmi_mgmt_command_log_buf_info;
540  	struct wmi_log_buf_t *mgmt_cmd_tx_cmp_log_buf =
541  		&wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info;
542  	struct wmi_log_buf_t *mgmt_event_log_buf =
543  			&wmi_handle->log_info.wmi_mgmt_event_log_buf_info;
544  	struct wmi_log_buf_t *diag_event_log_buf =
545  			&wmi_handle->log_info.wmi_diag_event_log_buf_info;
546  
547  	wmi_handle->log_info.wmi_logging_enable = 0;
548  
549  	/* WMI commands */
550  	cmd_log_buf->length = 0;
551  	cmd_log_buf->buf_tail_idx = 0;
552  	cmd_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc(
553  		wmi_cmd_log_max_entry * sizeof(struct wmi_command_debug));
554  	cmd_log_buf->size = wmi_cmd_log_max_entry;
555  
556  	if (!cmd_log_buf->buf)
557  		return QDF_STATUS_E_NOMEM;
558  
559  	cmd_log_buf->p_buf_tail_idx = &cmd_log_buf->buf_tail_idx;
560  
561  	/* WMI commands TX completed */
562  	cmd_tx_cmpl_log_buf->length = 0;
563  	cmd_tx_cmpl_log_buf->buf_tail_idx = 0;
564  	cmd_tx_cmpl_log_buf->buf = (struct wmi_command_cmp_debug *) qdf_mem_malloc(
565  		wmi_cmd_cmpl_log_max_entry * sizeof(struct wmi_command_cmp_debug));
566  	cmd_tx_cmpl_log_buf->size = wmi_cmd_cmpl_log_max_entry;
567  
568  	if (!cmd_tx_cmpl_log_buf->buf)
569  		return QDF_STATUS_E_NOMEM;
570  
571  	cmd_tx_cmpl_log_buf->p_buf_tail_idx =
572  		&cmd_tx_cmpl_log_buf->buf_tail_idx;
573  
574  	/* WMI events when processed */
575  	event_log_buf->length = 0;
576  	event_log_buf->buf_tail_idx = 0;
577  	event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
578  		wmi_event_log_max_entry * sizeof(struct wmi_event_debug));
579  	event_log_buf->size = wmi_event_log_max_entry;
580  
581  	if (!event_log_buf->buf)
582  		return QDF_STATUS_E_NOMEM;
583  
584  	event_log_buf->p_buf_tail_idx = &event_log_buf->buf_tail_idx;
585  
586  	/* WMI events when queued */
587  	rx_event_log_buf->length = 0;
588  	rx_event_log_buf->buf_tail_idx = 0;
589  	rx_event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
590  		wmi_event_log_max_entry * sizeof(struct wmi_event_debug));
591  	rx_event_log_buf->size = wmi_event_log_max_entry;
592  
593  	if (!rx_event_log_buf->buf)
594  		return QDF_STATUS_E_NOMEM;
595  
596  	rx_event_log_buf->p_buf_tail_idx = &rx_event_log_buf->buf_tail_idx;
597  
598  	/* WMI Management commands */
599  	mgmt_cmd_log_buf->length = 0;
600  	mgmt_cmd_log_buf->buf_tail_idx = 0;
601  	mgmt_cmd_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc(
602  		wmi_mgmt_tx_log_max_entry * sizeof(struct wmi_command_debug));
603  	mgmt_cmd_log_buf->size = wmi_mgmt_tx_log_max_entry;
604  
605  	if (!mgmt_cmd_log_buf->buf)
606  		return QDF_STATUS_E_NOMEM;
607  
608  	mgmt_cmd_log_buf->p_buf_tail_idx = &mgmt_cmd_log_buf->buf_tail_idx;
609  
610  	/* WMI Management commands Tx completed*/
611  	mgmt_cmd_tx_cmp_log_buf->length = 0;
612  	mgmt_cmd_tx_cmp_log_buf->buf_tail_idx = 0;
613  	mgmt_cmd_tx_cmp_log_buf->buf = (struct wmi_command_debug *)
614  		qdf_mem_malloc(
615  		wmi_mgmt_tx_cmpl_log_max_entry *
616  		sizeof(struct wmi_command_debug));
617  	mgmt_cmd_tx_cmp_log_buf->size = wmi_mgmt_tx_cmpl_log_max_entry;
618  
619  	if (!mgmt_cmd_tx_cmp_log_buf->buf)
620  		return QDF_STATUS_E_NOMEM;
621  
622  	mgmt_cmd_tx_cmp_log_buf->p_buf_tail_idx =
623  		&mgmt_cmd_tx_cmp_log_buf->buf_tail_idx;
624  
625  	/* WMI Management events when received */
626  	mgmt_event_log_buf->length = 0;
627  	mgmt_event_log_buf->buf_tail_idx = 0;
628  
629  	mgmt_event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
630  		wmi_mgmt_rx_log_max_entry *
631  		sizeof(struct wmi_event_debug));
632  	mgmt_event_log_buf->size = wmi_mgmt_rx_log_max_entry;
633  
634  	if (!mgmt_event_log_buf->buf)
635  		return QDF_STATUS_E_NOMEM;
636  
637  	mgmt_event_log_buf->p_buf_tail_idx = &mgmt_event_log_buf->buf_tail_idx;
638  
639  	/* WMI diag events when received */
640  	diag_event_log_buf->length = 0;
641  	diag_event_log_buf->buf_tail_idx = 0;
642  
643  	diag_event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
644  		wmi_diag_log_max_entry *
645  		sizeof(struct wmi_event_debug));
646  	diag_event_log_buf->size = wmi_diag_log_max_entry;
647  
648  	if (!diag_event_log_buf->buf)
649  		return QDF_STATUS_E_NOMEM;
650  
651  	diag_event_log_buf->p_buf_tail_idx = &diag_event_log_buf->buf_tail_idx;
652  
653  	qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock);
654  	wmi_handle->log_info.wmi_logging_enable = 1;
655  
656  	wmi_filtered_logging_init(wmi_handle);
657  
658  	return QDF_STATUS_SUCCESS;
659  }
660  #endif
661  
662  /**
663   * wmi_log_buffer_free() - Free all dynamic allocated buffer memory for
664   * event logging
665   * @wmi_handle: WMI handle.
666   *
667   * Return: None
668   */
669  #ifdef WMI_INTERFACE_EVENT_LOGGING_DYNAMIC_ALLOC
wmi_log_buffer_free(struct wmi_unified * wmi_handle)670  static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle)
671  {
672  	wmi_filtered_logging_free(wmi_handle);
673  
674  	if (wmi_handle->log_info.wmi_command_log_buf_info.buf)
675  		qdf_mem_free(wmi_handle->log_info.wmi_command_log_buf_info.buf);
676  	if (wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info.buf)
677  		qdf_mem_free(
678  		wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info.buf);
679  	if (wmi_handle->log_info.wmi_event_log_buf_info.buf)
680  		qdf_mem_free(wmi_handle->log_info.wmi_event_log_buf_info.buf);
681  	if (wmi_handle->log_info.wmi_rx_event_log_buf_info.buf)
682  		qdf_mem_free(
683  			wmi_handle->log_info.wmi_rx_event_log_buf_info.buf);
684  	if (wmi_handle->log_info.wmi_mgmt_command_log_buf_info.buf)
685  		qdf_mem_free(
686  			wmi_handle->log_info.wmi_mgmt_command_log_buf_info.buf);
687  	if (wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.buf)
688  		qdf_mem_free(
689  		wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.buf);
690  	if (wmi_handle->log_info.wmi_mgmt_event_log_buf_info.buf)
691  		qdf_mem_free(
692  			wmi_handle->log_info.wmi_mgmt_event_log_buf_info.buf);
693  	if (wmi_handle->log_info.wmi_diag_event_log_buf_info.buf)
694  		qdf_mem_free(
695  			wmi_handle->log_info.wmi_diag_event_log_buf_info.buf);
696  	wmi_handle->log_info.wmi_logging_enable = 0;
697  
698  	qdf_spinlock_destroy(&wmi_handle->log_info.wmi_record_lock);
699  }
700  #else
wmi_log_buffer_free(struct wmi_unified * wmi_handle)701  static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle)
702  {
703  	/* Do Nothing */
704  }
705  #endif
706  
707  /**
708   * wmi_print_cmd_log_buffer() - an output agnostic wmi command log printer
709   * @log_buffer: the command log buffer metadata of the buffer to print
710   * @count: the maximum number of entries to print
711   * @print: an abstract print method, e.g. a qdf_print() or seq_printf() wrapper
712   * @print_priv: any data required by the print method, e.g. a file handle
713   *
714   * Return: None
715   */
716  static void
wmi_print_cmd_log_buffer(struct wmi_log_buf_t * log_buffer,uint32_t count,qdf_abstract_print * print,void * print_priv)717  wmi_print_cmd_log_buffer(struct wmi_log_buf_t *log_buffer, uint32_t count,
718  			 qdf_abstract_print *print, void *print_priv)
719  {
720  	static const int data_len =
721  		WMI_DEBUG_ENTRY_MAX_LENGTH / sizeof(uint32_t);
722  	char str[128];
723  	uint32_t idx;
724  
725  	if (count > log_buffer->size)
726  		count = log_buffer->size;
727  	if (count > log_buffer->length)
728  		count = log_buffer->length;
729  
730  	/* subtract count from index, and wrap if necessary */
731  	idx = log_buffer->size + *log_buffer->p_buf_tail_idx - count;
732  	idx %= log_buffer->size;
733  
734  	print(print_priv, "Time (seconds)      Cmd Id              Payload");
735  	while (count) {
736  		struct wmi_command_debug *cmd_log = (struct wmi_command_debug *)
737  			&((struct wmi_command_debug *)log_buffer->buf)[idx];
738  		uint64_t secs, usecs;
739  		int len = 0;
740  		int i;
741  
742  		qdf_log_timestamp_to_secs(cmd_log->time, &secs, &usecs);
743  		len += scnprintf(str + len, sizeof(str) - len,
744  				 "% 8lld.%06lld    %6u (0x%06x)    ",
745  				 secs, usecs,
746  				 cmd_log->command, cmd_log->command);
747  		for (i = 0; i < data_len; ++i) {
748  			len += scnprintf(str + len, sizeof(str) - len,
749  					 "0x%08x ", cmd_log->data[i]);
750  		}
751  
752  		print(print_priv, str);
753  
754  		--count;
755  		++idx;
756  		if (idx >= log_buffer->size)
757  			idx = 0;
758  	}
759  }
760  
761  /**
762   * wmi_dump_last_cmd_rec_info() - last wmi command tx completion time print
763   * @wmi_handle: wmi handle
764   *
765   * Return: None
766   */
767  static void
wmi_dump_last_cmd_rec_info(wmi_unified_t wmi_handle)768  wmi_dump_last_cmd_rec_info(wmi_unified_t wmi_handle) {
769  	uint32_t idx, idx_tx_cmp, cmd_tmp_log, cmd_tmp_tx_cmp;
770  	uint64_t secs, secs_tx_cmp, usecs, usecs_tx_cmp;
771  	struct wmi_command_debug *cmd_log;
772  	struct wmi_command_debug *cmd_log_tx_cmp;
773  	struct wmi_log_buf_t *log_buf =
774  		&wmi_handle->log_info.wmi_command_log_buf_info;
775  	struct wmi_log_buf_t *log_buf_tx_cmp =
776  		&wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info;
777  
778  	qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
779  
780  	(*log_buf->p_buf_tail_idx == 0) ? (idx = log_buf->size) :
781  		(idx = *log_buf->p_buf_tail_idx - 1);
782  	idx %= log_buf->size;
783  
784  	(*log_buf_tx_cmp->p_buf_tail_idx == 0) ? (idx_tx_cmp =
785  		log_buf_tx_cmp->size) : (idx_tx_cmp =
786  		*log_buf_tx_cmp->p_buf_tail_idx - 1);
787  	idx_tx_cmp %= log_buf_tx_cmp->size;
788  	cmd_log = &((struct wmi_command_debug *)log_buf->buf)[idx];
789  	cmd_log_tx_cmp = &((struct wmi_command_debug *)log_buf_tx_cmp->buf)
790  		[idx_tx_cmp];
791  	cmd_tmp_log = cmd_log->command;
792  	cmd_tmp_tx_cmp = cmd_log_tx_cmp->command;
793  	qdf_log_timestamp_to_secs(cmd_log->time, &secs, &usecs);
794  	qdf_log_timestamp_to_secs(cmd_log_tx_cmp->time, &secs_tx_cmp,
795  				  &usecs_tx_cmp);
796  
797  	qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
798  
799  	wmi_nofl_err("Last wmi command Time (s) = % 8lld.%06lld ",
800  		     secs, usecs);
801  	wmi_nofl_err("Last wmi Cmd_Id = (0x%06x) ", cmd_tmp_log);
802  	wmi_nofl_err("Last wmi command tx completion Time (s) = % 8lld.%06lld",
803  		     secs_tx_cmp, usecs_tx_cmp);
804  	wmi_nofl_err("Last wmi command tx completion Cmd_Id = (0x%06x) ",
805  		     cmd_tmp_tx_cmp);
806  }
807  
808  /**
809   * wmi_print_cmd_cmp_log_buffer() - wmi command completion log printer
810   * @log_buffer: the command completion log buffer metadata of the buffer to print
811   * @count: the maximum number of entries to print
812   * @print: an abstract print method, e.g. a qdf_print() or seq_printf() wrapper
813   * @print_priv: any data required by the print method, e.g. a file handle
814   *
815   * Return: None
816   */
817  static void
wmi_print_cmd_cmp_log_buffer(struct wmi_log_buf_t * log_buffer,uint32_t count,qdf_abstract_print * print,void * print_priv)818  wmi_print_cmd_cmp_log_buffer(struct wmi_log_buf_t *log_buffer, uint32_t count,
819  			 qdf_abstract_print *print, void *print_priv)
820  {
821  	static const int data_len =
822  		WMI_DEBUG_ENTRY_MAX_LENGTH / sizeof(uint32_t);
823  	char str[128];
824  	uint32_t idx;
825  
826  	if (count > log_buffer->size)
827  		count = log_buffer->size;
828  	if (count > log_buffer->length)
829  		count = log_buffer->length;
830  
831  	/* subtract count from index, and wrap if necessary */
832  	idx = log_buffer->size + *log_buffer->p_buf_tail_idx - count;
833  	idx %= log_buffer->size;
834  
835  	print(print_priv, "Time (seconds)      Cmd Id              Payload");
836  	while (count) {
837  		struct wmi_command_cmp_debug *cmd_log = (struct wmi_command_cmp_debug *)
838  			&((struct wmi_command_cmp_debug *)log_buffer->buf)[idx];
839  		uint64_t secs, usecs;
840  		int len = 0;
841  		int i;
842  
843  		qdf_log_timestamp_to_secs(cmd_log->time, &secs, &usecs);
844  		len += scnprintf(str + len, sizeof(str) - len,
845  				 "% 8lld.%06lld    %6u (0x%06x)    ",
846  				 secs, usecs,
847  				 cmd_log->command, cmd_log->command);
848  		for (i = 0; i < data_len; ++i) {
849  			len += scnprintf(str + len, sizeof(str) - len,
850  					 "0x%08x ", cmd_log->data[i]);
851  		}
852  
853  		print(print_priv, str);
854  
855  		--count;
856  		++idx;
857  		if (idx >= log_buffer->size)
858  			idx = 0;
859  	}
860  }
861  
862  /**
863   * wmi_print_event_log_buffer() - an output agnostic wmi event log printer
864   * @log_buffer: the event log buffer metadata of the buffer to print
865   * @count: the maximum number of entries to print
866   * @print: an abstract print method, e.g. a qdf_print() or seq_printf() wrapper
867   * @print_priv: any data required by the print method, e.g. a file handle
868   *
869   * Return: None
870   */
871  static void
wmi_print_event_log_buffer(struct wmi_log_buf_t * log_buffer,uint32_t count,qdf_abstract_print * print,void * print_priv)872  wmi_print_event_log_buffer(struct wmi_log_buf_t *log_buffer, uint32_t count,
873  			   qdf_abstract_print *print, void *print_priv)
874  {
875  	static const int data_len =
876  		WMI_DEBUG_ENTRY_MAX_LENGTH / sizeof(uint32_t);
877  	char str[128];
878  	uint32_t idx;
879  
880  	if (count > log_buffer->size)
881  		count = log_buffer->size;
882  	if (count > log_buffer->length)
883  		count = log_buffer->length;
884  
885  	/* subtract count from index, and wrap if necessary */
886  	idx = log_buffer->size + *log_buffer->p_buf_tail_idx - count;
887  	idx %= log_buffer->size;
888  
889  	print(print_priv, "Time (seconds)      Event Id             Payload");
890  	while (count) {
891  		struct wmi_event_debug *event_log = (struct wmi_event_debug *)
892  			&((struct wmi_event_debug *)log_buffer->buf)[idx];
893  		uint64_t secs, usecs;
894  		int len = 0;
895  		int i;
896  
897  		qdf_log_timestamp_to_secs(event_log->time, &secs, &usecs);
898  		len += scnprintf(str + len, sizeof(str) - len,
899  				 "% 8lld.%06lld    %6u (0x%06x)    ",
900  				 secs, usecs,
901  				 event_log->event, event_log->event);
902  		for (i = 0; i < data_len; ++i) {
903  			len += scnprintf(str + len, sizeof(str) - len,
904  					 "0x%08x ", event_log->data[i]);
905  		}
906  
907  		print(print_priv, str);
908  
909  		--count;
910  		++idx;
911  		if (idx >= log_buffer->size)
912  			idx = 0;
913  	}
914  }
915  
916  inline void
wmi_print_cmd_log(wmi_unified_t wmi,uint32_t count,qdf_abstract_print * print,void * print_priv)917  wmi_print_cmd_log(wmi_unified_t wmi, uint32_t count,
918  		  qdf_abstract_print *print, void *print_priv)
919  {
920  	wmi_print_cmd_log_buffer(
921  		&wmi->log_info.wmi_command_log_buf_info,
922  		count, print, print_priv);
923  }
924  
925  inline void
wmi_print_cmd_tx_cmp_log(wmi_unified_t wmi,uint32_t count,qdf_abstract_print * print,void * print_priv)926  wmi_print_cmd_tx_cmp_log(wmi_unified_t wmi, uint32_t count,
927  			 qdf_abstract_print *print, void *print_priv)
928  {
929  	wmi_print_cmd_cmp_log_buffer(
930  		&wmi->log_info.wmi_command_tx_cmp_log_buf_info,
931  		count, print, print_priv);
932  }
933  
934  inline void
wmi_print_mgmt_cmd_log(wmi_unified_t wmi,uint32_t count,qdf_abstract_print * print,void * print_priv)935  wmi_print_mgmt_cmd_log(wmi_unified_t wmi, uint32_t count,
936  		       qdf_abstract_print *print, void *print_priv)
937  {
938  	wmi_print_cmd_log_buffer(
939  		&wmi->log_info.wmi_mgmt_command_log_buf_info,
940  		count, print, print_priv);
941  }
942  
943  inline void
wmi_print_mgmt_cmd_tx_cmp_log(wmi_unified_t wmi,uint32_t count,qdf_abstract_print * print,void * print_priv)944  wmi_print_mgmt_cmd_tx_cmp_log(wmi_unified_t wmi, uint32_t count,
945  			      qdf_abstract_print *print, void *print_priv)
946  {
947  	wmi_print_cmd_log_buffer(
948  		&wmi->log_info.wmi_mgmt_command_tx_cmp_log_buf_info,
949  		count, print, print_priv);
950  }
951  
952  inline void
wmi_print_event_log(wmi_unified_t wmi,uint32_t count,qdf_abstract_print * print,void * print_priv)953  wmi_print_event_log(wmi_unified_t wmi, uint32_t count,
954  		    qdf_abstract_print *print, void *print_priv)
955  {
956  	wmi_print_event_log_buffer(
957  		&wmi->log_info.wmi_event_log_buf_info,
958  		count, print, print_priv);
959  }
960  
961  inline void
wmi_print_rx_event_log(wmi_unified_t wmi,uint32_t count,qdf_abstract_print * print,void * print_priv)962  wmi_print_rx_event_log(wmi_unified_t wmi, uint32_t count,
963  		       qdf_abstract_print *print, void *print_priv)
964  {
965  	wmi_print_event_log_buffer(
966  		&wmi->log_info.wmi_rx_event_log_buf_info,
967  		count, print, print_priv);
968  }
969  
970  inline void
wmi_print_mgmt_event_log(wmi_unified_t wmi,uint32_t count,qdf_abstract_print * print,void * print_priv)971  wmi_print_mgmt_event_log(wmi_unified_t wmi, uint32_t count,
972  			 qdf_abstract_print *print, void *print_priv)
973  {
974  	wmi_print_event_log_buffer(
975  		&wmi->log_info.wmi_mgmt_event_log_buf_info,
976  		count, print, print_priv);
977  }
978  
979  
980  /* debugfs routines*/
981  
982  /*
983   * debug_wmi_##func_base##_show() - debugfs functions to display content of
984   * command and event buffers. Macro uses max buffer length to display
985   * buffer when it is wraparound.
986   *
987   * @m: debugfs handler to access wmi_handle
988   * @v: Variable arguments (not used)
989   *
990   * Return: Length of characters printed
991   */
992  #define GENERATE_COMMAND_DEBUG_SHOW_FUNCS(func_base, wmi_ring_size, wmi_record_type)\
993  	static int debug_wmi_##func_base##_show(struct seq_file *m,	\
994  						void *v)		\
995  	{								\
996  		wmi_unified_t wmi_handle = (wmi_unified_t) m->private;	\
997  		struct wmi_log_buf_t *wmi_log =				\
998  			&wmi_handle->log_info.wmi_##func_base##_buf_info;\
999  		int pos, nread, outlen;					\
1000  		int i;							\
1001  		uint64_t secs, usecs;					\
1002  									\
1003  		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);\
1004  		if (!wmi_log->length) {					\
1005  			qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);\
1006  			return wmi_bp_seq_printf(m,			\
1007  			"no elements to read from ring buffer!\n");	\
1008  		}							\
1009  									\
1010  		if (wmi_log->length <= wmi_ring_size)			\
1011  			nread = wmi_log->length;			\
1012  		else							\
1013  			nread = wmi_ring_size;				\
1014  									\
1015  		if (*(wmi_log->p_buf_tail_idx) == 0)			\
1016  			/* tail can be 0 after wrap-around */		\
1017  			pos = wmi_ring_size - 1;			\
1018  		else							\
1019  			pos = *(wmi_log->p_buf_tail_idx) - 1;		\
1020  									\
1021  		outlen = wmi_bp_seq_printf(m, "Length = %d\n", wmi_log->length);\
1022  		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);\
1023  		while (nread--) {					\
1024  			struct wmi_record_type *wmi_record;		\
1025  									\
1026  			wmi_record = (struct wmi_record_type *)	\
1027  			&(((struct wmi_record_type *)wmi_log->buf)[pos]);\
1028  			outlen += wmi_bp_seq_printf(m, "CMD ID = %x\n",	\
1029  				(wmi_record->command));			\
1030  			qdf_log_timestamp_to_secs(wmi_record->time, &secs,\
1031  				&usecs);				\
1032  			outlen +=					\
1033  			wmi_bp_seq_printf(m, "CMD TIME = [%llu.%06llu]\n",\
1034  				secs, usecs);				\
1035  			outlen += wmi_bp_seq_printf(m, "CMD = ");	\
1036  			for (i = 0; i < (wmi_record_max_length/		\
1037  					sizeof(uint32_t)); i++)		\
1038  				outlen += wmi_bp_seq_printf(m, "%x ",	\
1039  					wmi_record->data[i]);		\
1040  			outlen += wmi_bp_seq_printf(m, "\n");		\
1041  									\
1042  			if (pos == 0)					\
1043  				pos = wmi_ring_size - 1;		\
1044  			else						\
1045  				pos--;					\
1046  		}							\
1047  		return outlen;						\
1048  	}								\
1049  
1050  #define GENERATE_EVENT_DEBUG_SHOW_FUNCS(func_base, wmi_ring_size)	\
1051  	static int debug_wmi_##func_base##_show(struct seq_file *m,	\
1052  						void *v)		\
1053  	{								\
1054  		wmi_unified_t wmi_handle = (wmi_unified_t) m->private;	\
1055  		struct wmi_log_buf_t *wmi_log =				\
1056  			&wmi_handle->log_info.wmi_##func_base##_buf_info;\
1057  		int pos, nread, outlen;					\
1058  		int i;							\
1059  		uint64_t secs, usecs;					\
1060  									\
1061  		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);\
1062  		if (!wmi_log->length) {					\
1063  			qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);\
1064  			return wmi_bp_seq_printf(m,			\
1065  			"no elements to read from ring buffer!\n");	\
1066  		}							\
1067  									\
1068  		if (wmi_log->length <= wmi_ring_size)			\
1069  			nread = wmi_log->length;			\
1070  		else							\
1071  			nread = wmi_ring_size;				\
1072  									\
1073  		if (*(wmi_log->p_buf_tail_idx) == 0)			\
1074  			/* tail can be 0 after wrap-around */		\
1075  			pos = wmi_ring_size - 1;			\
1076  		else							\
1077  			pos = *(wmi_log->p_buf_tail_idx) - 1;		\
1078  									\
1079  		outlen = wmi_bp_seq_printf(m, "Length = %d\n", wmi_log->length);\
1080  		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);\
1081  		while (nread--) {					\
1082  			struct wmi_event_debug *wmi_record;		\
1083  									\
1084  			wmi_record = (struct wmi_event_debug *)		\
1085  			&(((struct wmi_event_debug *)wmi_log->buf)[pos]);\
1086  			qdf_log_timestamp_to_secs(wmi_record->time, &secs,\
1087  				&usecs);				\
1088  			outlen += wmi_bp_seq_printf(m, "Event ID = %x\n",\
1089  				(wmi_record->event));			\
1090  			outlen +=					\
1091  			wmi_bp_seq_printf(m, "Event TIME = [%llu.%06llu]\n",\
1092  				secs, usecs);				\
1093  			outlen += wmi_bp_seq_printf(m, "CMD = ");	\
1094  			for (i = 0; i < (wmi_record_max_length/		\
1095  					sizeof(uint32_t)); i++)		\
1096  				outlen += wmi_bp_seq_printf(m, "%x ",	\
1097  					wmi_record->data[i]);		\
1098  			outlen += wmi_bp_seq_printf(m, "\n");		\
1099  									\
1100  			if (pos == 0)					\
1101  				pos = wmi_ring_size - 1;		\
1102  			else						\
1103  				pos--;					\
1104  		}							\
1105  		return outlen;						\
1106  	}
1107  
1108  GENERATE_COMMAND_DEBUG_SHOW_FUNCS(command_log, wmi_display_size,
1109  				  wmi_command_debug);
1110  GENERATE_COMMAND_DEBUG_SHOW_FUNCS(command_tx_cmp_log, wmi_display_size,
1111  				  wmi_command_cmp_debug);
1112  GENERATE_EVENT_DEBUG_SHOW_FUNCS(event_log, wmi_display_size);
1113  GENERATE_EVENT_DEBUG_SHOW_FUNCS(rx_event_log, wmi_display_size);
1114  GENERATE_COMMAND_DEBUG_SHOW_FUNCS(mgmt_command_log, wmi_display_size,
1115  				  wmi_command_debug);
1116  GENERATE_COMMAND_DEBUG_SHOW_FUNCS(mgmt_command_tx_cmp_log,
1117  					wmi_display_size,
1118  					wmi_command_debug);
1119  GENERATE_EVENT_DEBUG_SHOW_FUNCS(mgmt_event_log, wmi_display_size);
1120  
1121  /**
1122   * debug_wmi_enable_show() - debugfs functions to display enable state of
1123   * wmi logging feature.
1124   *
1125   * @m: debugfs handler to access wmi_handle
1126   * @v: Variable arguments (not used)
1127   *
1128   * Return: always 1
1129   */
debug_wmi_enable_show(struct seq_file * m,void * v)1130  static int debug_wmi_enable_show(struct seq_file *m, void *v)
1131  {
1132  	wmi_unified_t wmi_handle = (wmi_unified_t) m->private;
1133  
1134  	return wmi_bp_seq_printf(m, "%d\n",
1135  			wmi_handle->log_info.wmi_logging_enable);
1136  }
1137  
1138  /**
1139   * debug_wmi_log_size_show() - debugfs functions to display configured size of
1140   * wmi logging command/event buffer and management command/event buffer.
1141   *
1142   * @m: debugfs handler to access wmi_handle
1143   * @v: Variable arguments (not used)
1144   *
1145   * Return: Length of characters printed
1146   */
debug_wmi_log_size_show(struct seq_file * m,void * v)1147  static int debug_wmi_log_size_show(struct seq_file *m, void *v)
1148  {
1149  
1150  	wmi_bp_seq_printf(m, "WMI command/cmpl log max size:%d/%d\n",
1151  			  wmi_cmd_log_max_entry, wmi_cmd_cmpl_log_max_entry);
1152  	wmi_bp_seq_printf(m, "WMI management Tx/cmpl log max size:%d/%d\n",
1153  			  wmi_mgmt_tx_log_max_entry,
1154  			  wmi_mgmt_tx_cmpl_log_max_entry);
1155  	wmi_bp_seq_printf(m, "WMI event log max size:%d\n",
1156  			  wmi_event_log_max_entry);
1157  	wmi_bp_seq_printf(m, "WMI management Rx log max size:%d\n",
1158  			  wmi_mgmt_rx_log_max_entry);
1159  	return wmi_bp_seq_printf(m,
1160  				 "WMI diag log max size:%d\n",
1161  				 wmi_diag_log_max_entry);
1162  }
1163  
1164  /*
1165   * debug_wmi_##func_base##_write() - debugfs functions to clear
1166   * wmi logging command/event buffer and management command/event buffer.
1167   *
1168   * @file: file handler to access wmi_handle
1169   * @buf: received data buffer
1170   * @count: length of received buffer
1171   * @ppos: Not used
1172   *
1173   * Return: count
1174   */
1175  #define GENERATE_DEBUG_WRITE_FUNCS(func_base, wmi_ring_size, wmi_record_type)\
1176  	static ssize_t debug_wmi_##func_base##_write(struct file *file,	\
1177  				const char __user *buf,			\
1178  				size_t count, loff_t *ppos)		\
1179  	{								\
1180  		int k, ret;						\
1181  		wmi_unified_t wmi_handle =				\
1182  			((struct seq_file *)file->private_data)->private;\
1183  		struct wmi_log_buf_t *wmi_log = &wmi_handle->log_info.	\
1184  				wmi_##func_base##_buf_info;		\
1185  		char locbuf[50] = {0x00};				\
1186  									\
1187  		if ((!buf) || (count > 50))				\
1188  			return -EFAULT;					\
1189  									\
1190  		if (copy_from_user(locbuf, buf, count))			\
1191  			return -EFAULT;					\
1192  									\
1193  		ret = sscanf(locbuf, "%d", &k);				\
1194  		if ((ret != 1) || (k != 0)) {                           \
1195  			wmi_err("Wrong input, echo 0 to clear the wmi buffer");\
1196  			return -EINVAL;					\
1197  		}							\
1198  									\
1199  		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);\
1200  		qdf_mem_zero(wmi_log->buf, wmi_ring_size *		\
1201  				sizeof(struct wmi_record_type));	\
1202  		wmi_log->length = 0;					\
1203  		*(wmi_log->p_buf_tail_idx) = 0;				\
1204  		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);\
1205  									\
1206  		return count;						\
1207  	}
1208  
1209  GENERATE_DEBUG_WRITE_FUNCS(command_log, wmi_cmd_log_max_entry,
1210  			   wmi_command_debug);
1211  GENERATE_DEBUG_WRITE_FUNCS(command_tx_cmp_log, wmi_cmd_cmpl_log_max_entry,
1212  			   wmi_command_cmp_debug);
1213  GENERATE_DEBUG_WRITE_FUNCS(event_log, wmi_event_log_max_entry,
1214  			   wmi_event_debug);
1215  GENERATE_DEBUG_WRITE_FUNCS(rx_event_log, wmi_event_log_max_entry,
1216  			   wmi_event_debug);
1217  GENERATE_DEBUG_WRITE_FUNCS(mgmt_command_log, wmi_mgmt_tx_log_max_entry,
1218  			   wmi_command_debug);
1219  GENERATE_DEBUG_WRITE_FUNCS(mgmt_command_tx_cmp_log,
1220  			   wmi_mgmt_tx_cmpl_log_max_entry, wmi_command_debug);
1221  GENERATE_DEBUG_WRITE_FUNCS(mgmt_event_log, wmi_mgmt_rx_log_max_entry,
1222  			   wmi_event_debug);
1223  
1224  /**
1225   * debug_wmi_enable_write() - debugfs functions to enable/disable
1226   * wmi logging feature.
1227   *
1228   * @file: file handler to access wmi_handle
1229   * @buf: received data buffer
1230   * @count: length of received buffer
1231   * @ppos: Not used
1232   *
1233   * Return: count
1234   */
debug_wmi_enable_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)1235  static ssize_t debug_wmi_enable_write(struct file *file, const char __user *buf,
1236  					size_t count, loff_t *ppos)
1237  {
1238  	wmi_unified_t wmi_handle =
1239  		((struct seq_file *)file->private_data)->private;
1240  	int k, ret;
1241  	char locbuf[50] = {0x00};
1242  
1243  	if ((!buf) || (count > 50))
1244  		return -EFAULT;
1245  
1246  	if (copy_from_user(locbuf, buf, count))
1247  		return -EFAULT;
1248  
1249  	ret = sscanf(locbuf, "%d", &k);
1250  	if ((ret != 1) || ((k != 0) && (k != 1)))
1251  		return -EINVAL;
1252  
1253  	wmi_handle->log_info.wmi_logging_enable = k;
1254  	return count;
1255  }
1256  
1257  /**
1258   * debug_wmi_log_size_write() - reserved.
1259   *
1260   * @file: file handler to access wmi_handle
1261   * @buf: received data buffer
1262   * @count: length of received buffer
1263   * @ppos: Not used
1264   *
1265   * Return: count
1266   */
debug_wmi_log_size_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)1267  static ssize_t debug_wmi_log_size_write(struct file *file,
1268  		const char __user *buf, size_t count, loff_t *ppos)
1269  {
1270  	return -EINVAL;
1271  }
1272  
1273  /* Structure to maintain debug information */
1274  struct wmi_debugfs_info {
1275  	const char *name;
1276  	const struct file_operations *ops;
1277  };
1278  
1279  #define DEBUG_FOO(func_base) { .name = #func_base,			\
1280  	.ops = &debug_##func_base##_ops }
1281  
1282  /*
1283   * debug_##func_base##_open() - Open debugfs entry for respective command
1284   * and event buffer.
1285   *
1286   * @inode: node for debug dir entry
1287   * @file: file handler
1288   *
1289   * Return: open status
1290   */
1291  #define GENERATE_DEBUG_STRUCTS(func_base)				\
1292  	static int debug_##func_base##_open(struct inode *inode,	\
1293  						struct file *file)	\
1294  	{								\
1295  		return single_open(file, debug_##func_base##_show,	\
1296  				inode->i_private);			\
1297  	}								\
1298  									\
1299  									\
1300  	static struct file_operations debug_##func_base##_ops = {	\
1301  		.open		= debug_##func_base##_open,		\
1302  		.read		= seq_read,				\
1303  		.llseek		= seq_lseek,				\
1304  		.write		= debug_##func_base##_write,		\
1305  		.release	= single_release,			\
1306  	};
1307  
1308  GENERATE_DEBUG_STRUCTS(wmi_command_log);
1309  GENERATE_DEBUG_STRUCTS(wmi_command_tx_cmp_log);
1310  GENERATE_DEBUG_STRUCTS(wmi_event_log);
1311  GENERATE_DEBUG_STRUCTS(wmi_rx_event_log);
1312  GENERATE_DEBUG_STRUCTS(wmi_mgmt_command_log);
1313  GENERATE_DEBUG_STRUCTS(wmi_mgmt_command_tx_cmp_log);
1314  GENERATE_DEBUG_STRUCTS(wmi_mgmt_event_log);
1315  GENERATE_DEBUG_STRUCTS(wmi_enable);
1316  GENERATE_DEBUG_STRUCTS(wmi_log_size);
1317  #ifdef WMI_INTERFACE_FILTERED_EVENT_LOGGING
1318  GENERATE_DEBUG_STRUCTS(filtered_wmi_cmds);
1319  GENERATE_DEBUG_STRUCTS(filtered_wmi_evts);
1320  GENERATE_DEBUG_STRUCTS(wmi_filtered_command_log);
1321  GENERATE_DEBUG_STRUCTS(wmi_filtered_event_log);
1322  #endif
1323  
1324  struct wmi_debugfs_info wmi_debugfs_infos[NUM_DEBUG_INFOS] = {
1325  	DEBUG_FOO(wmi_command_log),
1326  	DEBUG_FOO(wmi_command_tx_cmp_log),
1327  	DEBUG_FOO(wmi_event_log),
1328  	DEBUG_FOO(wmi_rx_event_log),
1329  	DEBUG_FOO(wmi_mgmt_command_log),
1330  	DEBUG_FOO(wmi_mgmt_command_tx_cmp_log),
1331  	DEBUG_FOO(wmi_mgmt_event_log),
1332  	DEBUG_FOO(wmi_enable),
1333  	DEBUG_FOO(wmi_log_size),
1334  #ifdef WMI_INTERFACE_FILTERED_EVENT_LOGGING
1335  	DEBUG_FOO(filtered_wmi_cmds),
1336  	DEBUG_FOO(filtered_wmi_evts),
1337  	DEBUG_FOO(wmi_filtered_command_log),
1338  	DEBUG_FOO(wmi_filtered_event_log),
1339  #endif
1340  };
1341  
1342  /**
1343   * wmi_debugfs_create() - Create debug_fs entry for wmi logging.
1344   *
1345   * @wmi_handle: wmi handle
1346   * @par_entry: debug directory entry
1347   *
1348   * Return: none
1349   */
wmi_debugfs_create(wmi_unified_t wmi_handle,struct dentry * par_entry)1350  static void wmi_debugfs_create(wmi_unified_t wmi_handle,
1351  			       struct dentry *par_entry)
1352  {
1353  	int i;
1354  
1355  	if (!par_entry)
1356  		goto out;
1357  
1358  	for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
1359  		wmi_handle->debugfs_de[i] = qdf_debugfs_create_entry(
1360  						wmi_debugfs_infos[i].name,
1361  						WMI_INFOS_DBG_FILE_PERM,
1362  						par_entry,
1363  						wmi_handle,
1364  						wmi_debugfs_infos[i].ops);
1365  
1366  		if (!wmi_handle->debugfs_de[i]) {
1367  			wmi_err("debug Entry creation failed!");
1368  			goto out;
1369  		}
1370  	}
1371  
1372  	return;
1373  
1374  out:
1375  	wmi_err("debug Entry creation failed!");
1376  	wmi_log_buffer_free(wmi_handle);
1377  	return;
1378  }
1379  
1380  /**
1381   * wmi_debugfs_remove() - Remove debugfs entry for wmi logging.
1382   * @wmi_handle: wmi handle
1383   *
1384   * Return: none
1385   */
wmi_debugfs_remove(wmi_unified_t wmi_handle)1386  static void wmi_debugfs_remove(wmi_unified_t wmi_handle)
1387  {
1388  	int i;
1389  	struct dentry *dentry = wmi_handle->log_info.wmi_log_debugfs_dir;
1390  
1391  	if (dentry) {
1392  		for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
1393  			if (wmi_handle->debugfs_de[i])
1394  				wmi_handle->debugfs_de[i] = NULL;
1395  		}
1396  	}
1397  
1398  	if (dentry)
1399  		qdf_debugfs_remove_dir_recursive(dentry);
1400  }
1401  
1402  /**
1403   * wmi_debugfs_init() - debugfs functions to create debugfs directory and to
1404   *                      create debugfs entries.
1405   * @wmi_handle: wmi handler
1406   * @pdev_idx: pdev id
1407   *
1408   * Return: init status
1409   */
wmi_debugfs_init(wmi_unified_t wmi_handle,uint32_t pdev_idx)1410  static QDF_STATUS wmi_debugfs_init(wmi_unified_t wmi_handle, uint32_t pdev_idx)
1411  {
1412  	char buf[32];
1413  
1414  	snprintf(buf, sizeof(buf), "WMI_SOC%u_PDEV%u",
1415  		 wmi_handle->soc->soc_idx, pdev_idx);
1416  
1417  	wmi_handle->log_info.wmi_log_debugfs_dir =
1418  		qdf_debugfs_create_dir(buf, NULL);
1419  
1420  	if (!wmi_handle->log_info.wmi_log_debugfs_dir) {
1421  		wmi_err("error while creating debugfs dir for %s", buf);
1422  		return QDF_STATUS_E_FAILURE;
1423  	}
1424  	wmi_debugfs_create(wmi_handle,
1425  			   wmi_handle->log_info.wmi_log_debugfs_dir);
1426  
1427  	return QDF_STATUS_SUCCESS;
1428  }
1429  
wmi_mgmt_cmd_record(wmi_unified_t wmi_handle,uint32_t cmd,void * header,uint32_t vdev_id,uint32_t chanfreq)1430  void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
1431  			void *header, uint32_t vdev_id, uint32_t chanfreq)
1432  {
1433  
1434  	uint32_t data[CUSTOM_MGMT_CMD_DATA_SIZE];
1435  
1436  	data[0] = ((struct wmi_command_header *)header)->type;
1437  	data[1] = ((struct wmi_command_header *)header)->sub_type;
1438  	data[2] = vdev_id;
1439  	data[3] = chanfreq;
1440  
1441  	qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
1442  
1443  	WMI_MGMT_COMMAND_RECORD(wmi_handle, cmd, (uint8_t *)data);
1444  	wmi_specific_cmd_record(wmi_handle, cmd, (uint8_t *)data);
1445  	qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
1446  }
1447  #else
wmi_debugfs_remove(wmi_unified_t wmi_handle)1448  static void wmi_debugfs_remove(wmi_unified_t wmi_handle) { }
wmi_mgmt_cmd_record(wmi_unified_t wmi_handle,uint32_t cmd,void * header,uint32_t vdev_id,uint32_t chanfreq)1449  void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
1450  			void *header, uint32_t vdev_id, uint32_t chanfreq) { }
wmi_log_buffer_free(struct wmi_unified * wmi_handle)1451  static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle) { }
wmi_minidump_detach(struct wmi_unified * wmi_handle)1452  static void wmi_minidump_detach(struct wmi_unified *wmi_handle) { }
wmi_minidump_attach(struct wmi_unified * wmi_handle)1453  static void wmi_minidump_attach(struct wmi_unified *wmi_handle) { }
wmi_dump_last_cmd_rec_info(wmi_unified_t wmi_handle)1454  static void wmi_dump_last_cmd_rec_info(wmi_unified_t wmi_handle) { }
1455  #endif /*WMI_INTERFACE_EVENT_LOGGING */
1456  qdf_export_symbol(wmi_mgmt_cmd_record);
1457  
1458  #ifdef WMI_EXT_DBG
1459  
1460  /**
1461   * wmi_ext_dbg_msg_enqueue() - enqueue wmi message
1462   * @wmi_handle: wmi handler
1463   * @msg: WMI message
1464   *
1465   * Return: size of wmi message queue after enqueue
1466   */
wmi_ext_dbg_msg_enqueue(struct wmi_unified * wmi_handle,struct wmi_ext_dbg_msg * msg)1467  static uint32_t wmi_ext_dbg_msg_enqueue(struct wmi_unified *wmi_handle,
1468  					struct wmi_ext_dbg_msg *msg)
1469  {
1470  	uint32_t list_size;
1471  
1472  	qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
1473  	qdf_list_insert_back_size(&wmi_handle->wmi_ext_dbg_msg_queue,
1474  				  &msg->node, &list_size);
1475  	qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
1476  
1477  	return list_size;
1478  }
1479  
1480  /**
1481   * wmi_ext_dbg_msg_dequeue() - dequeue wmi message
1482   * @wmi_handle: wmi handler
1483   *
1484   * Return: wmi msg on success else NULL
1485   */
wmi_ext_dbg_msg_dequeue(struct wmi_unified * wmi_handle)1486  static struct wmi_ext_dbg_msg *wmi_ext_dbg_msg_dequeue(struct wmi_unified
1487  						       *wmi_handle)
1488  {
1489  	qdf_list_node_t *list_node = NULL;
1490  
1491  	qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
1492  	qdf_list_remove_front(&wmi_handle->wmi_ext_dbg_msg_queue, &list_node);
1493  	qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
1494  
1495  	if (!list_node)
1496  		return NULL;
1497  
1498  	return qdf_container_of(list_node, struct wmi_ext_dbg_msg, node);
1499  }
1500  
1501  /**
1502   * wmi_ext_dbg_msg_record() - record wmi messages
1503   * @wmi_handle: wmi handler
1504   * @buf: wmi message buffer
1505   * @len: wmi message length
1506   * @type: wmi message type
1507   *
1508   * Return: QDF_STATUS_SUCCESS on successful recording else failure.
1509   */
wmi_ext_dbg_msg_record(struct wmi_unified * wmi_handle,uint8_t * buf,uint32_t len,enum WMI_MSG_TYPE type)1510  static QDF_STATUS wmi_ext_dbg_msg_record(struct wmi_unified *wmi_handle,
1511  					 uint8_t *buf, uint32_t len,
1512  					 enum WMI_MSG_TYPE type)
1513  {
1514  	struct wmi_ext_dbg_msg *msg;
1515  	uint32_t list_size;
1516  
1517  	msg = wmi_ext_dbg_msg_get(len);
1518  	if (!msg)
1519  		return QDF_STATUS_E_NOMEM;
1520  
1521  	msg->len = len;
1522  	msg->type = type;
1523  	qdf_mem_copy(msg->buf, buf, len);
1524  	msg->ts = qdf_get_log_timestamp();
1525  	list_size = wmi_ext_dbg_msg_enqueue(wmi_handle, msg);
1526  
1527  	if (list_size >= wmi_handle->wmi_ext_dbg_msg_queue_size) {
1528  		msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
1529  		wmi_ext_dbg_msg_put(msg);
1530  	}
1531  
1532  	return QDF_STATUS_SUCCESS;
1533  }
1534  
1535  /**
1536   * wmi_ext_dbg_msg_cmd_record() - record wmi command messages
1537   * @wmi_handle: wmi handler
1538   * @buf: wmi command buffer
1539   * @len: wmi command message length
1540   *
1541   * Return: QDF_STATUS_SUCCESS on successful recording else failure.
1542   */
wmi_ext_dbg_msg_cmd_record(struct wmi_unified * wmi_handle,uint8_t * buf,uint32_t len)1543  static QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified *wmi_handle,
1544  					     uint8_t *buf, uint32_t len)
1545  {
1546  	return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
1547  				      WMI_MSG_TYPE_CMD);
1548  }
1549  
1550  /**
1551   * wmi_ext_dbg_msg_event_record() - record wmi event messages
1552   * @wmi_handle: wmi handler
1553   * @buf: wmi event buffer
1554   * @len: wmi event message length
1555   *
1556   * Return: QDF_STATUS_SUCCESS on successful recording else failure.
1557   */
wmi_ext_dbg_msg_event_record(struct wmi_unified * wmi_handle,uint8_t * buf,uint32_t len)1558  static QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified *wmi_handle,
1559  					       uint8_t *buf, uint32_t len)
1560  {
1561  	uint32_t id;
1562  
1563  	id = WMI_GET_FIELD(buf, WMI_CMD_HDR, COMMANDID);
1564  	if (id != wmi_handle->wmi_events[wmi_diag_event_id])
1565  		return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
1566  					      WMI_MSG_TYPE_EVENT);
1567  
1568  	return QDF_STATUS_SUCCESS;
1569  }
1570  
1571  /**
1572   * wmi_ext_dbg_msg_queue_init() - create debugfs queue and associated lock
1573   * @wmi_handle: wmi handler
1574   *
1575   * Return: none
1576   */
wmi_ext_dbg_msg_queue_init(struct wmi_unified * wmi_handle)1577  static void wmi_ext_dbg_msg_queue_init(struct wmi_unified *wmi_handle)
1578  {
1579  	qdf_list_create(&wmi_handle->wmi_ext_dbg_msg_queue,
1580  			wmi_handle->wmi_ext_dbg_msg_queue_size);
1581  	qdf_spinlock_create(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
1582  }
1583  
1584  /**
1585   * wmi_ext_dbg_msg_queue_deinit() - destroy debugfs queue and associated lock
1586   * @wmi_handle: wmi handler
1587   *
1588   * Return: none
1589   */
wmi_ext_dbg_msg_queue_deinit(struct wmi_unified * wmi_handle)1590  static void wmi_ext_dbg_msg_queue_deinit(struct wmi_unified *wmi_handle)
1591  {
1592  	qdf_list_destroy(&wmi_handle->wmi_ext_dbg_msg_queue);
1593  	qdf_spinlock_destroy(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
1594  }
1595  
1596  /**
1597   * wmi_ext_dbg_msg_show() - debugfs function to display whole content of
1598   * wmi command/event messages including headers.
1599   * @file: qdf debugfs file handler
1600   * @arg: pointer to wmi handler
1601   *
1602   * Return: QDF_STATUS_SUCCESS if all the messages are shown successfully,
1603   * else QDF_STATUS_E_AGAIN if more data to show.
1604   */
wmi_ext_dbg_msg_show(qdf_debugfs_file_t file,void * arg)1605  static QDF_STATUS wmi_ext_dbg_msg_show(qdf_debugfs_file_t file, void *arg)
1606  {
1607  	struct wmi_unified *wmi_handle = (struct wmi_unified *)arg;
1608  	struct wmi_ext_dbg_msg *msg;
1609  	uint64_t secs, usecs;
1610  
1611  	msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
1612  	if (!msg)
1613  		return QDF_STATUS_SUCCESS;
1614  
1615  	qdf_debugfs_printf(file, "%s: 0x%x\n",
1616  			   msg->type == WMI_MSG_TYPE_CMD ? "COMMAND" :
1617  			   "EVENT", WMI_GET_FIELD(msg->buf, WMI_CMD_HDR,
1618  						  COMMANDID));
1619  	qdf_log_timestamp_to_secs(msg->ts, &secs, &usecs);
1620  	qdf_debugfs_printf(file, "Time: %llu.%llu\n", secs, usecs);
1621  	qdf_debugfs_printf(file, "Length:%d\n", msg->len);
1622  	qdf_debugfs_hexdump(file, msg->buf, msg->len,
1623  			    WMI_EXT_DBG_DUMP_ROW_SIZE,
1624  			    WMI_EXT_DBG_DUMP_GROUP_SIZE);
1625  	qdf_debugfs_printf(file, "\n");
1626  
1627  	if (qdf_debugfs_overflow(file)) {
1628  		qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
1629  		qdf_list_insert_front(&wmi_handle->wmi_ext_dbg_msg_queue,
1630  				      &msg->node);
1631  		qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
1632  
1633  	} else {
1634  		wmi_ext_dbg_msg_put(msg);
1635  	}
1636  
1637  	return QDF_STATUS_E_AGAIN;
1638  }
1639  
1640  /**
1641   * wmi_ext_dbg_msg_write() - debugfs write not supported
1642   * @priv: private data
1643   * @buf: received data buffer
1644   * @len: length of received buffer
1645   *
1646   * Return: QDF_STATUS_E_NOSUPPORT.
1647   */
wmi_ext_dbg_msg_write(void * priv,const char * buf,qdf_size_t len)1648  static QDF_STATUS wmi_ext_dbg_msg_write(void *priv, const char *buf,
1649  					qdf_size_t len)
1650  {
1651  	return QDF_STATUS_E_NOSUPPORT;
1652  }
1653  
1654  static struct qdf_debugfs_fops wmi_ext_dbgfs_ops[WMI_MAX_RADIOS];
1655  
1656  /**
1657   * wmi_ext_dbgfs_init() - init debugfs items for extended wmi dump.
1658   * @wmi_handle: wmi handler
1659   * @pdev_idx: pdev index
1660   *
1661   * Return: QDF_STATUS_SUCCESS if debugfs is initialized else
1662   * QDF_STATUS_E_FAILURE
1663   */
wmi_ext_dbgfs_init(struct wmi_unified * wmi_handle,uint32_t pdev_idx)1664  static QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle,
1665  				     uint32_t pdev_idx)
1666  {
1667  	qdf_dentry_t dentry;
1668  	char buf[32];
1669  
1670  	/* To maintain backward compatibility, naming convention for PDEV 0
1671  	 * dentry is kept same as before. For more than 1 PDEV, dentry
1672  	 * names will be appended with PDEVx.
1673  	*/
1674  	if (wmi_handle->soc->soc_idx == 0 && pdev_idx == 0) {
1675  		dentry  = qdf_debugfs_create_dir(WMI_EXT_DBG_DIR, NULL);
1676  	} else {
1677  		snprintf(buf, sizeof(buf), "WMI_EXT_DBG_SOC%u_PDEV%u",
1678  			 wmi_handle->soc->soc_idx, pdev_idx);
1679  		dentry  = qdf_debugfs_create_dir(buf, NULL);
1680  	}
1681  
1682  	if (!dentry) {
1683  		wmi_err("error while creating extended wmi debugfs dir");
1684  		return QDF_STATUS_E_FAILURE;
1685  	}
1686  
1687  	wmi_ext_dbgfs_ops[pdev_idx].show = wmi_ext_dbg_msg_show;
1688  	wmi_ext_dbgfs_ops[pdev_idx].write = wmi_ext_dbg_msg_write;
1689  	wmi_ext_dbgfs_ops[pdev_idx].priv = wmi_handle;
1690  	if (!qdf_debugfs_create_file(WMI_EXT_DBG_FILE, WMI_EXT_DBG_FILE_PERM,
1691  				     dentry, &wmi_ext_dbgfs_ops[pdev_idx])) {
1692  		qdf_debugfs_remove_dir(dentry);
1693  		wmi_err("Error while creating extended wmi debugfs file");
1694  		return QDF_STATUS_E_FAILURE;
1695  	}
1696  
1697  	wmi_handle->wmi_ext_dbg_dentry = dentry;
1698  	wmi_handle->wmi_ext_dbg_msg_queue_size = WMI_EXT_DBG_QUEUE_SIZE;
1699  	wmi_ext_dbg_msg_queue_init(wmi_handle);
1700  
1701  	return QDF_STATUS_SUCCESS;
1702  }
1703  
1704  /**
1705   * wmi_ext_dbgfs_deinit() - cleanup/deinit debugfs items of extended wmi dump.
1706   * @wmi_handle: wmi handler
1707   *
1708   * Return: QDF_STATUS_SUCCESS if cleanup is successful
1709   */
wmi_ext_dbgfs_deinit(struct wmi_unified * wmi_handle)1710  static QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
1711  {
1712  	struct wmi_ext_dbg_msg *msg;
1713  
1714  	while ((msg = wmi_ext_dbg_msg_dequeue(wmi_handle)))
1715  		wmi_ext_dbg_msg_put(msg);
1716  
1717  	wmi_ext_dbg_msg_queue_deinit(wmi_handle);
1718  	qdf_debugfs_remove_dir_recursive(wmi_handle->wmi_ext_dbg_dentry);
1719  
1720  	return QDF_STATUS_SUCCESS;
1721  }
1722  
1723  #else
1724  
wmi_ext_dbg_msg_cmd_record(struct wmi_unified * wmi_handle,uint8_t * buf,uint32_t len)1725  static inline QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified
1726  						    *wmi_handle,
1727  						    uint8_t *buf, uint32_t len)
1728  {
1729  		return QDF_STATUS_SUCCESS;
1730  }
1731  
wmi_ext_dbg_msg_event_record(struct wmi_unified * wmi_handle,uint8_t * buf,uint32_t len)1732  static inline QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified
1733  						      *wmi_handle,
1734  						      uint8_t *buf, uint32_t len)
1735  {
1736  		return QDF_STATUS_SUCCESS;
1737  }
1738  
wmi_ext_dbgfs_init(struct wmi_unified * wmi_handle,uint32_t pdev_idx)1739  static inline QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle,
1740  					    uint32_t pdev_idx)
1741  {
1742  		return QDF_STATUS_SUCCESS;
1743  }
1744  
wmi_ext_dbgfs_deinit(struct wmi_unified * wmi_handle)1745  static inline QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
1746  {
1747  		return QDF_STATUS_SUCCESS;
1748  }
1749  
1750  #endif /*WMI_EXT_DBG */
1751  
1752  int wmi_get_host_credits(wmi_unified_t wmi_handle);
1753  /* WMI buffer APIs */
1754  
1755  #ifdef NBUF_MEMORY_DEBUG
1756  wmi_buf_t
wmi_buf_alloc_debug(wmi_unified_t wmi_handle,uint32_t len,const char * func_name,uint32_t line_num)1757  wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint32_t len,
1758  		    const char *func_name,
1759  		    uint32_t line_num)
1760  {
1761  	wmi_buf_t wmi_buf;
1762  
1763  	if (roundup(len, 4) > wmi_handle->max_msg_len) {
1764  		wmi_err("Invalid length %u (via %s:%u) max size: %u",
1765  			len, func_name, line_num,
1766  			wmi_handle->max_msg_len);
1767  		QDF_ASSERT(0);
1768  		return NULL;
1769  	}
1770  
1771  	wmi_buf = wbuff_buff_get(wmi_handle->wbuff_handle, WBUFF_MAX_POOL_ID,
1772  				 len, func_name, line_num);
1773  	if (!wmi_buf)
1774  		wmi_buf = qdf_nbuf_alloc_debug(NULL,
1775  					       roundup(len + WMI_MIN_HEAD_ROOM,
1776  						       4),
1777  					       WMI_MIN_HEAD_ROOM, 4, false,
1778  					       func_name, line_num);
1779  	if (!wmi_buf)
1780  		return NULL;
1781  
1782  	/* Clear the wmi buffer */
1783  	OS_MEMZERO(qdf_nbuf_data(wmi_buf), len);
1784  
1785  	/*
1786  	 * Set the length of the buffer to match the allocation size.
1787  	 */
1788  	qdf_nbuf_set_pktlen(wmi_buf, len);
1789  
1790  	return wmi_buf;
1791  }
1792  qdf_export_symbol(wmi_buf_alloc_debug);
1793  
wmi_buf_free(wmi_buf_t net_buf)1794  void wmi_buf_free(wmi_buf_t net_buf)
1795  {
1796  	net_buf = wbuff_buff_put(net_buf);
1797  	if (net_buf)
1798  		qdf_nbuf_free(net_buf);
1799  }
1800  qdf_export_symbol(wmi_buf_free);
1801  #else
wmi_buf_alloc_fl(wmi_unified_t wmi_handle,uint32_t len,const char * func,uint32_t line)1802  wmi_buf_t wmi_buf_alloc_fl(wmi_unified_t wmi_handle, uint32_t len,
1803  			   const char *func, uint32_t line)
1804  {
1805  	wmi_buf_t wmi_buf;
1806  
1807  	if (roundup(len, 4) > wmi_handle->max_msg_len) {
1808  		QDF_DEBUG_PANIC("Invalid length %u (via %s:%u) max size: %u",
1809  				len, func, line, wmi_handle->max_msg_len);
1810  		return NULL;
1811  	}
1812  
1813  	wmi_buf = wbuff_buff_get(wmi_handle->wbuff_handle, WBUFF_MAX_POOL_ID,
1814  				 len, __func__, __LINE__);
1815  	if (!wmi_buf)
1816  		wmi_buf = qdf_nbuf_alloc_fl(NULL, roundup(len +
1817  				WMI_MIN_HEAD_ROOM, 4), WMI_MIN_HEAD_ROOM, 4,
1818  				false, func, line);
1819  
1820  	if (!wmi_buf) {
1821  		wmi_nofl_err("%s:%d, failed to alloc len:%d", func, line, len);
1822  		return NULL;
1823  	}
1824  
1825  	/* Clear the wmi buffer */
1826  	OS_MEMZERO(qdf_nbuf_data(wmi_buf), len);
1827  
1828  	/*
1829  	 * Set the length of the buffer to match the allocation size.
1830  	 */
1831  	qdf_nbuf_set_pktlen(wmi_buf, len);
1832  
1833  	return wmi_buf;
1834  }
1835  qdf_export_symbol(wmi_buf_alloc_fl);
1836  
wmi_buf_free(wmi_buf_t net_buf)1837  void wmi_buf_free(wmi_buf_t net_buf)
1838  {
1839  	net_buf = wbuff_buff_put(net_buf);
1840  	if (net_buf)
1841  		qdf_nbuf_free(net_buf);
1842  }
1843  qdf_export_symbol(wmi_buf_free);
1844  #endif
1845  
wmi_get_max_msg_len(wmi_unified_t wmi_handle)1846  uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle)
1847  {
1848  	return wmi_handle->max_msg_len - WMI_MIN_HEAD_ROOM;
1849  }
1850  qdf_export_symbol(wmi_get_max_msg_len);
1851  
1852  #ifndef WMI_CMD_STRINGS
wmi_id_to_name(uint32_t wmi_command)1853  static uint8_t *wmi_id_to_name(uint32_t wmi_command)
1854  {
1855  	return "Invalid WMI cmd";
1856  }
1857  #endif
1858  
wmi_log_cmd_id(uint32_t cmd_id,uint32_t tag)1859  static inline void wmi_log_cmd_id(uint32_t cmd_id, uint32_t tag)
1860  {
1861  	wmi_nofl_debug("Send cmd %s(0x%x) tag:%d",
1862  		       wmi_id_to_name(cmd_id), cmd_id, tag);
1863  }
1864  
1865  /**
1866   * wmi_is_pm_resume_cmd() - check if a cmd is part of the resume sequence
1867   * @cmd_id: command to check
1868   *
1869   * Return: true if the command is part of the resume sequence.
1870   */
1871  #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
wmi_is_pm_resume_cmd(uint32_t cmd_id)1872  static bool wmi_is_pm_resume_cmd(uint32_t cmd_id)
1873  {
1874  	switch (cmd_id) {
1875  	case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID:
1876  	case WMI_PDEV_RESUME_CMDID:
1877  		return true;
1878  
1879  	default:
1880  		return false;
1881  	}
1882  }
1883  
1884  #else
wmi_is_pm_resume_cmd(uint32_t cmd_id)1885  static bool wmi_is_pm_resume_cmd(uint32_t cmd_id)
1886  {
1887  	return false;
1888  }
1889  
1890  #endif
1891  
1892  #ifdef FEATURE_WLAN_D0WOW
wmi_is_legacy_d0wow_disable_cmd(wmi_buf_t buf,uint32_t cmd_id)1893  static bool wmi_is_legacy_d0wow_disable_cmd(wmi_buf_t buf, uint32_t cmd_id)
1894  {
1895  	wmi_d0_wow_enable_disable_cmd_fixed_param *cmd;
1896  
1897  	if (cmd_id == WMI_D0_WOW_ENABLE_DISABLE_CMDID) {
1898  		cmd = (wmi_d0_wow_enable_disable_cmd_fixed_param *)
1899  			wmi_buf_data(buf);
1900  		if (!cmd->enable)
1901  			return true;
1902  		else
1903  			return false;
1904  	}
1905  
1906  	return false;
1907  }
1908  #else
wmi_is_legacy_d0wow_disable_cmd(wmi_buf_t buf,uint32_t cmd_id)1909  static bool wmi_is_legacy_d0wow_disable_cmd(wmi_buf_t buf, uint32_t cmd_id)
1910  {
1911  	return false;
1912  }
1913  
1914  #endif
1915  
1916  #ifdef WMI_INTERFACE_SEQUENCE_CHECK
wmi_interface_sequence_reset(struct wmi_unified * wmi_handle)1917  static inline void wmi_interface_sequence_reset(struct wmi_unified *wmi_handle)
1918  {
1919  	wmi_handle->wmi_sequence = 0;
1920  	wmi_handle->wmi_exp_sequence = 0;
1921  	wmi_handle->wmi_sequence_stop = false;
1922  }
1923  
wmi_interface_sequence_init(struct wmi_unified * wmi_handle)1924  static inline void wmi_interface_sequence_init(struct wmi_unified *wmi_handle)
1925  {
1926  	qdf_spinlock_create(&wmi_handle->wmi_seq_lock);
1927  	wmi_interface_sequence_reset(wmi_handle);
1928  }
1929  
wmi_interface_sequence_deinit(struct wmi_unified * wmi_handle)1930  static inline void wmi_interface_sequence_deinit(struct wmi_unified *wmi_handle)
1931  {
1932  	qdf_spinlock_destroy(&wmi_handle->wmi_seq_lock);
1933  }
1934  
wmi_interface_sequence_stop(struct wmi_unified * wmi_handle)1935  void wmi_interface_sequence_stop(struct wmi_unified *wmi_handle)
1936  {
1937  	wmi_handle->wmi_sequence_stop = true;
1938  }
1939  
wmi_htc_send_pkt(struct wmi_unified * wmi_handle,HTC_PACKET * pkt,const char * func,uint32_t line)1940  static inline QDF_STATUS wmi_htc_send_pkt(struct wmi_unified *wmi_handle,
1941  					  HTC_PACKET *pkt,
1942  					  const char *func, uint32_t line)
1943  {
1944  	wmi_buf_t buf = GET_HTC_PACKET_NET_BUF_CONTEXT(pkt);
1945  	QDF_STATUS status;
1946  
1947  	qdf_spin_lock_bh(&wmi_handle->wmi_seq_lock);
1948  	status = htc_send_pkt(wmi_handle->htc_handle, pkt);
1949  	if (QDF_STATUS_SUCCESS != status) {
1950  		qdf_spin_unlock_bh(&wmi_handle->wmi_seq_lock);
1951  		qdf_atomic_dec(&wmi_handle->pending_cmds);
1952  		wmi_nofl_err("%s:%d, htc_send_pkt failed, status:%d",
1953  			     func, line, status);
1954  		qdf_mem_free(pkt);
1955  		return status;
1956  	}
1957  	/* Record the sequence number in the SKB */
1958  	qdf_nbuf_set_mark(buf, wmi_handle->wmi_sequence);
1959  	/* Increment the sequence number */
1960  	wmi_handle->wmi_sequence = (wmi_handle->wmi_sequence + 1)
1961  				   & (wmi_handle->wmi_max_cmds - 1);
1962  	qdf_spin_unlock_bh(&wmi_handle->wmi_seq_lock);
1963  
1964  	return status;
1965  }
1966  
wmi_interface_sequence_check(struct wmi_unified * wmi_handle,wmi_buf_t buf)1967  static inline void wmi_interface_sequence_check(struct wmi_unified *wmi_handle,
1968  						wmi_buf_t buf)
1969  {
1970  	/* Skip sequence check when wmi sequence stop is set */
1971  	if (wmi_handle->wmi_sequence_stop)
1972  		return;
1973  
1974  	qdf_spin_lock_bh(&wmi_handle->wmi_seq_lock);
1975  	/* Match the completion sequence and expected sequence number */
1976  	if (qdf_nbuf_get_mark(buf) != wmi_handle->wmi_exp_sequence) {
1977  		qdf_spin_unlock_bh(&wmi_handle->wmi_seq_lock);
1978  		wmi_nofl_err("WMI Tx Completion Sequence number mismatch");
1979  		wmi_nofl_err("Expected %d Received %d",
1980  			     wmi_handle->wmi_exp_sequence,
1981  			     qdf_nbuf_get_mark(buf));
1982  		/* Trigger Recovery */
1983  		qdf_trigger_self_recovery(wmi_handle->soc,
1984  					  QDF_WMI_BUF_SEQUENCE_MISMATCH);
1985  	} else {
1986  		/* Increment the expected sequence number */
1987  		wmi_handle->wmi_exp_sequence =
1988  				(wmi_handle->wmi_exp_sequence + 1)
1989  				& (wmi_handle->wmi_max_cmds - 1);
1990  		qdf_spin_unlock_bh(&wmi_handle->wmi_seq_lock);
1991  	}
1992  }
1993  #else
wmi_interface_sequence_reset(struct wmi_unified * wmi_handle)1994  static inline void wmi_interface_sequence_reset(struct wmi_unified *wmi_handle)
1995  {
1996  }
1997  
wmi_interface_sequence_init(struct wmi_unified * wmi_handle)1998  static inline void wmi_interface_sequence_init(struct wmi_unified *wmi_handle)
1999  {
2000  }
2001  
wmi_interface_sequence_deinit(struct wmi_unified * wmi_handle)2002  static inline void wmi_interface_sequence_deinit(struct wmi_unified *wmi_handle)
2003  {
2004  }
2005  
wmi_interface_sequence_stop(struct wmi_unified * wmi_handle)2006  void wmi_interface_sequence_stop(struct wmi_unified *wmi_handle)
2007  {
2008  }
2009  
wmi_htc_send_pkt(struct wmi_unified * wmi_handle,HTC_PACKET * pkt,const char * func,uint32_t line)2010  static inline QDF_STATUS wmi_htc_send_pkt(struct wmi_unified *wmi_handle,
2011  					  HTC_PACKET *pkt,
2012  					  const char *func, uint32_t line)
2013  {
2014  	QDF_STATUS status;
2015  
2016  	status = htc_send_pkt(wmi_handle->htc_handle, pkt);
2017  	if (QDF_STATUS_SUCCESS != status) {
2018  		qdf_atomic_dec(&wmi_handle->pending_cmds);
2019  		wmi_nofl_err("%s:%d, htc_send_pkt failed, status:%d",
2020  			     func, line, status);
2021  		qdf_mem_free(pkt);
2022  		return status;
2023  	}
2024  
2025  	return status;
2026  }
2027  
wmi_interface_sequence_check(struct wmi_unified * wmi_handle,wmi_buf_t buf)2028  static inline void wmi_interface_sequence_check(struct wmi_unified *wmi_handle,
2029  						wmi_buf_t buf)
2030  {
2031  }
2032  #endif
2033  
wmi_unified_debug_dump(wmi_unified_t wmi_handle)2034  static inline void wmi_unified_debug_dump(wmi_unified_t wmi_handle)
2035  {
2036  	wmi_nofl_err("Endpoint ID = %d, Tx Queue Depth = %d, soc_id = %u, target type = %s",
2037  		     wmi_handle->wmi_endpoint_id,
2038  		     htc_get_tx_queue_depth(wmi_handle->htc_handle,
2039  					    wmi_handle->wmi_endpoint_id),
2040  		     wmi_handle->soc->soc_idx,
2041  		     (wmi_handle->target_type ==
2042  		      WMI_TLV_TARGET ? "WMI_TLV_TARGET" :
2043  						"WMI_NON_TLV_TARGET"));
2044  }
2045  
2046  #ifdef SYSTEM_PM_CHECK
2047  /**
2048   * wmi_set_system_pm_pkt_tag() - API to set tag for system pm packets
2049   * @htc_tag: HTC tag
2050   * @buf: wmi cmd buffer
2051   * @cmd_id: cmd id
2052   *
2053   * Return: None
2054   */
wmi_set_system_pm_pkt_tag(uint16_t * htc_tag,wmi_buf_t buf,uint32_t cmd_id)2055  static void wmi_set_system_pm_pkt_tag(uint16_t *htc_tag, wmi_buf_t buf,
2056  				      uint32_t cmd_id)
2057  {
2058  	switch (cmd_id) {
2059  	case WMI_WOW_ENABLE_CMDID:
2060  	case WMI_PDEV_SUSPEND_CMDID:
2061  		*htc_tag = HTC_TX_PACKET_SYSTEM_SUSPEND;
2062  		break;
2063  	case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID:
2064  	case WMI_PDEV_RESUME_CMDID:
2065  		*htc_tag = HTC_TX_PACKET_SYSTEM_RESUME;
2066  		break;
2067  	case WMI_D0_WOW_ENABLE_DISABLE_CMDID:
2068  		if (wmi_is_legacy_d0wow_disable_cmd(buf, cmd_id))
2069  			*htc_tag = HTC_TX_PACKET_SYSTEM_RESUME;
2070  		else
2071  			*htc_tag = HTC_TX_PACKET_SYSTEM_SUSPEND;
2072  		break;
2073  	default:
2074  		break;
2075  	}
2076  }
2077  #else
wmi_set_system_pm_pkt_tag(uint16_t * htc_tag,wmi_buf_t buf,uint32_t cmd_id)2078  static inline void wmi_set_system_pm_pkt_tag(uint16_t *htc_tag, wmi_buf_t buf,
2079  					     uint32_t cmd_id)
2080  {
2081  }
2082  #endif
2083  
2084  #ifdef DP_UMAC_HW_RESET_SUPPORT
2085  /**
2086   * wmi_unified_is_max_pending_commands_reached() - API to check if WMI max
2087   * pending commands are reached.
2088   * @wmi_handle: Pointer to WMI handle
2089   *
2090   * Return: If umac reset is in progress and max wmi pending commands are reached
2091   * then return false. The reason is FW will not reap the WMI commands from CE
2092   * ring when umac reset is in progress. Hence, all the pending WMI command to
2093   * host SW ring.
2094   */
2095  static inline bool
wmi_unified_is_max_pending_commands_reached(wmi_unified_t wmi_handle)2096  wmi_unified_is_max_pending_commands_reached(wmi_unified_t wmi_handle)
2097  {
2098  	ol_txrx_soc_handle soc_txrx_handle;
2099  
2100  	soc_txrx_handle = (ol_txrx_soc_handle)wlan_psoc_get_dp_handle(
2101  			wmi_handle->soc->wmi_psoc);
2102  	if (!soc_txrx_handle) {
2103  		wmi_err("psoc handle is NULL");
2104  		return false;
2105  	}
2106  
2107  	return ((qdf_atomic_read(&wmi_handle->pending_cmds) >=
2108  			wmi_handle->wmi_max_cmds) &&
2109  		!cdp_umac_reset_is_inprogress(soc_txrx_handle));
2110  }
2111  #else
2112  static inline bool
wmi_unified_is_max_pending_commands_reached(wmi_unified_t wmi_handle)2113  wmi_unified_is_max_pending_commands_reached(wmi_unified_t wmi_handle)
2114  {
2115  	return (qdf_atomic_read(&wmi_handle->pending_cmds) >=
2116  			wmi_handle->wmi_max_cmds);
2117  }
2118  #endif
2119  
wmi_unified_cmd_send_fl(wmi_unified_t wmi_handle,wmi_buf_t buf,uint32_t len,uint32_t cmd_id,const char * func,uint32_t line)2120  QDF_STATUS wmi_unified_cmd_send_fl(wmi_unified_t wmi_handle, wmi_buf_t buf,
2121  				   uint32_t len, uint32_t cmd_id,
2122  				   const char *func, uint32_t line)
2123  {
2124  	HTC_PACKET *pkt;
2125  	uint16_t htc_tag = 0;
2126  	bool rtpm_inprogress;
2127  
2128  	rtpm_inprogress = wmi_get_runtime_pm_inprogress(wmi_handle);
2129  	if (rtpm_inprogress) {
2130  		htc_tag = wmi_handle->ops->wmi_set_htc_tx_tag(wmi_handle, buf,
2131  							      cmd_id);
2132  	} else if (qdf_atomic_read(&wmi_handle->is_target_suspended) &&
2133  		   !wmi_is_pm_resume_cmd(cmd_id) &&
2134  		   !wmi_is_legacy_d0wow_disable_cmd(buf, cmd_id)) {
2135  			wmi_nofl_err("Target is suspended (via %s:%u)",
2136  					func, line);
2137  		return QDF_STATUS_E_BUSY;
2138  	}
2139  
2140  	if (wmi_handle->wmi_stopinprogress) {
2141  		wmi_nofl_err("%s:%d, WMI stop in progress, wmi_handle:%pK",
2142  			     func, line, wmi_handle);
2143  		return QDF_STATUS_E_INVAL;
2144  	}
2145  
2146  	if (wmi_has_wow_enable_ack_failed(wmi_handle)) {
2147  		wmi_nofl_err("wow enable ack already failed(via %s:%u)",
2148  			     func, line);
2149  		return QDF_STATUS_E_INVAL;
2150  	}
2151  
2152  #ifndef WMI_NON_TLV_SUPPORT
2153  	/* Do sanity check on the TLV parameter structure */
2154  	if (wmi_handle->target_type == WMI_TLV_TARGET) {
2155  		void *buf_ptr = (void *)qdf_nbuf_data(buf);
2156  
2157  		if (wmi_handle->ops->wmi_check_command_params(NULL, buf_ptr, len, cmd_id)
2158  			!= 0) {
2159  			wmi_nofl_err("%s:%d, Invalid WMI Param Buffer for Cmd:%d",
2160  				     func, line, cmd_id);
2161  			return QDF_STATUS_E_INVAL;
2162  		}
2163  	}
2164  #endif
2165  
2166  	if (qdf_nbuf_push_head(buf, sizeof(WMI_CMD_HDR)) == NULL) {
2167  		wmi_nofl_err("%s:%d, Failed to send cmd %x, no memory",
2168  			     func, line, cmd_id);
2169  		return QDF_STATUS_E_NOMEM;
2170  	}
2171  
2172  	qdf_mem_zero(qdf_nbuf_data(buf), sizeof(WMI_CMD_HDR));
2173  	WMI_SET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id);
2174  
2175  	qdf_atomic_inc(&wmi_handle->pending_cmds);
2176  	if (wmi_unified_is_max_pending_commands_reached(wmi_handle)) {
2177  		wmi_dump_last_cmd_rec_info(wmi_handle);
2178  		wmi_nofl_err("hostcredits = %d",
2179  			     wmi_get_host_credits(wmi_handle));
2180  		htc_dump_counter_info(wmi_handle->htc_handle);
2181  		qdf_atomic_dec(&wmi_handle->pending_cmds);
2182  		wmi_nofl_err("%s:%d, MAX %d WMI Pending cmds reached",
2183  			     func, line, wmi_handle->wmi_max_cmds);
2184  		wmi_unified_debug_dump(wmi_handle);
2185  		htc_ce_tasklet_debug_dump(wmi_handle->htc_handle);
2186  		qdf_trigger_self_recovery(wmi_handle->soc->wmi_psoc,
2187  					  QDF_WMI_EXCEED_MAX_PENDING_CMDS);
2188  		return QDF_STATUS_E_BUSY;
2189  	}
2190  
2191  	pkt = qdf_mem_malloc_fl(sizeof(*pkt), func, line);
2192  	if (!pkt) {
2193  		qdf_atomic_dec(&wmi_handle->pending_cmds);
2194  		return QDF_STATUS_E_NOMEM;
2195  	}
2196  
2197  	if (!rtpm_inprogress)
2198  		wmi_set_system_pm_pkt_tag(&htc_tag, buf, cmd_id);
2199  
2200  	SET_HTC_PACKET_INFO_TX(pkt,
2201  			       NULL,
2202  			       qdf_nbuf_data(buf), len + sizeof(WMI_CMD_HDR),
2203  			       wmi_handle->wmi_endpoint_id, htc_tag);
2204  
2205  	SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf);
2206  	wmi_log_cmd_id(cmd_id, htc_tag);
2207  	wmi_ext_dbg_msg_cmd_record(wmi_handle,
2208  				   qdf_nbuf_data(buf), qdf_nbuf_len(buf));
2209  #ifdef WMI_INTERFACE_EVENT_LOGGING
2210  	if (wmi_handle->log_info.wmi_logging_enable) {
2211  		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
2212  		/*
2213  		 * Record 16 bytes of WMI cmd data -
2214  		 * exclude TLV and WMI headers
2215  		 *
2216  		 * WMI mgmt command already recorded in wmi_mgmt_cmd_record
2217  		 */
2218  		if (wmi_handle->ops->is_management_record(cmd_id) == false) {
2219  			uint8_t *tmpbuf = (uint8_t *)qdf_nbuf_data(buf) +
2220  				wmi_handle->soc->buf_offset_command;
2221  
2222  			WMI_COMMAND_RECORD(wmi_handle, cmd_id, tmpbuf);
2223  			wmi_specific_cmd_record(wmi_handle, cmd_id, tmpbuf);
2224  		}
2225  
2226  		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
2227  	}
2228  #endif
2229  	return wmi_htc_send_pkt(wmi_handle, pkt, func, line);
2230  }
2231  qdf_export_symbol(wmi_unified_cmd_send_fl);
2232  
2233  /**
2234   * wmi_unified_get_event_handler_ix() - gives event handler's index
2235   * @wmi_handle: handle to wmi
2236   * @event_id: wmi  event id
2237   *
2238   * Return: event handler's index
2239   */
wmi_unified_get_event_handler_ix(wmi_unified_t wmi_handle,uint32_t event_id)2240  static int wmi_unified_get_event_handler_ix(wmi_unified_t wmi_handle,
2241  					    uint32_t event_id)
2242  {
2243  	uint32_t idx = 0;
2244  	int32_t invalid_idx = -1;
2245  	struct wmi_soc *soc = wmi_handle->soc;
2246  
2247  	for (idx = 0; (idx < soc->max_event_idx &&
2248  		       idx < WMI_UNIFIED_MAX_EVENT); ++idx) {
2249  		if (wmi_handle->event_id[idx] == event_id &&
2250  		    wmi_handle->event_handler[idx]) {
2251  			return idx;
2252  		}
2253  	}
2254  
2255  	return invalid_idx;
2256  }
2257  
2258  /**
2259   * wmi_register_event_handler_with_ctx() - register event handler with
2260   * exec ctx and buffer type
2261   * @wmi_handle: handle to wmi
2262   * @event_id: wmi event id
2263   * @handler_func: wmi event handler function
2264   * @rx_ctx: rx execution context for wmi rx events
2265   * @rx_buf_type: rx execution context for wmi rx events
2266   *
2267   * Return: QDF_STATUS_SUCCESS on successful register event else failure.
2268   */
2269  static QDF_STATUS
wmi_register_event_handler_with_ctx(wmi_unified_t wmi_handle,uint32_t event_id,wmi_unified_event_handler handler_func,enum wmi_rx_exec_ctx rx_ctx,enum wmi_rx_buff_type rx_buf_type)2270  wmi_register_event_handler_with_ctx(wmi_unified_t wmi_handle,
2271  				    uint32_t event_id,
2272  				    wmi_unified_event_handler handler_func,
2273  				    enum wmi_rx_exec_ctx rx_ctx,
2274  				    enum wmi_rx_buff_type rx_buf_type)
2275  {
2276  	uint32_t idx = 0;
2277  	uint32_t evt_id;
2278  	struct wmi_soc *soc;
2279  
2280  	if (!wmi_handle) {
2281  		wmi_err("WMI handle is NULL");
2282  		return QDF_STATUS_E_FAILURE;
2283  	}
2284  
2285  	soc = wmi_handle->soc;
2286  
2287  	if (event_id >= wmi_events_max) {
2288  		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO,
2289  			  "%s: Event id %d is unavailable",
2290  					__func__, event_id);
2291  		return QDF_STATUS_E_FAILURE;
2292  	}
2293  
2294  	if (wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) {
2295  		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
2296  			  "%s: Event id %d is not supported",
2297  			  __func__, event_id);
2298  		return QDF_STATUS_E_NOSUPPORT;
2299  	}
2300  	evt_id = wmi_handle->wmi_events[event_id];
2301  
2302  	if (wmi_unified_get_event_handler_ix(wmi_handle, evt_id) != -1) {
2303  		wmi_info("event handler already registered 0x%x", evt_id);
2304  		return QDF_STATUS_E_FAILURE;
2305  	}
2306  	if (soc->max_event_idx == WMI_UNIFIED_MAX_EVENT) {
2307  		wmi_err("no more event handlers 0x%x",
2308  			 evt_id);
2309  		return QDF_STATUS_E_FAILURE;
2310  	}
2311  	QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
2312  		  "Registered event handler for event 0x%8x", evt_id);
2313  	idx = soc->max_event_idx;
2314  	wmi_handle->event_handler[idx] = handler_func;
2315  	wmi_handle->event_id[idx] = evt_id;
2316  
2317  	qdf_spin_lock_bh(&soc->ctx_lock);
2318  	wmi_handle->ctx[idx].exec_ctx = rx_ctx;
2319  	wmi_handle->ctx[idx].buff_type = rx_buf_type;
2320  	qdf_spin_unlock_bh(&soc->ctx_lock);
2321  	soc->max_event_idx++;
2322  
2323  	return QDF_STATUS_SUCCESS;
2324  }
2325  
2326  QDF_STATUS
wmi_unified_register_event(wmi_unified_t wmi_handle,uint32_t event_id,wmi_unified_event_handler handler_func)2327  wmi_unified_register_event(wmi_unified_t wmi_handle,
2328  			   uint32_t event_id,
2329  			   wmi_unified_event_handler handler_func)
2330  {
2331  	return wmi_register_event_handler_with_ctx(wmi_handle, event_id,
2332  						   handler_func,
2333  						   WMI_RX_UMAC_CTX,
2334  						   WMI_RX_PROCESSED_BUFF);
2335  }
2336  
2337  QDF_STATUS
wmi_unified_register_event_handler(wmi_unified_t wmi_handle,wmi_conv_event_id event_id,wmi_unified_event_handler handler_func,uint8_t rx_ctx)2338  wmi_unified_register_event_handler(wmi_unified_t wmi_handle,
2339  				   wmi_conv_event_id event_id,
2340  				   wmi_unified_event_handler handler_func,
2341  				   uint8_t rx_ctx)
2342  {
2343  	return wmi_register_event_handler_with_ctx(wmi_handle, event_id,
2344  						   handler_func, rx_ctx,
2345  						   WMI_RX_PROCESSED_BUFF);
2346  }
2347  
2348  qdf_export_symbol(wmi_unified_register_event_handler);
2349  
2350  QDF_STATUS
wmi_unified_register_raw_event_handler(wmi_unified_t wmi_handle,wmi_conv_event_id event_id,wmi_unified_event_handler handler_func,enum wmi_rx_exec_ctx rx_ctx)2351  wmi_unified_register_raw_event_handler(wmi_unified_t wmi_handle,
2352  				       wmi_conv_event_id event_id,
2353  				       wmi_unified_event_handler handler_func,
2354  				       enum wmi_rx_exec_ctx rx_ctx)
2355  {
2356  	return wmi_register_event_handler_with_ctx(wmi_handle, event_id,
2357  						   handler_func, rx_ctx,
2358  						   WMI_RX_RAW_BUFF);
2359  }
2360  
2361  qdf_export_symbol(wmi_unified_register_raw_event_handler);
2362  
wmi_unified_unregister_event(wmi_unified_t wmi_handle,uint32_t event_id)2363  QDF_STATUS wmi_unified_unregister_event(wmi_unified_t wmi_handle,
2364  					uint32_t event_id)
2365  {
2366  	uint32_t idx = 0;
2367  	uint32_t evt_id;
2368  	struct wmi_soc *soc;
2369  
2370  	if (!wmi_handle) {
2371  		wmi_err("WMI handle is NULL");
2372  		return QDF_STATUS_E_FAILURE;
2373  	}
2374  
2375  	soc = wmi_handle->soc;
2376  	if (event_id >= wmi_events_max ||
2377  		wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) {
2378  		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO,
2379  			  "%s: Event id %d is unavailable",
2380  					__func__, event_id);
2381  		return QDF_STATUS_E_FAILURE;
2382  	}
2383  	evt_id = wmi_handle->wmi_events[event_id];
2384  
2385  	idx = wmi_unified_get_event_handler_ix(wmi_handle, evt_id);
2386  	if (idx == -1) {
2387  		wmi_warn("event handler is not registered: evt id 0x%x",
2388  			 evt_id);
2389  		return QDF_STATUS_E_FAILURE;
2390  	}
2391  	wmi_handle->event_handler[idx] = NULL;
2392  	wmi_handle->event_id[idx] = 0;
2393  	--soc->max_event_idx;
2394  	wmi_handle->event_handler[idx] =
2395  		wmi_handle->event_handler[soc->max_event_idx];
2396  	wmi_handle->event_id[idx] =
2397  		wmi_handle->event_id[soc->max_event_idx];
2398  
2399  	qdf_spin_lock_bh(&soc->ctx_lock);
2400  
2401  	wmi_handle->ctx[idx].exec_ctx =
2402  		wmi_handle->ctx[soc->max_event_idx].exec_ctx;
2403  	wmi_handle->ctx[idx].buff_type =
2404  		wmi_handle->ctx[soc->max_event_idx].buff_type;
2405  
2406  	qdf_spin_unlock_bh(&soc->ctx_lock);
2407  
2408  	return QDF_STATUS_SUCCESS;
2409  }
2410  
wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle,wmi_conv_event_id event_id)2411  QDF_STATUS wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle,
2412  						wmi_conv_event_id event_id)
2413  {
2414  	uint32_t idx = 0;
2415  	uint32_t evt_id;
2416  	struct wmi_soc *soc;
2417  
2418  	if (!wmi_handle) {
2419  		wmi_err("WMI handle is NULL");
2420  		return QDF_STATUS_E_FAILURE;
2421  	}
2422  
2423  	soc = wmi_handle->soc;
2424  
2425  	if (event_id >= wmi_events_max) {
2426  		wmi_err("Event id %d is unavailable", event_id);
2427  		return QDF_STATUS_E_FAILURE;
2428  	}
2429  
2430  	if (wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) {
2431  		wmi_debug("Event id %d is not supported", event_id);
2432  		return QDF_STATUS_E_NOSUPPORT;
2433  	}
2434  
2435  	evt_id = wmi_handle->wmi_events[event_id];
2436  
2437  	idx = wmi_unified_get_event_handler_ix(wmi_handle, evt_id);
2438  	if (idx == -1) {
2439  		wmi_err("event handler is not registered: evt id 0x%x",
2440  			 evt_id);
2441  		return QDF_STATUS_E_FAILURE;
2442  	}
2443  	wmi_handle->event_handler[idx] = NULL;
2444  	wmi_handle->event_id[idx] = 0;
2445  	--soc->max_event_idx;
2446  	wmi_handle->event_handler[idx] =
2447  		wmi_handle->event_handler[soc->max_event_idx];
2448  	wmi_handle->event_id[idx] =
2449  		wmi_handle->event_id[soc->max_event_idx];
2450  
2451  	qdf_spin_lock_bh(&soc->ctx_lock);
2452  
2453  	wmi_handle->ctx[idx].exec_ctx =
2454  		wmi_handle->ctx[soc->max_event_idx].exec_ctx;
2455  	wmi_handle->ctx[idx].buff_type =
2456  		wmi_handle->ctx[soc->max_event_idx].buff_type;
2457  
2458  	qdf_spin_unlock_bh(&soc->ctx_lock);
2459  
2460  	return QDF_STATUS_SUCCESS;
2461  }
2462  qdf_export_symbol(wmi_unified_unregister_event_handler);
2463  
2464  static void
wmi_process_rx_diag_event_worker_thread_ctx(struct wmi_unified * wmi_handle,void * evt_buf)2465  wmi_process_rx_diag_event_worker_thread_ctx(struct wmi_unified *wmi_handle,
2466  					    void *evt_buf)
2467  {
2468  	uint32_t num_diag_events_pending;
2469  
2470  	qdf_spin_lock_bh(&wmi_handle->diag_eventq_lock);
2471  	if (RX_DIAG_WQ_MAX_SIZE > 0) {
2472  		num_diag_events_pending = qdf_nbuf_queue_len(
2473  						&wmi_handle->diag_event_queue);
2474  
2475  		if (num_diag_events_pending >= RX_DIAG_WQ_MAX_SIZE) {
2476  			qdf_spin_unlock_bh(&wmi_handle->diag_eventq_lock);
2477  			wmi_handle->wmi_rx_diag_events_dropped++;
2478  			wmi_debug_rl("Rx diag events dropped count: %d",
2479  				     wmi_handle->wmi_rx_diag_events_dropped);
2480  			qdf_nbuf_free(evt_buf);
2481  			return;
2482  		}
2483  	}
2484  
2485  	qdf_nbuf_queue_add(&wmi_handle->diag_event_queue, evt_buf);
2486  	qdf_spin_unlock_bh(&wmi_handle->diag_eventq_lock);
2487  	qdf_queue_work(0, wmi_handle->wmi_rx_diag_work_queue,
2488  		       &wmi_handle->rx_diag_event_work);
2489  }
2490  
wmi_process_fw_event_worker_thread_ctx(struct wmi_unified * wmi_handle,void * evt_buf)2491  void wmi_process_fw_event_worker_thread_ctx(struct wmi_unified *wmi_handle,
2492  					    void *evt_buf)
2493  {
2494  
2495  	qdf_spin_lock_bh(&wmi_handle->eventq_lock);
2496  	qdf_nbuf_queue_add(&wmi_handle->event_queue, evt_buf);
2497  	qdf_spin_unlock_bh(&wmi_handle->eventq_lock);
2498  	qdf_queue_work(0, wmi_handle->wmi_rx_work_queue,
2499  			&wmi_handle->rx_event_work);
2500  
2501  	return;
2502  }
2503  
2504  qdf_export_symbol(wmi_process_fw_event_worker_thread_ctx);
2505  
wmi_critical_events_in_flight(struct wmi_unified * wmi)2506  uint32_t wmi_critical_events_in_flight(struct wmi_unified *wmi)
2507  {
2508  	return qdf_atomic_read(&wmi->critical_events_in_flight);
2509  }
2510  
2511  static bool
wmi_is_event_critical(struct wmi_unified * wmi_handle,uint32_t event_id)2512  wmi_is_event_critical(struct wmi_unified *wmi_handle, uint32_t event_id)
2513  {
2514  	if (wmi_handle->wmi_events[wmi_roam_synch_event_id] == event_id)
2515  		return true;
2516  
2517  	return false;
2518  }
2519  
wmi_discard_fw_event(struct scheduler_msg * msg)2520  static QDF_STATUS wmi_discard_fw_event(struct scheduler_msg *msg)
2521  {
2522  	struct wmi_process_fw_event_params *event_param;
2523  
2524  	if (!msg->bodyptr)
2525  		return QDF_STATUS_E_INVAL;
2526  
2527  	event_param = (struct wmi_process_fw_event_params *)msg->bodyptr;
2528  	qdf_nbuf_free(event_param->evt_buf);
2529  	qdf_mem_free(msg->bodyptr);
2530  	msg->bodyptr = NULL;
2531  	msg->bodyval = 0;
2532  	msg->type = 0;
2533  
2534  	return QDF_STATUS_SUCCESS;
2535  }
2536  
wmi_process_fw_event_handler(struct scheduler_msg * msg)2537  static QDF_STATUS wmi_process_fw_event_handler(struct scheduler_msg *msg)
2538  {
2539  	struct wmi_process_fw_event_params *params =
2540  		(struct wmi_process_fw_event_params *)msg->bodyptr;
2541  	struct wmi_unified *wmi_handle;
2542  	uint32_t event_id;
2543  
2544  	wmi_handle = (struct wmi_unified *)params->wmi_handle;
2545  	event_id = WMI_GET_FIELD(qdf_nbuf_data(params->evt_buf),
2546  				 WMI_CMD_HDR, COMMANDID);
2547  	wmi_process_fw_event(wmi_handle, params->evt_buf);
2548  
2549  	if (wmi_is_event_critical(wmi_handle, event_id))
2550  		qdf_atomic_dec(&wmi_handle->critical_events_in_flight);
2551  
2552  	qdf_mem_free(msg->bodyptr);
2553  
2554  	return QDF_STATUS_SUCCESS;
2555  }
2556  
2557  /**
2558   * wmi_process_fw_event_sched_thread_ctx() - common event handler to serialize
2559   *                                  event processing through scheduler thread
2560   * @wmi: wmi context
2561   * @ev: event buffer
2562   *
2563   * Return: 0 on success, errno on failure
2564   */
2565  static QDF_STATUS
wmi_process_fw_event_sched_thread_ctx(struct wmi_unified * wmi,void * ev)2566  wmi_process_fw_event_sched_thread_ctx(struct wmi_unified *wmi,
2567  				      void *ev)
2568  {
2569  	struct wmi_process_fw_event_params *params_buf;
2570  	struct scheduler_msg msg = { 0 };
2571  	uint32_t event_id;
2572  
2573  	params_buf = qdf_mem_malloc(sizeof(struct wmi_process_fw_event_params));
2574  	if (!params_buf) {
2575  		wmi_err("malloc failed");
2576  		qdf_nbuf_free(ev);
2577  		return QDF_STATUS_E_NOMEM;
2578  	}
2579  
2580  	params_buf->wmi_handle = wmi;
2581  	params_buf->evt_buf = ev;
2582  
2583  	event_id = WMI_GET_FIELD(qdf_nbuf_data(params_buf->evt_buf),
2584  				 WMI_CMD_HDR, COMMANDID);
2585  	if (wmi_is_event_critical(wmi, event_id))
2586  		qdf_atomic_inc(&wmi->critical_events_in_flight);
2587  
2588  	msg.bodyptr = params_buf;
2589  	msg.bodyval = 0;
2590  	msg.callback = wmi_process_fw_event_handler;
2591  	msg.flush_callback = wmi_discard_fw_event;
2592  
2593  	if (QDF_STATUS_SUCCESS !=
2594  		scheduler_post_message(QDF_MODULE_ID_TARGET_IF,
2595  				       QDF_MODULE_ID_TARGET_IF,
2596  				       QDF_MODULE_ID_TARGET_IF, &msg)) {
2597  		qdf_nbuf_free(ev);
2598  		qdf_mem_free(params_buf);
2599  		return QDF_STATUS_E_FAULT;
2600  	}
2601  
2602  	return QDF_STATUS_SUCCESS;
2603  }
2604  
2605  /**
2606   * wmi_get_pdev_ep: Get wmi handle based on endpoint
2607   * @soc: handle to wmi soc
2608   * @ep: endpoint id
2609   *
2610   * Return: none
2611   */
wmi_get_pdev_ep(struct wmi_soc * soc,HTC_ENDPOINT_ID ep)2612  static struct wmi_unified *wmi_get_pdev_ep(struct wmi_soc *soc,
2613  						HTC_ENDPOINT_ID ep)
2614  {
2615  	uint32_t i;
2616  
2617  	for (i = 0; i < WMI_MAX_RADIOS; i++)
2618  		if (soc->wmi_endpoint_id[i] == ep)
2619  			break;
2620  
2621  	if (i == WMI_MAX_RADIOS)
2622  		return NULL;
2623  
2624  	return soc->wmi_pdev[i];
2625  }
2626  
2627  /**
2628   * wmi_mtrace_rx() - Wrappper function for qdf_mtrace api
2629   * @message_id: 32-Bit Wmi message ID
2630   * @vdev_id: Vdev ID
2631   * @data: Actual message contents
2632   *
2633   * This function converts the 32-bit WMI message ID in 15-bit message ID
2634   * format for qdf_mtrace as in qdf_mtrace message there are only 15
2635   * bits reserved for message ID.
2636   * out of these 15-bits, 8-bits (From LSB) specifies the WMI_GRP_ID
2637   * and remaining 7-bits specifies the actual WMI command. With this
2638   * notation there can be maximum 256 groups and each group can have
2639   * max 128 commands can be supported.
2640   *
2641   * Return: None
2642   */
wmi_mtrace_rx(uint32_t message_id,uint16_t vdev_id,uint32_t data)2643  static void wmi_mtrace_rx(uint32_t message_id, uint16_t vdev_id, uint32_t data)
2644  {
2645  	uint16_t mtrace_message_id;
2646  
2647  	mtrace_message_id = QDF_WMI_MTRACE_CMD_ID(message_id) |
2648  		(QDF_WMI_MTRACE_GRP_ID(message_id) <<
2649  						QDF_WMI_MTRACE_CMD_NUM_BITS);
2650  	qdf_mtrace(QDF_MODULE_ID_WMI, QDF_MODULE_ID_WMA,
2651  		   mtrace_message_id, vdev_id, data);
2652  }
2653  
2654  #ifdef WLAN_FEATURE_CE_RX_BUFFER_REUSE
wmi_rx_nbuf_free(qdf_nbuf_t nbuf)2655  static void wmi_rx_nbuf_free(qdf_nbuf_t nbuf)
2656  {
2657  	nbuf = wbuff_buff_put(nbuf);
2658  	if (nbuf)
2659  		qdf_nbuf_free(nbuf);
2660  }
2661  #else
wmi_rx_nbuf_free(qdf_nbuf_t nbuf)2662  static inline void wmi_rx_nbuf_free(qdf_nbuf_t nbuf)
2663  {
2664  	return qdf_nbuf_free(nbuf);
2665  }
2666  #endif
2667  
2668  /**
2669   * wmi_process_control_rx() - process fw events callbacks
2670   * @wmi_handle: handle to wmi_unified
2671   * @evt_buf: handle to wmi_buf_t
2672   *
2673   * Return: none
2674   */
wmi_process_control_rx(struct wmi_unified * wmi_handle,wmi_buf_t evt_buf)2675  static void wmi_process_control_rx(struct wmi_unified *wmi_handle,
2676  				   wmi_buf_t evt_buf)
2677  {
2678  	struct wmi_soc *soc = wmi_handle->soc;
2679  	uint32_t id;
2680  	uint32_t idx;
2681  	enum wmi_rx_exec_ctx exec_ctx;
2682  
2683  	id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
2684  	idx = wmi_unified_get_event_handler_ix(wmi_handle, id);
2685  	if (qdf_unlikely(idx == A_ERROR)) {
2686  		wmi_debug("no handler registered for event id 0x%x", id);
2687  		wmi_rx_nbuf_free(evt_buf);
2688  		return;
2689  	}
2690  	wmi_mtrace_rx(id, 0xFF, idx);
2691  	qdf_spin_lock_bh(&soc->ctx_lock);
2692  	exec_ctx = wmi_handle->ctx[idx].exec_ctx;
2693  	qdf_spin_unlock_bh(&soc->ctx_lock);
2694  
2695  #ifdef WMI_INTERFACE_EVENT_LOGGING
2696  	if (wmi_handle->log_info.wmi_logging_enable) {
2697  		uint8_t *data;
2698  		data = qdf_nbuf_data(evt_buf);
2699  
2700  		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
2701  		/* Exclude 4 bytes of TLV header */
2702  		if (wmi_handle->ops->is_diag_event(id)) {
2703  			WMI_DIAG_RX_EVENT_RECORD(wmi_handle, id,
2704  				((uint8_t *) data +
2705  				wmi_handle->soc->buf_offset_event));
2706  		} else if (wmi_handle->ops->is_management_record(id)) {
2707  			WMI_MGMT_RX_EVENT_RECORD(wmi_handle, id,
2708  				((uint8_t *) data +
2709  				wmi_handle->soc->buf_offset_event));
2710  		} else {
2711  			WMI_RX_EVENT_RECORD(wmi_handle, id, ((uint8_t *) data +
2712  				wmi_handle->soc->buf_offset_event));
2713  		}
2714  		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
2715  	}
2716  #endif
2717  
2718  	if (exec_ctx == WMI_RX_WORK_CTX) {
2719  		wmi_process_fw_event_worker_thread_ctx(wmi_handle, evt_buf);
2720  	} else if (exec_ctx == WMI_RX_TASKLET_CTX) {
2721  		wmi_process_fw_event(wmi_handle, evt_buf);
2722  	} else if (exec_ctx == WMI_RX_SERIALIZER_CTX) {
2723  		wmi_process_fw_event_sched_thread_ctx(wmi_handle, evt_buf);
2724  	} else if (exec_ctx == WMI_RX_DIAG_WORK_CTX) {
2725  		wmi_process_rx_diag_event_worker_thread_ctx(wmi_handle,
2726  							    evt_buf);
2727  	} else {
2728  		wmi_err("Invalid event context %d", exec_ctx);
2729  		wmi_rx_nbuf_free(evt_buf);
2730  	}
2731  
2732  }
2733  
2734  /**
2735   * wmi_control_rx() - process fw events callbacks
2736   * @ctx: handle to wmi
2737   * @htc_packet: pointer to htc packet
2738   *
2739   * Return: none
2740   */
wmi_control_rx(void * ctx,HTC_PACKET * htc_packet)2741  static void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet)
2742  {
2743  	struct wmi_soc *soc = (struct wmi_soc *)ctx;
2744  	struct wmi_unified *wmi_handle;
2745  	wmi_buf_t evt_buf;
2746  
2747  	evt_buf = (wmi_buf_t)htc_packet->pPktContext;
2748  
2749  	wmi_handle = wmi_get_pdev_ep(soc, htc_packet->Endpoint);
2750  	if (!wmi_handle) {
2751  		wmi_err("unable to get wmi_handle to Endpoint %d",
2752  			htc_packet->Endpoint);
2753  		wmi_rx_nbuf_free(evt_buf);
2754  		return;
2755  	}
2756  
2757  	wmi_process_control_rx(wmi_handle, evt_buf);
2758  }
2759  
2760  #if defined(WLAN_FEATURE_WMI_DIAG_OVER_CE7) || \
2761  	defined(WLAN_DIAG_AND_DBR_OVER_SEPARATE_CE)
2762  /**
2763   * wmi_control_diag_rx() - process diag fw events callbacks
2764   * @ctx: handle to wmi
2765   * @htc_packet: pointer to htc packet
2766   *
2767   * Return: none
2768   */
wmi_control_diag_rx(void * ctx,HTC_PACKET * htc_packet)2769  static void wmi_control_diag_rx(void *ctx, HTC_PACKET *htc_packet)
2770  {
2771  	struct wmi_soc *soc = (struct wmi_soc *)ctx;
2772  	struct wmi_unified *wmi_handle;
2773  	wmi_buf_t evt_buf;
2774  
2775  	evt_buf = (wmi_buf_t)htc_packet->pPktContext;
2776  
2777  	wmi_handle = soc->wmi_pdev[0];
2778  
2779  	if (!wmi_handle) {
2780  		wmi_err("unable to get wmi_handle for diag event end point id:%d", htc_packet->Endpoint);
2781  		wmi_rx_nbuf_free(evt_buf);
2782  		return;
2783  	}
2784  
2785  	wmi_process_control_rx(wmi_handle, evt_buf);
2786  }
2787  #endif
2788  
2789  #if defined(WLAN_DIAG_AND_DBR_OVER_SEPARATE_CE)
2790  /**
2791   * wmi_control_dbr_rx() - process dbr fw events callbacks
2792   * @ctx: handle to wmi
2793   * @htc_packet: pointer to htc packet
2794   *
2795   * Return: none
2796   */
wmi_control_dbr_rx(void * ctx,HTC_PACKET * htc_packet)2797  static void wmi_control_dbr_rx(void *ctx, HTC_PACKET *htc_packet)
2798  {
2799  	struct wmi_soc *soc = (struct wmi_soc *)ctx;
2800  	struct wmi_unified *wmi_handle;
2801  	wmi_buf_t evt_buf;
2802  
2803  	evt_buf = (wmi_buf_t)htc_packet->pPktContext;
2804  	wmi_handle = soc->wmi_pdev[0];
2805  
2806  	if (!wmi_handle) {
2807  		wmi_err("unable to get wmi_handle for dbr event endpoint id:%d",
2808  			htc_packet->Endpoint);
2809  		wmi_rx_nbuf_free(evt_buf);
2810  		return;
2811  	}
2812  
2813  	wmi_process_control_rx(wmi_handle, evt_buf);
2814  }
2815  #endif
2816  
2817  #ifdef WLAN_FEATURE_WMI_SEND_RECV_QMI
wmi_unified_cmd_send_over_qmi(struct wmi_unified * wmi_handle,wmi_buf_t buf,uint32_t buflen,uint32_t cmd_id)2818  QDF_STATUS wmi_unified_cmd_send_over_qmi(struct wmi_unified *wmi_handle,
2819  					 wmi_buf_t buf, uint32_t buflen,
2820  					 uint32_t cmd_id)
2821  {
2822  	QDF_STATUS status;
2823  	int32_t ret;
2824  
2825  	if (!qdf_nbuf_push_head(buf, sizeof(WMI_CMD_HDR))) {
2826  		wmi_err("Failed to send cmd %x, no memory", cmd_id);
2827  		return QDF_STATUS_E_NOMEM;
2828  	}
2829  
2830  	qdf_mem_zero(qdf_nbuf_data(buf), sizeof(WMI_CMD_HDR));
2831  	WMI_SET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id);
2832  	wmi_debug("Sending WMI_CMD_ID: 0x%x over qmi", cmd_id);
2833  	status = qdf_wmi_send_recv_qmi(qdf_nbuf_data(buf),
2834  				       buflen + sizeof(WMI_CMD_HDR),
2835  				       wmi_handle,
2836  				       wmi_process_qmi_fw_event);
2837  	if (QDF_IS_STATUS_ERROR(status)) {
2838  		qdf_nbuf_pull_head(buf, sizeof(WMI_CMD_HDR));
2839  		wmi_warn("WMI send on QMI failed. Retrying WMI on HTC");
2840  	} else {
2841  		ret = qdf_atomic_inc_return(&wmi_handle->num_stats_over_qmi);
2842  		wmi_debug("num stats over qmi: %d", ret);
2843  		wmi_buf_free(buf);
2844  	}
2845  
2846  	return status;
2847  }
2848  
__wmi_process_qmi_fw_event(void * wmi_cb_ctx,void * buf,int len)2849  static int __wmi_process_qmi_fw_event(void *wmi_cb_ctx, void *buf, int len)
2850  {
2851  	struct wmi_unified *wmi_handle = wmi_cb_ctx;
2852  	wmi_buf_t evt_buf;
2853  	uint32_t evt_id;
2854  
2855  	if (!wmi_handle || !buf || !len) {
2856  		wmi_err_rl("%s is invalid", !wmi_handle ?
2857  				"wmi_buf" : !buf ? "buf" : "length");
2858  		return -EINVAL;
2859  	}
2860  
2861  	evt_buf = wmi_buf_alloc(wmi_handle, len);
2862  	if (!evt_buf)
2863  		return -ENOMEM;
2864  
2865  	qdf_mem_copy(qdf_nbuf_data(evt_buf), buf, len);
2866  	evt_id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
2867  	wmi_debug("Received WMI_EVT_ID: 0x%x over qmi", evt_id);
2868  	wmi_process_control_rx(wmi_handle, evt_buf);
2869  
2870  	return 0;
2871  }
2872  
wmi_process_qmi_fw_event(void * wmi_cb_ctx,void * buf,int len)2873  int wmi_process_qmi_fw_event(void *wmi_cb_ctx, void *buf, int len)
2874  {
2875  	struct qdf_op_sync *op_sync;
2876  	int ret;
2877  
2878  	if (qdf_op_protect(&op_sync))
2879  		return -EINVAL;
2880  	ret = __wmi_process_qmi_fw_event(wmi_cb_ctx, buf, len);
2881  	qdf_op_unprotect(op_sync);
2882  
2883  	return ret;
2884  }
2885  #endif
2886  
wmi_process_fw_event(struct wmi_unified * wmi_handle,wmi_buf_t evt_buf)2887  void wmi_process_fw_event(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf)
2888  {
2889  	__wmi_control_rx(wmi_handle, evt_buf);
2890  }
2891  
__wmi_control_rx(struct wmi_unified * wmi_handle,wmi_buf_t evt_buf)2892  void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf)
2893  {
2894  	uint32_t id;
2895  	uint8_t *data;
2896  	uint32_t len;
2897  	void *wmi_cmd_struct_ptr = NULL;
2898  #ifndef WMI_NON_TLV_SUPPORT
2899  	int tlv_ok_status = 0;
2900  #endif
2901  	uint32_t idx = 0;
2902  	struct wmi_raw_event_buffer ev_buf;
2903  	enum wmi_rx_buff_type ev_buff_type;
2904  
2905  	id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
2906  
2907  	wmi_ext_dbg_msg_event_record(wmi_handle, qdf_nbuf_data(evt_buf),
2908  				     qdf_nbuf_len(evt_buf));
2909  
2910  	if (qdf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
2911  		goto end;
2912  
2913  	data = qdf_nbuf_data(evt_buf);
2914  	len = qdf_nbuf_len(evt_buf);
2915  
2916  #ifndef WMI_NON_TLV_SUPPORT
2917  	if (wmi_handle->target_type == WMI_TLV_TARGET) {
2918  		/* Validate and pad(if necessary) the TLVs */
2919  		tlv_ok_status =
2920  			wmi_handle->ops->wmi_check_and_pad_event(wmi_handle->scn_handle,
2921  							data, len, id,
2922  							&wmi_cmd_struct_ptr);
2923  		if (tlv_ok_status != 0) {
2924  			QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
2925  				  "%s: Error: id=0x%x, wmitlv check status=%d",
2926  				  __func__, id, tlv_ok_status);
2927  			goto end;
2928  		}
2929  	}
2930  #endif
2931  
2932  	idx = wmi_unified_get_event_handler_ix(wmi_handle, id);
2933  	if (idx == A_ERROR) {
2934  		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
2935  		   "%s : event handler is not registered: event id 0x%x",
2936  			__func__, id);
2937  		goto end;
2938  	}
2939  #ifdef WMI_INTERFACE_EVENT_LOGGING
2940  	if (wmi_handle->log_info.wmi_logging_enable) {
2941  		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
2942  		/* Exclude 4 bytes of TLV header */
2943  		if (wmi_handle->ops->is_diag_event(id)) {
2944  			/*
2945  			 * skip diag event logging in WMI event buffer
2946  			 * as its already logged in WMI RX event buffer
2947  			 */
2948  		} else if (wmi_handle->ops->is_management_record(id)) {
2949  			/*
2950  			 * skip wmi mgmt event logging in WMI event buffer
2951  			 * as its already logged in WMI RX event buffer
2952  			 */
2953  		} else {
2954  			uint8_t *tmpbuf = (uint8_t *)data +
2955  					wmi_handle->soc->buf_offset_event;
2956  
2957  			WMI_EVENT_RECORD(wmi_handle, id, tmpbuf);
2958  			wmi_specific_evt_record(wmi_handle, id, tmpbuf);
2959  		}
2960  		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
2961  	}
2962  #endif
2963  	/* Call the WMI registered event handler */
2964  	if (wmi_handle->target_type == WMI_TLV_TARGET) {
2965  		ev_buff_type = wmi_handle->ctx[idx].buff_type;
2966  		if (ev_buff_type == WMI_RX_PROCESSED_BUFF) {
2967  			if (qdf_likely(wmi_handle->event_handler[idx]))
2968  				wmi_handle->event_handler[idx] (wmi_handle->scn_handle,
2969  								wmi_cmd_struct_ptr, len);
2970  		} else if (ev_buff_type == WMI_RX_RAW_BUFF) {
2971  			ev_buf.evt_raw_buf = data;
2972  			ev_buf.evt_processed_buf = wmi_cmd_struct_ptr;
2973  			wmi_handle->event_handler[idx] (wmi_handle->scn_handle,
2974  							(void *)&ev_buf, len);
2975  		}
2976  	}
2977  	else
2978  		wmi_handle->event_handler[idx] (wmi_handle->scn_handle,
2979  			data, len);
2980  
2981  end:
2982  	/* Free event buffer and allocated event tlv */
2983  #ifndef WMI_NON_TLV_SUPPORT
2984  	if (wmi_handle->target_type == WMI_TLV_TARGET)
2985  		wmi_handle->ops->wmi_free_allocated_event(id, &wmi_cmd_struct_ptr);
2986  #endif
2987  
2988  	wmi_rx_nbuf_free(evt_buf);
2989  
2990  }
2991  
2992  #define WMI_WQ_WD_TIMEOUT (30 * 1000) /* 30s */
2993  
wmi_workqueue_watchdog_warn(uint32_t msg_type_id)2994  static inline void wmi_workqueue_watchdog_warn(uint32_t msg_type_id)
2995  {
2996  	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2997  		  "%s: WLAN_BUG_RCA: Message type %x has exceeded its allotted time of %ds",
2998  		  __func__, msg_type_id, WMI_WQ_WD_TIMEOUT / 1000);
2999  }
3000  
3001  #ifdef CONFIG_SLUB_DEBUG_ON
wmi_workqueue_watchdog_bite(void * arg)3002  static void wmi_workqueue_watchdog_bite(void *arg)
3003  {
3004  	struct wmi_wq_dbg_info *info = arg;
3005  
3006  	wmi_workqueue_watchdog_warn(info->wd_msg_type_id);
3007  	qdf_print_thread_trace(info->task);
3008  
3009  	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
3010  		  "%s: Going down for WMI WQ Watchdog Bite!", __func__);
3011  	QDF_BUG(0);
3012  }
3013  #else
wmi_workqueue_watchdog_bite(void * arg)3014  static inline void wmi_workqueue_watchdog_bite(void *arg)
3015  {
3016  	struct wmi_wq_dbg_info *info = arg;
3017  
3018  	wmi_workqueue_watchdog_warn(info->wd_msg_type_id);
3019  
3020  	qdf_print_thread_trace(info->task);
3021  }
3022  #endif
3023  
3024  /**
3025   * wmi_rx_event_work() - process rx event in rx work queue context
3026   * @arg: opaque pointer to wmi handle
3027   *
3028   * This function process any fw event to serialize it through rx worker thread.
3029   *
3030   * Return: none
3031   */
wmi_rx_event_work(void * arg)3032  static void wmi_rx_event_work(void *arg)
3033  {
3034  	wmi_buf_t buf;
3035  	struct wmi_unified *wmi = arg;
3036  	qdf_timer_t wd_timer;
3037  	struct wmi_wq_dbg_info info;
3038  
3039  	/* initialize WMI workqueue watchdog timer */
3040  	qdf_timer_init(NULL, &wd_timer, &wmi_workqueue_watchdog_bite,
3041  			&info, QDF_TIMER_TYPE_SW);
3042  	qdf_spin_lock_bh(&wmi->eventq_lock);
3043  	buf = qdf_nbuf_queue_remove(&wmi->event_queue);
3044  	qdf_spin_unlock_bh(&wmi->eventq_lock);
3045  	while (buf) {
3046  		qdf_timer_start(&wd_timer, WMI_WQ_WD_TIMEOUT);
3047  		info.wd_msg_type_id =
3048  		   WMI_GET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID);
3049  		info.wmi_wq = wmi->wmi_rx_work_queue;
3050  		info.task = qdf_get_current_task();
3051  		__wmi_control_rx(wmi, buf);
3052  		qdf_timer_stop(&wd_timer);
3053  		qdf_spin_lock_bh(&wmi->eventq_lock);
3054  		buf = qdf_nbuf_queue_remove(&wmi->event_queue);
3055  		qdf_spin_unlock_bh(&wmi->eventq_lock);
3056  	}
3057  	qdf_timer_free(&wd_timer);
3058  }
3059  
3060  /**
3061   * wmi_rx_diag_event_work() - process rx diag event in work queue context
3062   * @arg: opaque pointer to wmi handle
3063   *
3064   * This function process fw diag event to serialize it through rx worker thread.
3065   *
3066   * Return: none
3067   */
wmi_rx_diag_event_work(void * arg)3068  static void wmi_rx_diag_event_work(void *arg)
3069  {
3070  	wmi_buf_t buf;
3071  	struct wmi_unified *wmi = arg;
3072  	qdf_timer_t wd_timer;
3073  	struct wmi_wq_dbg_info info;
3074  	uint32_t diag_event_process_count = 0;
3075  
3076  	if (!wmi) {
3077  		wmi_err("Invalid WMI handle");
3078  		return;
3079  	}
3080  
3081  	/* initialize WMI workqueue watchdog timer */
3082  	qdf_timer_init(NULL, &wd_timer, &wmi_workqueue_watchdog_bite,
3083  		       &info, QDF_TIMER_TYPE_SW);
3084  	qdf_spin_lock_bh(&wmi->diag_eventq_lock);
3085  	buf = qdf_nbuf_queue_remove(&wmi->diag_event_queue);
3086  	qdf_spin_unlock_bh(&wmi->diag_eventq_lock);
3087  	while (buf) {
3088  		qdf_timer_start(&wd_timer, WMI_WQ_WD_TIMEOUT);
3089  		info.wd_msg_type_id =
3090  		   WMI_GET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID);
3091  		info.wmi_wq = NULL;
3092  		info.task = qdf_get_current_task();
3093  		__wmi_control_rx(wmi, buf);
3094  		qdf_timer_stop(&wd_timer);
3095  
3096  		if (diag_event_process_count++ >
3097  		    RX_DIAG_EVENT_WORK_PROCESS_MAX_COUNT) {
3098  			qdf_queue_work(0, wmi->wmi_rx_diag_work_queue,
3099  				       &wmi->rx_diag_event_work);
3100  			break;
3101  		}
3102  
3103  		qdf_spin_lock_bh(&wmi->diag_eventq_lock);
3104  		buf = qdf_nbuf_queue_remove(&wmi->diag_event_queue);
3105  		qdf_spin_unlock_bh(&wmi->diag_eventq_lock);
3106  	}
3107  	qdf_timer_free(&wd_timer);
3108  }
3109  
3110  #ifdef FEATURE_RUNTIME_PM
3111  /**
3112   * wmi_runtime_pm_init() - initialize runtime pm wmi variables
3113   * @wmi_handle: wmi context
3114   */
wmi_runtime_pm_init(struct wmi_unified * wmi_handle)3115  static void wmi_runtime_pm_init(struct wmi_unified *wmi_handle)
3116  {
3117  	qdf_atomic_init(&wmi_handle->runtime_pm_inprogress);
3118  }
3119  
wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle,A_BOOL val)3120  void wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, A_BOOL val)
3121  {
3122  	qdf_atomic_set(&wmi_handle->runtime_pm_inprogress, val);
3123  }
3124  
wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle)3125  bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle)
3126  {
3127  	return qdf_atomic_read(&wmi_handle->runtime_pm_inprogress);
3128  }
3129  #else
wmi_runtime_pm_init(struct wmi_unified * wmi_handle)3130  static void wmi_runtime_pm_init(struct wmi_unified *wmi_handle)
3131  {
3132  }
3133  #endif
3134  
wmi_set_wow_enable_ack_failed(wmi_unified_t wmi_handle)3135  void wmi_set_wow_enable_ack_failed(wmi_unified_t wmi_handle)
3136  {
3137  	qdf_atomic_set(&wmi_handle->is_wow_enable_ack_failed, 1);
3138  }
3139  
wmi_clear_wow_enable_ack_failed(wmi_unified_t wmi_handle)3140  void wmi_clear_wow_enable_ack_failed(wmi_unified_t wmi_handle)
3141  {
3142  	qdf_atomic_set(&wmi_handle->is_wow_enable_ack_failed, 0);
3143  }
3144  
wmi_has_wow_enable_ack_failed(wmi_unified_t wmi_handle)3145  bool wmi_has_wow_enable_ack_failed(wmi_unified_t wmi_handle)
3146  {
3147  	return qdf_atomic_read(&wmi_handle->is_wow_enable_ack_failed);
3148  }
3149  
wmi_unified_get_soc_handle(struct wmi_unified * wmi_handle)3150  void *wmi_unified_get_soc_handle(struct wmi_unified *wmi_handle)
3151  {
3152  	return wmi_handle->soc;
3153  }
3154  
3155  /**
3156   * wmi_interface_logging_init: Interface looging init
3157   * @wmi_handle: Pointer to wmi handle object
3158   * @pdev_idx: pdev index
3159   *
3160   * Return: None
3161   */
3162  #ifdef WMI_INTERFACE_EVENT_LOGGING
wmi_interface_logging_init(struct wmi_unified * wmi_handle,uint32_t pdev_idx)3163  static inline void wmi_interface_logging_init(struct wmi_unified *wmi_handle,
3164  					      uint32_t pdev_idx)
3165  {
3166  	if (QDF_STATUS_SUCCESS == wmi_log_init(wmi_handle)) {
3167  		qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock);
3168  		wmi_debugfs_init(wmi_handle, pdev_idx);
3169  	}
3170  }
3171  #else
wmi_interface_logging_init(struct wmi_unified * wmi_handle,uint32_t pdev_idx)3172  static inline void wmi_interface_logging_init(struct wmi_unified *wmi_handle,
3173  					      uint32_t pdev_idx)
3174  {
3175  }
3176  #endif
3177  
wmi_initialize_worker_context(struct wmi_unified * wmi_handle)3178  static QDF_STATUS wmi_initialize_worker_context(struct wmi_unified *wmi_handle)
3179  {
3180  	wmi_handle->wmi_rx_work_queue =
3181  		qdf_alloc_unbound_workqueue("wmi_rx_event_work_queue");
3182  	if (!wmi_handle->wmi_rx_work_queue) {
3183  		wmi_err("failed to create wmi_rx_event_work_queue");
3184  		return QDF_STATUS_E_RESOURCES;
3185  	}
3186  
3187  	qdf_spinlock_create(&wmi_handle->eventq_lock);
3188  	qdf_nbuf_queue_init(&wmi_handle->event_queue);
3189  	qdf_create_work(0, &wmi_handle->rx_event_work,
3190  			wmi_rx_event_work, wmi_handle);
3191  
3192  	wmi_handle->wmi_rx_diag_work_queue =
3193  		qdf_alloc_unbound_workqueue("wmi_rx_diag_event_work_queue");
3194  	if (!wmi_handle->wmi_rx_diag_work_queue) {
3195  		wmi_err("failed to create wmi_rx_diag_event_work_queue");
3196  		return QDF_STATUS_E_RESOURCES;
3197  	}
3198  	qdf_spinlock_create(&wmi_handle->diag_eventq_lock);
3199  	qdf_nbuf_queue_init(&wmi_handle->diag_event_queue);
3200  	qdf_create_work(0, &wmi_handle->rx_diag_event_work,
3201  			wmi_rx_diag_event_work, wmi_handle);
3202  	wmi_handle->wmi_rx_diag_events_dropped = 0;
3203  
3204  	return QDF_STATUS_SUCCESS;
3205  }
3206  
wmi_unified_get_pdev_handle(struct wmi_soc * soc,uint32_t pdev_idx)3207  void *wmi_unified_get_pdev_handle(struct wmi_soc *soc, uint32_t pdev_idx)
3208  {
3209  	struct wmi_unified *wmi_handle;
3210  	QDF_STATUS status;
3211  
3212  	if (pdev_idx >= WMI_MAX_RADIOS)
3213  		return NULL;
3214  
3215  	if (!soc->wmi_pdev[pdev_idx]) {
3216  		wmi_handle =
3217  			(struct wmi_unified *) qdf_mem_malloc(
3218  					sizeof(struct wmi_unified));
3219  		if (!wmi_handle)
3220  			return NULL;
3221  
3222  		status = wmi_initialize_worker_context(wmi_handle);
3223  		if (QDF_IS_STATUS_ERROR(status))
3224  			goto error;
3225  
3226  		wmi_handle->scn_handle = soc->scn_handle;
3227  		wmi_handle->event_id = soc->event_id;
3228  		wmi_handle->event_handler = soc->event_handler;
3229  		wmi_handle->ctx = soc->ctx;
3230  		wmi_handle->ops = soc->ops;
3231  		wmi_handle->wmi_events = soc->wmi_events;
3232  		wmi_handle->services = soc->services;
3233  		wmi_handle->soc = soc;
3234  		wmi_handle->cmd_pdev_id_map = soc->cmd_pdev_id_map;
3235  		wmi_handle->evt_pdev_id_map = soc->evt_pdev_id_map;
3236  		wmi_handle->cmd_phy_id_map = soc->cmd_phy_id_map;
3237  		wmi_handle->evt_phy_id_map = soc->evt_phy_id_map;
3238  		wmi_interface_logging_init(wmi_handle, pdev_idx);
3239  		qdf_atomic_init(&wmi_handle->is_target_suspended);
3240  		qdf_atomic_init(&wmi_handle->is_wow_enable_ack_failed);
3241  		wmi_handle->target_type = soc->target_type;
3242  		wmi_handle->wmi_max_cmds = soc->wmi_max_cmds;
3243  
3244  		wmi_interface_sequence_init(wmi_handle);
3245  		if (wmi_ext_dbgfs_init(wmi_handle, pdev_idx) !=
3246  		    QDF_STATUS_SUCCESS)
3247  			wmi_err("Failed to initialize wmi extended debugfs");
3248  
3249  		soc->wmi_pdev[pdev_idx] = wmi_handle;
3250  	} else
3251  		wmi_handle = soc->wmi_pdev[pdev_idx];
3252  
3253  	qdf_atomic_init(&wmi_handle->pending_cmds);
3254  	wmi_handle->wmi_stopinprogress = 0;
3255  	wmi_handle->wmi_endpoint_id = soc->wmi_endpoint_id[pdev_idx];
3256  	wmi_handle->htc_handle = soc->htc_handle;
3257  	wmi_handle->max_msg_len = soc->max_msg_len[pdev_idx];
3258  	wmi_handle->tag_crash_inject = false;
3259  	wmi_interface_sequence_reset(wmi_handle);
3260  
3261  	return wmi_handle;
3262  
3263  error:
3264  	qdf_mem_free(wmi_handle);
3265  
3266  	return NULL;
3267  }
3268  qdf_export_symbol(wmi_unified_get_pdev_handle);
3269  
3270  static void (*wmi_attach_register[WMI_MAX_TARGET_TYPE])(wmi_unified_t);
3271  
wmi_unified_register_module(enum wmi_target_type target_type,void (* wmi_attach)(wmi_unified_t wmi_handle))3272  void wmi_unified_register_module(enum wmi_target_type target_type,
3273  			void (*wmi_attach)(wmi_unified_t wmi_handle))
3274  {
3275  	if (target_type < WMI_MAX_TARGET_TYPE)
3276  		wmi_attach_register[target_type] = wmi_attach;
3277  
3278  	return;
3279  }
3280  qdf_export_symbol(wmi_unified_register_module);
3281  
3282  /**
3283   * wmi_wbuff_register() - register wmi with wbuff
3284   * @wmi_handle: handle to wmi
3285   *
3286   * Return: void
3287   */
wmi_wbuff_register(struct wmi_unified * wmi_handle)3288  static void wmi_wbuff_register(struct wmi_unified *wmi_handle)
3289  {
3290  	struct wbuff_alloc_request wbuff_alloc[4];
3291  	uint8_t reserve = WMI_MIN_HEAD_ROOM;
3292  
3293  	wbuff_alloc[0].pool_id = 0;
3294  	wbuff_alloc[0].pool_size = WMI_WBUFF_POOL_0_SIZE;
3295  	wbuff_alloc[0].buffer_size = roundup(WMI_WBUFF_LEN_POOL0 + reserve, 4);
3296  
3297  	wbuff_alloc[1].pool_id = 1;
3298  	wbuff_alloc[1].pool_size = WMI_WBUFF_POOL_1_SIZE;
3299  	wbuff_alloc[1].buffer_size = roundup(WMI_WBUFF_LEN_POOL1 + reserve, 4);
3300  
3301  	wbuff_alloc[2].pool_id = 2;
3302  	wbuff_alloc[2].pool_size = WMI_WBUFF_POOL_2_SIZE;
3303  	wbuff_alloc[2].buffer_size = roundup(WMI_WBUFF_LEN_POOL2 + reserve, 4);
3304  
3305  	wbuff_alloc[3].pool_id = 3;
3306  	wbuff_alloc[3].pool_size = WMI_WBUFF_POOL_3_SIZE;
3307  	wbuff_alloc[3].buffer_size = roundup(WMI_WBUFF_LEN_POOL3 + reserve, 4);
3308  
3309  	wmi_handle->wbuff_handle =
3310  		wbuff_module_register(wbuff_alloc, QDF_ARRAY_SIZE(wbuff_alloc),
3311  				      reserve, 4, WBUFF_MODULE_WMI_TX);
3312  }
3313  
3314  /**
3315   * wmi_wbuff_deregister() - deregister wmi with wbuff
3316   * @wmi_handle: handle to wmi
3317   *
3318   * Return: void
3319   */
wmi_wbuff_deregister(struct wmi_unified * wmi_handle)3320  static inline void wmi_wbuff_deregister(struct wmi_unified *wmi_handle)
3321  {
3322  	wbuff_module_deregister(wmi_handle->wbuff_handle);
3323  	wmi_handle->wbuff_handle = NULL;
3324  }
3325  
wmi_unified_attach(void * scn_handle,struct wmi_unified_attach_params * param)3326  void *wmi_unified_attach(void *scn_handle,
3327  			 struct wmi_unified_attach_params *param)
3328  {
3329  	struct wmi_unified *wmi_handle;
3330  	struct wmi_soc *soc;
3331  	QDF_STATUS status;
3332  
3333  	soc = (struct wmi_soc *) qdf_mem_malloc(sizeof(struct wmi_soc));
3334  	if (!soc)
3335  		return NULL;
3336  
3337  	wmi_handle =
3338  		(struct wmi_unified *) qdf_mem_malloc(
3339  			sizeof(struct wmi_unified));
3340  	if (!wmi_handle) {
3341  		qdf_mem_free(soc);
3342  		return NULL;
3343  	}
3344  
3345  	status = wmi_initialize_worker_context(wmi_handle);
3346  	if (QDF_IS_STATUS_ERROR(status))
3347  		goto error;
3348  
3349  	wmi_handle->soc = soc;
3350  	wmi_handle->soc->soc_idx = param->soc_id;
3351  	wmi_handle->soc->is_async_ep = param->is_async_ep;
3352  	wmi_handle->event_id = soc->event_id;
3353  	wmi_handle->event_handler = soc->event_handler;
3354  	wmi_handle->ctx = soc->ctx;
3355  	wmi_handle->wmi_events = soc->wmi_events;
3356  	wmi_handle->services = soc->services;
3357  	wmi_handle->scn_handle = scn_handle;
3358  	wmi_handle->cmd_pdev_id_map = soc->cmd_pdev_id_map;
3359  	wmi_handle->evt_pdev_id_map = soc->evt_pdev_id_map;
3360  	wmi_handle->cmd_phy_id_map = soc->cmd_phy_id_map;
3361  	wmi_handle->evt_phy_id_map = soc->evt_phy_id_map;
3362  	soc->scn_handle = scn_handle;
3363  	wmi_handle->target_type = param->target_type;
3364  	soc->target_type = param->target_type;
3365  
3366  	if (param->target_type >= WMI_MAX_TARGET_TYPE)
3367  		goto error;
3368  
3369  	if (wmi_attach_register[param->target_type]) {
3370  		wmi_attach_register[param->target_type](wmi_handle);
3371  	} else {
3372  		wmi_err("wmi attach is not registered");
3373  		goto error;
3374  	}
3375  
3376  	qdf_atomic_init(&wmi_handle->pending_cmds);
3377  	qdf_atomic_init(&wmi_handle->is_target_suspended);
3378  	qdf_atomic_init(&wmi_handle->is_target_suspend_acked);
3379  	qdf_atomic_init(&wmi_handle->num_stats_over_qmi);
3380  	qdf_atomic_init(&wmi_handle->is_wow_enable_ack_failed);
3381  	wmi_runtime_pm_init(wmi_handle);
3382  	wmi_interface_logging_init(wmi_handle, WMI_HOST_PDEV_ID_0);
3383  
3384  	wmi_interface_sequence_init(wmi_handle);
3385  	/* Assign target cookie capability */
3386  	wmi_handle->use_cookie = param->use_cookie;
3387  	wmi_handle->osdev = param->osdev;
3388  	wmi_handle->wmi_stopinprogress = 0;
3389  	wmi_handle->wmi_max_cmds = param->max_commands;
3390  	soc->wmi_max_cmds = param->max_commands;
3391  	/* Increase the ref count once refcount infra is present */
3392  	soc->wmi_psoc = param->psoc;
3393  	qdf_spinlock_create(&soc->ctx_lock);
3394  	soc->ops = wmi_handle->ops;
3395  	soc->wmi_pdev[0] = wmi_handle;
3396  	if (wmi_ext_dbgfs_init(wmi_handle, 0) != QDF_STATUS_SUCCESS)
3397  		wmi_err("Failed to initialize wmi extended debugfs");
3398  
3399  	wmi_wbuff_register(wmi_handle);
3400  
3401  	wmi_hang_event_notifier_register(wmi_handle);
3402  
3403  	wmi_minidump_attach(wmi_handle);
3404  
3405  	return wmi_handle;
3406  
3407  error:
3408  	qdf_mem_free(soc);
3409  	qdf_mem_free(wmi_handle);
3410  
3411  	return NULL;
3412  }
3413  
wmi_unified_detach(struct wmi_unified * wmi_handle)3414  void wmi_unified_detach(struct wmi_unified *wmi_handle)
3415  {
3416  	wmi_buf_t buf;
3417  	struct wmi_soc *soc;
3418  	uint8_t i;
3419  
3420  	wmi_minidump_detach(wmi_handle);
3421  
3422  	wmi_hang_event_notifier_unregister();
3423  
3424  	wmi_wbuff_deregister(wmi_handle);
3425  
3426  	soc = wmi_handle->soc;
3427  	for (i = 0; i < WMI_MAX_RADIOS; i++) {
3428  		if (soc->wmi_pdev[i]) {
3429  			qdf_flush_workqueue(0,
3430  				soc->wmi_pdev[i]->wmi_rx_work_queue);
3431  			qdf_destroy_workqueue(0,
3432  				soc->wmi_pdev[i]->wmi_rx_work_queue);
3433  			wmi_debugfs_remove(soc->wmi_pdev[i]);
3434  			buf = qdf_nbuf_queue_remove(
3435  					&soc->wmi_pdev[i]->event_queue);
3436  			while (buf) {
3437  				qdf_nbuf_free(buf);
3438  				buf = qdf_nbuf_queue_remove(
3439  						&soc->wmi_pdev[i]->event_queue);
3440  			}
3441  
3442  			qdf_flush_workqueue(0,
3443  				soc->wmi_pdev[i]->wmi_rx_diag_work_queue);
3444  			qdf_destroy_workqueue(0,
3445  				soc->wmi_pdev[i]->wmi_rx_diag_work_queue);
3446  			buf = qdf_nbuf_queue_remove(
3447  					&soc->wmi_pdev[i]->diag_event_queue);
3448  			while (buf) {
3449  				qdf_nbuf_free(buf);
3450  				buf = qdf_nbuf_queue_remove(
3451  					&soc->wmi_pdev[i]->diag_event_queue);
3452  			}
3453  
3454  			wmi_log_buffer_free(soc->wmi_pdev[i]);
3455  
3456  			/* Free events logs list */
3457  			if (soc->wmi_pdev[i]->events_logs_list)
3458  				qdf_mem_free(
3459  					soc->wmi_pdev[i]->events_logs_list);
3460  
3461  			qdf_spinlock_destroy(&soc->wmi_pdev[i]->eventq_lock);
3462  			qdf_spinlock_destroy(
3463  					&soc->wmi_pdev[i]->diag_eventq_lock);
3464  
3465  			wmi_interface_sequence_deinit(soc->wmi_pdev[i]);
3466  			wmi_ext_dbgfs_deinit(soc->wmi_pdev[i]);
3467  			wmi_clear_wow_enable_ack_failed(soc->wmi_pdev[i]);
3468  
3469  			qdf_mem_free(soc->wmi_pdev[i]);
3470  		}
3471  	}
3472  	qdf_spinlock_destroy(&soc->ctx_lock);
3473  
3474  	if (soc->wmi_service_bitmap) {
3475  		qdf_mem_free(soc->wmi_service_bitmap);
3476  		soc->wmi_service_bitmap = NULL;
3477  	}
3478  
3479  	if (soc->wmi_ext_service_bitmap) {
3480  		qdf_mem_free(soc->wmi_ext_service_bitmap);
3481  		soc->wmi_ext_service_bitmap = NULL;
3482  	}
3483  
3484  	if (soc->wmi_ext2_service_bitmap) {
3485  		qdf_mem_free(soc->wmi_ext2_service_bitmap);
3486  		soc->wmi_ext2_service_bitmap = NULL;
3487  	}
3488  
3489  	/* Decrease the ref count once refcount infra is present */
3490  	soc->wmi_psoc = NULL;
3491  	qdf_mem_free(soc);
3492  }
3493  
3494  void
wmi_unified_remove_work(struct wmi_unified * wmi_handle)3495  wmi_unified_remove_work(struct wmi_unified *wmi_handle)
3496  {
3497  	wmi_buf_t buf;
3498  
3499  	qdf_flush_workqueue(0, wmi_handle->wmi_rx_work_queue);
3500  	qdf_spin_lock_bh(&wmi_handle->eventq_lock);
3501  	buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue);
3502  	while (buf) {
3503  		qdf_nbuf_free(buf);
3504  		buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue);
3505  	}
3506  	qdf_spin_unlock_bh(&wmi_handle->eventq_lock);
3507  
3508  	/* Remove diag events work */
3509  	qdf_flush_workqueue(0, wmi_handle->wmi_rx_diag_work_queue);
3510  	qdf_spin_lock_bh(&wmi_handle->diag_eventq_lock);
3511  	buf = qdf_nbuf_queue_remove(&wmi_handle->diag_event_queue);
3512  	while (buf) {
3513  		qdf_nbuf_free(buf);
3514  		buf = qdf_nbuf_queue_remove(&wmi_handle->diag_event_queue);
3515  	}
3516  	qdf_spin_unlock_bh(&wmi_handle->diag_eventq_lock);
3517  }
3518  
3519  /**
3520   * wmi_htc_tx_complete() - Process htc tx completion
3521   *
3522   * @ctx: handle to wmi
3523   * @htc_pkt: pointer to htc packet
3524   *
3525   * Return: none.
3526   */
wmi_htc_tx_complete(void * ctx,HTC_PACKET * htc_pkt)3527  static void wmi_htc_tx_complete(void *ctx, HTC_PACKET *htc_pkt)
3528  {
3529  	struct wmi_soc *soc = (struct wmi_soc *) ctx;
3530  	wmi_buf_t wmi_cmd_buf = GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt);
3531  	u_int8_t *buf_ptr;
3532  	u_int32_t len;
3533  	struct wmi_unified *wmi_handle;
3534  #ifdef WMI_INTERFACE_EVENT_LOGGING
3535  	struct wmi_debug_log_info *log_info;
3536  	uint32_t cmd_id;
3537  	uint8_t *offset_ptr;
3538  	qdf_dma_addr_t dma_addr;
3539  	uint64_t phy_addr;
3540  #endif
3541  
3542  	ASSERT(wmi_cmd_buf);
3543  	wmi_handle = wmi_get_pdev_ep(soc, htc_pkt->Endpoint);
3544  	if (!wmi_handle) {
3545  		wmi_err("Unable to get wmi handle");
3546  		QDF_ASSERT(0);
3547  		return;
3548  	}
3549  	buf_ptr = (u_int8_t *)wmi_buf_data(wmi_cmd_buf);
3550  #ifdef WMI_INTERFACE_EVENT_LOGGING
3551  	log_info = &wmi_handle->log_info;
3552  
3553  	if (wmi_handle && log_info->wmi_logging_enable) {
3554  		cmd_id = WMI_GET_FIELD(qdf_nbuf_data(wmi_cmd_buf),
3555  				WMI_CMD_HDR, COMMANDID);
3556  
3557  		dma_addr = QDF_NBUF_CB_PADDR(wmi_cmd_buf);
3558  		phy_addr = qdf_mem_virt_to_phys(qdf_nbuf_data(wmi_cmd_buf));
3559  
3560  		qdf_spin_lock_bh(&log_info->wmi_record_lock);
3561  		/* Record 16 bytes of WMI cmd tx complete data
3562  		 * - exclude TLV and WMI headers
3563  		 */
3564  		offset_ptr = buf_ptr + wmi_handle->soc->buf_offset_command;
3565  		if (wmi_handle->ops->is_management_record(cmd_id)) {
3566  			WMI_MGMT_COMMAND_TX_CMP_RECORD(wmi_handle, cmd_id,
3567  						       offset_ptr);
3568  		} else {
3569  			if (wmi_handle->ops->is_force_fw_hang_cmd(cmd_id)) {
3570  				wmi_info("Tx completion received for WMI_FORCE_FW_HANG_CMDID, current_time:%ld",
3571  					 qdf_mc_timer_get_system_time());
3572  			}
3573  
3574  			WMI_COMMAND_TX_CMP_RECORD(wmi_handle, cmd_id,
3575  						  offset_ptr, dma_addr,
3576  						  phy_addr);
3577  		}
3578  
3579  		qdf_spin_unlock_bh(&log_info->wmi_record_lock);
3580  	}
3581  #endif
3582  
3583  	wmi_interface_sequence_check(wmi_handle, wmi_cmd_buf);
3584  
3585  	len = qdf_nbuf_len(wmi_cmd_buf);
3586  	qdf_mem_zero(buf_ptr, len);
3587  	wmi_buf_free(wmi_cmd_buf);
3588  	qdf_mem_free(htc_pkt);
3589  	qdf_atomic_dec(&wmi_handle->pending_cmds);
3590  }
3591  
3592  #ifdef FEATURE_RUNTIME_PM
3593  /**
3594   * wmi_htc_log_pkt() - Print information of WMI command from HTC packet
3595   *
3596   * @ctx: handle of WMI context
3597   * @htc_pkt: handle of HTC packet
3598   *
3599   * Return: none
3600   */
wmi_htc_log_pkt(void * ctx,HTC_PACKET * htc_pkt)3601  static void wmi_htc_log_pkt(void *ctx, HTC_PACKET *htc_pkt)
3602  {
3603  	wmi_buf_t wmi_cmd_buf = GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt);
3604  	uint32_t cmd_id;
3605  
3606  	ASSERT(wmi_cmd_buf);
3607  	cmd_id = WMI_GET_FIELD(qdf_nbuf_data(wmi_cmd_buf), WMI_CMD_HDR,
3608  			       COMMANDID);
3609  
3610  	wmi_debug("WMI command from HTC packet: %s, ID: %d",
3611  		 wmi_id_to_name(cmd_id), cmd_id);
3612  }
3613  #else
wmi_htc_log_pkt(void * ctx,HTC_PACKET * htc_pkt)3614  static void wmi_htc_log_pkt(void *ctx, HTC_PACKET *htc_pkt)
3615  {
3616  }
3617  #endif
3618  
3619  /**
3620   * wmi_connect_pdev_htc_service() -  WMI API to get connect to HTC service
3621   * @soc: handle to WMI SoC
3622   * @pdev_idx: Pdev index
3623   *
3624   * Return: QDF_STATUS
3625   */
wmi_connect_pdev_htc_service(struct wmi_soc * soc,uint32_t pdev_idx)3626  static QDF_STATUS wmi_connect_pdev_htc_service(struct wmi_soc *soc,
3627  					       uint32_t pdev_idx)
3628  {
3629  	QDF_STATUS status;
3630  	struct htc_service_connect_resp response;
3631  	struct htc_service_connect_req connect;
3632  
3633  	OS_MEMZERO(&connect, sizeof(connect));
3634  	OS_MEMZERO(&response, sizeof(response));
3635  
3636  	/* meta data is unused for now */
3637  	connect.pMetaData = NULL;
3638  	connect.MetaDataLength = 0;
3639  	/* these fields are the same for all service endpoints */
3640  	connect.EpCallbacks.pContext = soc;
3641  	connect.EpCallbacks.EpTxCompleteMultiple =
3642  		NULL /* Control path completion ar6000_tx_complete */;
3643  	connect.EpCallbacks.EpRecv = wmi_control_rx /* Control path rx */;
3644  	connect.EpCallbacks.EpRecvRefill = NULL /* ar6000_rx_refill */;
3645  	connect.EpCallbacks.EpSendFull = NULL /* ar6000_tx_queue_full */;
3646  	connect.EpCallbacks.EpTxComplete =
3647  		wmi_htc_tx_complete /* ar6000_tx_queue_full */;
3648  	connect.EpCallbacks.ep_log_pkt = wmi_htc_log_pkt;
3649  
3650  	/* connect to control service */
3651  	connect.service_id = soc->svc_ids[pdev_idx];
3652  	status = htc_connect_service(soc->htc_handle, &connect, &response);
3653  
3654  	if (QDF_IS_STATUS_ERROR(status)) {
3655  		wmi_err("Failed to connect to WMI CONTROL service status:%d",
3656  			 status);
3657  		return status;
3658  	}
3659  
3660  	if (soc->is_async_ep)
3661  		htc_set_async_ep(soc->htc_handle, response.Endpoint, true);
3662  
3663  	soc->wmi_endpoint_id[pdev_idx] = response.Endpoint;
3664  	soc->max_msg_len[pdev_idx] = response.MaxMsgLength;
3665  
3666  	return QDF_STATUS_SUCCESS;
3667  }
3668  
3669  QDF_STATUS
wmi_unified_connect_htc_service(struct wmi_unified * wmi_handle,HTC_HANDLE htc_handle)3670  wmi_unified_connect_htc_service(struct wmi_unified *wmi_handle,
3671  				HTC_HANDLE htc_handle)
3672  {
3673  	uint32_t i;
3674  	uint8_t wmi_ep_count;
3675  
3676  	wmi_handle->soc->htc_handle = htc_handle;
3677  
3678  	wmi_ep_count = htc_get_wmi_endpoint_count(htc_handle);
3679  	if (wmi_ep_count > WMI_MAX_RADIOS)
3680  		return QDF_STATUS_E_FAULT;
3681  
3682  	for (i = 0; i < wmi_ep_count; i++)
3683  		wmi_connect_pdev_htc_service(wmi_handle->soc, i);
3684  
3685  	wmi_handle->htc_handle = htc_handle;
3686  	wmi_handle->wmi_endpoint_id = wmi_handle->soc->wmi_endpoint_id[0];
3687  	wmi_handle->max_msg_len = wmi_handle->soc->max_msg_len[0];
3688  
3689  	return QDF_STATUS_SUCCESS;
3690  }
3691  
3692  #if defined(WLAN_FEATURE_WMI_DIAG_OVER_CE7) || \
3693  	defined(WLAN_DIAG_AND_DBR_OVER_SEPARATE_CE)
wmi_diag_connect_pdev_htc_service(struct wmi_unified * wmi_handle,HTC_HANDLE htc_handle)3694  QDF_STATUS wmi_diag_connect_pdev_htc_service(struct wmi_unified *wmi_handle,
3695  					     HTC_HANDLE htc_handle)
3696  {
3697  	QDF_STATUS status;
3698  	struct htc_service_connect_resp response = {0};
3699  	struct htc_service_connect_req connect = {0};
3700  
3701  	/* meta data is unused for now */
3702  	connect.pMetaData = NULL;
3703  	connect.MetaDataLength = 0;
3704  	connect.EpCallbacks.pContext = wmi_handle->soc;
3705  	connect.EpCallbacks.EpTxCompleteMultiple = NULL;
3706  	connect.EpCallbacks.EpRecv = wmi_control_diag_rx /* wmi diag rx */;
3707  	connect.EpCallbacks.EpRecvRefill = NULL;
3708  	connect.EpCallbacks.EpSendFull = NULL;
3709  	connect.EpCallbacks.EpTxComplete = NULL;
3710  	connect.EpCallbacks.ep_log_pkt = wmi_htc_log_pkt;
3711  
3712  	/* connect to wmi diag service */
3713  	connect.service_id = WMI_CONTROL_DIAG_SVC;
3714  	status = htc_connect_service(htc_handle, &connect, &response);
3715  
3716  	if (QDF_IS_STATUS_ERROR(status)) {
3717  		wmi_err("Failed to connect to WMI DIAG service status:%d",
3718  			status);
3719  		return status;
3720  	}
3721  
3722  	if (wmi_handle->soc->is_async_ep)
3723  		htc_set_async_ep(htc_handle, response.Endpoint, true);
3724  
3725  	wmi_handle->soc->wmi_diag_endpoint_id = response.Endpoint;
3726  
3727  	return QDF_STATUS_SUCCESS;
3728  }
3729  #endif
3730  
3731  #if defined(WLAN_DIAG_AND_DBR_OVER_SEPARATE_CE)
wmi_dbr_connect_pdev_htc_service(struct wmi_unified * wmi_handle,HTC_HANDLE htc_handle)3732  QDF_STATUS wmi_dbr_connect_pdev_htc_service(struct wmi_unified *wmi_handle,
3733  					    HTC_HANDLE htc_handle)
3734  {
3735  	QDF_STATUS status;
3736  	struct htc_service_connect_resp response = {0};
3737  	struct htc_service_connect_req connect = {0};
3738  
3739  	/* meta data is unused for now */
3740  	connect.pMetaData = NULL;
3741  	connect.MetaDataLength = 0;
3742  	connect.EpCallbacks.pContext = wmi_handle->soc;
3743  	connect.EpCallbacks.EpTxCompleteMultiple = NULL;
3744  	connect.EpCallbacks.EpRecv = wmi_control_dbr_rx /* wmi dbr rx */;
3745  	connect.EpCallbacks.EpRecvRefill = NULL;
3746  	connect.EpCallbacks.EpSendFull = NULL;
3747  	connect.EpCallbacks.EpTxComplete = NULL;
3748  	connect.EpCallbacks.ep_log_pkt = wmi_htc_log_pkt;
3749  
3750  	/* connect to wmi dbr service */
3751  	connect.service_id = WMI_CONTROL_DBR_SVC;
3752  	status = htc_connect_service(htc_handle, &connect, &response);
3753  
3754  	if (QDF_IS_STATUS_ERROR(status)) {
3755  		wmi_err("Failed to connect to WMI DBR service status:%d",
3756  			status);
3757  		return status;
3758  	}
3759  
3760  	if (wmi_handle->soc->is_async_ep)
3761  		htc_set_async_ep(htc_handle, response.Endpoint, true);
3762  
3763  	wmi_handle->soc->wmi_dbr_endpoint_id = response.Endpoint;
3764  
3765  	return QDF_STATUS_SUCCESS;
3766  }
3767  #endif
3768  
wmi_get_host_credits(wmi_unified_t wmi_handle)3769  int wmi_get_host_credits(wmi_unified_t wmi_handle)
3770  {
3771  	int host_credits = 0;
3772  
3773  	htc_get_control_endpoint_tx_host_credits(wmi_handle->htc_handle,
3774  						 &host_credits);
3775  	return host_credits;
3776  }
3777  
wmi_get_pending_cmds(wmi_unified_t wmi_handle)3778  int wmi_get_pending_cmds(wmi_unified_t wmi_handle)
3779  {
3780  	return qdf_atomic_read(&wmi_handle->pending_cmds);
3781  }
3782  
wmi_set_target_suspend(wmi_unified_t wmi_handle,A_BOOL val)3783  void wmi_set_target_suspend(wmi_unified_t wmi_handle, A_BOOL val)
3784  {
3785  	qdf_atomic_set(&wmi_handle->is_target_suspended, val);
3786  }
3787  
wmi_set_target_suspend_acked(wmi_unified_t wmi_handle,A_BOOL val)3788  void wmi_set_target_suspend_acked(wmi_unified_t wmi_handle, A_BOOL val)
3789  {
3790  	qdf_atomic_set(&wmi_handle->is_target_suspend_acked, val);
3791  	qdf_atomic_set(&wmi_handle->num_stats_over_qmi, 0);
3792  }
3793  
wmi_is_target_suspended(struct wmi_unified * wmi_handle)3794  bool wmi_is_target_suspended(struct wmi_unified *wmi_handle)
3795  {
3796  	return qdf_atomic_read(&wmi_handle->is_target_suspended);
3797  }
3798  qdf_export_symbol(wmi_is_target_suspended);
3799  
wmi_is_target_suspend_acked(struct wmi_unified * wmi_handle)3800  bool wmi_is_target_suspend_acked(struct wmi_unified *wmi_handle)
3801  {
3802  	return qdf_atomic_read(&wmi_handle->is_target_suspend_acked);
3803  }
3804  qdf_export_symbol(wmi_is_target_suspend_acked);
3805  
3806  #ifdef WLAN_FEATURE_WMI_SEND_RECV_QMI
wmi_set_qmi_stats(wmi_unified_t wmi_handle,bool val)3807  void wmi_set_qmi_stats(wmi_unified_t wmi_handle, bool val)
3808  {
3809  	wmi_handle->is_qmi_stats_enabled = val;
3810  }
3811  
wmi_is_qmi_stats_enabled(struct wmi_unified * wmi_handle)3812  bool wmi_is_qmi_stats_enabled(struct wmi_unified *wmi_handle)
3813  {
3814  	return wmi_handle->is_qmi_stats_enabled;
3815  }
3816  #endif
3817  
wmi_tag_crash_inject(wmi_unified_t wmi_handle,A_BOOL flag)3818  void wmi_tag_crash_inject(wmi_unified_t wmi_handle, A_BOOL flag)
3819  {
3820  	wmi_handle->tag_crash_inject = flag;
3821  }
3822  
wmi_set_is_wow_bus_suspended(wmi_unified_t wmi_handle,A_BOOL val)3823  void wmi_set_is_wow_bus_suspended(wmi_unified_t wmi_handle, A_BOOL val)
3824  {
3825  	qdf_atomic_set(&wmi_handle->is_wow_bus_suspended, val);
3826  }
3827  
wmi_set_tgt_assert(wmi_unified_t wmi_handle,bool val)3828  void wmi_set_tgt_assert(wmi_unified_t wmi_handle, bool val)
3829  {
3830  	wmi_handle->tgt_force_assert_enable = val;
3831  }
3832  
3833  int
wmi_stop(wmi_unified_t wmi_handle)3834  wmi_stop(wmi_unified_t wmi_handle)
3835  {
3836  	QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO,
3837  		  "WMI Stop");
3838  	wmi_handle->wmi_stopinprogress = 1;
3839  	return 0;
3840  }
3841  
3842  int
wmi_start(wmi_unified_t wmi_handle)3843  wmi_start(wmi_unified_t wmi_handle)
3844  {
3845  	QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO,
3846  		  "WMI Start");
3847  	wmi_handle->wmi_stopinprogress = 0;
3848  	return 0;
3849  }
3850  
3851  bool
wmi_is_blocked(wmi_unified_t wmi_handle)3852  wmi_is_blocked(wmi_unified_t wmi_handle)
3853  {
3854  	return (!(!wmi_handle->wmi_stopinprogress));
3855  }
3856  
3857  void
wmi_flush_endpoint(wmi_unified_t wmi_handle)3858  wmi_flush_endpoint(wmi_unified_t wmi_handle)
3859  {
3860  	htc_flush_endpoint(wmi_handle->htc_handle,
3861  		wmi_handle->wmi_endpoint_id, 0);
3862  }
3863  qdf_export_symbol(wmi_flush_endpoint);
3864  
wmi_get_endpoint(wmi_unified_t wmi_handle)3865  HTC_ENDPOINT_ID wmi_get_endpoint(wmi_unified_t wmi_handle)
3866  {
3867  	return wmi_handle->wmi_endpoint_id;
3868  }
3869  
wmi_pdev_id_conversion_enable(wmi_unified_t wmi_handle,uint32_t * pdev_id_map,uint8_t size)3870  void wmi_pdev_id_conversion_enable(wmi_unified_t wmi_handle,
3871  				   uint32_t *pdev_id_map,
3872  				   uint8_t size)
3873  {
3874  	if (wmi_handle->target_type == WMI_TLV_TARGET)
3875  		wmi_handle->ops->wmi_pdev_id_conversion_enable(wmi_handle,
3876  							       pdev_id_map,
3877  							       size);
3878  }
3879  
__wmi_validate_handle(wmi_unified_t wmi_handle,const char * func)3880  int __wmi_validate_handle(wmi_unified_t wmi_handle, const char *func)
3881  {
3882          if (!wmi_handle) {
3883                  wmi_err("Invalid WMI handle (via %s)", func);
3884                  return -EINVAL;
3885          }
3886  
3887          return 0;
3888  }
3889