xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified.c (revision 9cee4926f939c08040ba11c0036109a4558a9828)
1 /*
2  * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Host WMI unified implementation
21  */
22 #include "htc_api.h"
23 #include "htc_api.h"
24 #include "wmi_unified_priv.h"
25 #include "wmi_unified_api.h"
26 #include "qdf_module.h"
27 #ifdef WMI_EXT_DBG
28 #include "qdf_list.h"
29 #endif
30 
31 #ifndef WMI_NON_TLV_SUPPORT
32 #include "wmi_tlv_helper.h"
33 #endif
34 
35 #include <linux/debugfs.h>
36 
37 #ifdef WMI_EXT_DBG
38 
39 /**
40  * wmi_ext_dbg_msg_enqueue() - enqueue wmi message
41  *
42  * @wmi_handle: wmi handler
43  *
44  * Return: size of wmi message queue after enqueue
45  */
46 static uint32_t wmi_ext_dbg_msg_enqueue(struct wmi_unified *wmi_handle,
47 					struct wmi_ext_dbg_msg *msg)
48 {
49 	uint32_t list_size;
50 
51 	qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
52 	qdf_list_insert_back_size(&wmi_handle->wmi_ext_dbg_msg_queue,
53 				  &msg->node, &list_size);
54 	qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
55 
56 	return list_size;
57 }
58 
59 /**
60  * wmi_ext_dbg_msg_dequeue() - dequeue wmi message
61  *
62  * @wmi_handle: wmi handler
63  *
64  * Return: wmi msg on success else NULL
65  */
66 static struct wmi_ext_dbg_msg *wmi_ext_dbg_msg_dequeue(struct wmi_unified
67 						       *wmi_handle)
68 {
69 	qdf_list_node_t *list_node = NULL;
70 
71 	qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
72 	qdf_list_remove_front(&wmi_handle->wmi_ext_dbg_msg_queue, &list_node);
73 	qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
74 
75 	if (!list_node)
76 		return NULL;
77 
78 	return qdf_container_of(list_node, struct wmi_ext_dbg_msg, node);
79 }
80 
81 /**
82  * wmi_ext_dbg_msg_record() - record wmi messages
83  *
84  * @wmi_handle: wmi handler
85  * @buf: wmi message buffer
86  * @len: wmi message length
87  * @type: wmi message type
88  *
89  * Return: QDF_STATUS_SUCCESS on successful recording else failure.
90  */
91 static QDF_STATUS wmi_ext_dbg_msg_record(struct wmi_unified *wmi_handle,
92 					 uint8_t *buf, uint32_t len,
93 					 enum WMI_MSG_TYPE type)
94 {
95 	struct wmi_ext_dbg_msg *msg;
96 	uint32_t list_size;
97 
98 	msg = wmi_ext_dbg_msg_get(len);
99 	if (!msg)
100 		return QDF_STATUS_E_NOMEM;
101 
102 	msg->len = len;
103 	msg->type = type;
104 	qdf_mem_copy(msg->buf, buf, len);
105 	msg->ts = qdf_get_log_timestamp();
106 	list_size = wmi_ext_dbg_msg_enqueue(wmi_handle, msg);
107 
108 	if (list_size >= wmi_handle->wmi_ext_dbg_msg_queue_size) {
109 		msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
110 		wmi_ext_dbg_msg_put(msg);
111 	}
112 
113 	return QDF_STATUS_SUCCESS;
114 }
115 
116 /**
117  * wmi_ext_dbg_msg_cmd_record() - record wmi command messages
118  *
119  * @wmi_handle: wmi handler
120  * @buf: wmi command buffer
121  * @len: wmi command message length
122  *
123  * Return: QDF_STATUS_SUCCESS on successful recording else failure.
124  */
125 static QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified *wmi_handle,
126 					     uint8_t *buf, uint32_t len)
127 {
128 	return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
129 				      WMI_MSG_TYPE_CMD);
130 }
131 
132 /**
133  * wmi_ext_dbg_msg_event_record() - record wmi event messages
134  *
135  * @wmi_handle: wmi handler
136  * @buf: wmi event buffer
137  * @len: wmi event message length
138  *
139  * Return: QDF_STATUS_SUCCESS on successful recording else failure.
140  */
141 static QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified *wmi_handle,
142 					       uint8_t *buf, uint32_t len)
143 {
144 	uint32_t id;
145 
146 	id = WMI_GET_FIELD(buf, WMI_CMD_HDR, COMMANDID);
147 	if (id != wmi_diag_event_id)
148 		return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
149 					      WMI_MSG_TYPE_EVENT);
150 
151 	return QDF_STATUS_SUCCESS;
152 }
153 
154 /**
155  * wmi_ext_dbg_msg_queue_init() - create debugfs queue and associated lock
156  *
157  * @wmi_handle: wmi handler
158  *
159  * Return: none
160  */
161 static void wmi_ext_dbg_msg_queue_init(struct wmi_unified *wmi_handle)
162 {
163 	qdf_list_create(&wmi_handle->wmi_ext_dbg_msg_queue,
164 			wmi_handle->wmi_ext_dbg_msg_queue_size);
165 	qdf_spinlock_create(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
166 }
167 
168 /**
169  * wmi_ext_dbg_msg_queue_deinit() - destroy debugfs queue and associated lock
170  *
171  * @wmi_handle: wmi handler
172  *
173  * Return: none
174  */
175 static void wmi_ext_dbg_msg_queue_deinit(struct wmi_unified *wmi_handle)
176 {
177 	qdf_list_destroy(&wmi_handle->wmi_ext_dbg_msg_queue);
178 	qdf_spinlock_destroy(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
179 }
180 
181 /**
182  * wmi_ext_dbg_msg_show() - debugfs function to display whole content of
183  * wmi command/event messages including headers.
184  *
185  * @file: qdf debugfs file handler
186  * @arg: pointer to wmi handler
187  *
188  * Return: QDF_STATUS_SUCCESS if all the messages are shown successfully,
189  * else QDF_STATUS_E_AGAIN if more data to show.
190  */
191 static QDF_STATUS wmi_ext_dbg_msg_show(qdf_debugfs_file_t file, void *arg)
192 {
193 	struct wmi_unified *wmi_handle = (struct wmi_unified *)arg;
194 	struct wmi_ext_dbg_msg *msg;
195 	uint64_t secs, usecs;
196 
197 	msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
198 	if (!msg)
199 		return QDF_STATUS_SUCCESS;
200 
201 	qdf_debugfs_printf(file, "%s: 0x%x\n",
202 			   msg->type == WMI_MSG_TYPE_CMD ? "COMMAND" :
203 			   "EVENT", WMI_GET_FIELD(msg->buf, WMI_CMD_HDR,
204 						  COMMANDID));
205 	qdf_log_timestamp_to_secs(msg->ts, &secs, &usecs);
206 	qdf_debugfs_printf(file, "Time: %llu.%llu\n", secs, usecs);
207 	qdf_debugfs_printf(file, "Length:%d\n", msg->len);
208 	qdf_debugfs_hexdump(file, msg->buf, msg->len,
209 			    WMI_EXT_DBG_DUMP_ROW_SIZE,
210 			    WMI_EXT_DBG_DUMP_GROUP_SIZE);
211 	qdf_debugfs_printf(file, "\n");
212 
213 	if (qdf_debugfs_overflow(file)) {
214 		qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
215 		qdf_list_insert_front(&wmi_handle->wmi_ext_dbg_msg_queue,
216 				      &msg->node);
217 		qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
218 
219 	} else {
220 		wmi_ext_dbg_msg_put(msg);
221 	}
222 
223 	return QDF_STATUS_E_AGAIN;
224 }
225 
226 /**
227  * wmi_ext_dbg_msg_write() - debugfs write not supported
228  *
229  * @priv: private data
230  * @buf: received data buffer
231  * @len: length of received buffer
232  *
233  * Return: QDF_STATUS_E_NOSUPPORT.
234  */
235 static QDF_STATUS wmi_ext_dbg_msg_write(void *priv, const char *buf,
236 					qdf_size_t len)
237 {
238 	return QDF_STATUS_E_NOSUPPORT;
239 }
240 
241 static struct qdf_debugfs_fops wmi_ext_dbgfs_ops = {
242 	.show		= wmi_ext_dbg_msg_show,
243 	.write		= wmi_ext_dbg_msg_write,
244 	.priv		= NULL,
245 };
246 
247 /**
248  * wmi_ext_debugfs_init() - init debugfs items for extended wmi dump.
249  *
250  * @wmi_handle: wmi handler
251  *
252  * Return: QDF_STATUS_SUCCESS if debugfs is initialized else
253  * QDF_STATUS_E_FAILURE
254  */
255 static QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle)
256 {
257 	qdf_dentry_t dentry;
258 
259 	dentry  = qdf_debugfs_create_dir(WMI_EXT_DBG_DIR, NULL);
260 	if (!dentry) {
261 		qdf_print("error while creating extended wmi debugfs dir");
262 		return QDF_STATUS_E_FAILURE;
263 	}
264 
265 	wmi_ext_dbgfs_ops.priv = wmi_handle;
266 	if (!qdf_debugfs_create_file(WMI_EXT_DBG_FILE, WMI_EXT_DBG_FILE_PERM,
267 				     dentry, &wmi_ext_dbgfs_ops)) {
268 		qdf_debugfs_remove_dir(dentry);
269 		qdf_print("error while creating extended wmi debugfs file");
270 		return QDF_STATUS_E_FAILURE;
271 	}
272 
273 	wmi_handle->wmi_ext_dbg_dentry = dentry;
274 	wmi_handle->wmi_ext_dbg_msg_queue_size = WMI_EXT_DBG_QUEUE_SIZE;
275 	wmi_ext_dbg_msg_queue_init(wmi_handle);
276 
277 	return QDF_STATUS_SUCCESS;
278 }
279 
280 /**
281  * wmi_ext_debugfs_deinit() - cleanup/deinit debugfs items of extended wmi dump.
282  *
283  * @wmi_handle: wmi handler
284  *
285  * Return: QDF_STATUS_SUCCESS if cleanup is successful
286  */
287 static QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
288 {
289 	struct wmi_ext_dbg_msg *msg;
290 
291 	while ((msg = wmi_ext_dbg_msg_dequeue(wmi_handle)))
292 		wmi_ext_dbg_msg_put(msg);
293 
294 	wmi_ext_dbg_msg_queue_deinit(wmi_handle);
295 	qdf_debugfs_remove_dir_recursive(wmi_handle->wmi_ext_dbg_dentry);
296 
297 	return QDF_STATUS_SUCCESS;
298 }
299 
300 #endif /*WMI_EXT_DBG */
301 
302 /* This check for CONFIG_WIN temporary added due to redeclaration compilation
303 error in MCL. Error is caused due to inclusion of wmi.h in wmi_unified_api.h
304 which gets included here through ol_if_athvar.h. Eventually it is expected that
305 wmi.h will be removed from wmi_unified_api.h after cleanup, which will need
306 WMI_CMD_HDR to be defined here. */
307 #ifdef CONFIG_WIN
308 /* Copied from wmi.h */
309 #undef MS
310 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
311 #undef SM
312 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
313 #undef WO
314 #define WO(_f)      ((_f##_OFFSET) >> 2)
315 
316 #undef GET_FIELD
317 #define GET_FIELD(_addr, _f) MS(*((uint32_t *)(_addr) + WO(_f)), _f)
318 #undef SET_FIELD
319 #define SET_FIELD(_addr, _f, _val)  \
320 	    (*((uint32_t *)(_addr) + WO(_f)) = \
321 		(*((uint32_t *)(_addr) + WO(_f)) & ~_f##_MASK) | SM(_val, _f))
322 
323 #define WMI_GET_FIELD(_msg_buf, _msg_type, _f) \
324 	    GET_FIELD(_msg_buf, _msg_type ## _ ## _f)
325 
326 #define WMI_SET_FIELD(_msg_buf, _msg_type, _f, _val) \
327 	    SET_FIELD(_msg_buf, _msg_type ## _ ## _f, _val)
328 
329 #define WMI_EP_APASS           0x0
330 #define WMI_EP_LPASS           0x1
331 #define WMI_EP_SENSOR          0x2
332 
333 /*
334  *  * Control Path
335  *   */
336 typedef PREPACK struct {
337 	uint32_t	commandId:24,
338 			reserved:2, /* used for WMI endpoint ID */
339 			plt_priv:6; /* platform private */
340 } POSTPACK WMI_CMD_HDR;        /* used for commands and events */
341 
342 #define WMI_CMD_HDR_COMMANDID_LSB           0
343 #define WMI_CMD_HDR_COMMANDID_MASK          0x00ffffff
344 #define WMI_CMD_HDR_COMMANDID_OFFSET        0x00000000
345 #define WMI_CMD_HDR_WMI_ENDPOINTID_MASK        0x03000000
346 #define WMI_CMD_HDR_WMI_ENDPOINTID_OFFSET      24
347 #define WMI_CMD_HDR_PLT_PRIV_LSB               24
348 #define WMI_CMD_HDR_PLT_PRIV_MASK              0xff000000
349 #define WMI_CMD_HDR_PLT_PRIV_OFFSET            0x00000000
350 /* end of copy wmi.h */
351 #endif /* CONFIG_WIN */
352 
353 #define WMI_MIN_HEAD_ROOM 64
354 
355 #ifdef WMI_INTERFACE_EVENT_LOGGING
356 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0))
357 /* TODO Cleanup this backported function */
358 static int wmi_bp_seq_printf(struct seq_file *m, const char *f, ...)
359 {
360 	va_list args;
361 
362 	va_start(args, f);
363 	seq_vprintf(m, f, args);
364 	va_end(args);
365 
366 	return 0;
367 }
368 #else
369 #define wmi_bp_seq_printf(m, fmt, ...) seq_printf((m), fmt, ##__VA_ARGS__)
370 #endif
371 
372 #ifndef MAX_WMI_INSTANCES
373 #define CUSTOM_MGMT_CMD_DATA_SIZE 4
374 #endif
375 
376 #ifdef CONFIG_MCL
377 /* WMI commands */
378 uint32_t g_wmi_command_buf_idx = 0;
379 struct wmi_command_debug wmi_command_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
380 
381 /* WMI commands TX completed */
382 uint32_t g_wmi_command_tx_cmp_buf_idx = 0;
383 struct wmi_command_debug
384 	wmi_command_tx_cmp_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
385 
386 /* WMI events when processed */
387 uint32_t g_wmi_event_buf_idx = 0;
388 struct wmi_event_debug wmi_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
389 
390 /* WMI events when queued */
391 uint32_t g_wmi_rx_event_buf_idx = 0;
392 struct wmi_event_debug wmi_rx_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
393 #endif
394 
395 #define WMI_COMMAND_RECORD(h, a, b) {					\
396 	if (wmi_log_max_entry <=					\
397 		*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx))	\
398 		*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx) = 0;\
399 	((struct wmi_command_debug *)h->log_info.wmi_command_log_buf_info.buf)\
400 		[*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)]\
401 						.command = a;		\
402 	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.		\
403 				wmi_command_log_buf_info.buf)		\
404 		[*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)].data,\
405 			b, wmi_record_max_length);			\
406 	((struct wmi_command_debug *)h->log_info.wmi_command_log_buf_info.buf)\
407 		[*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)].\
408 		time = qdf_get_log_timestamp();			\
409 	(*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx))++;	\
410 	h->log_info.wmi_command_log_buf_info.length++;			\
411 }
412 
413 #define WMI_COMMAND_TX_CMP_RECORD(h, a, b) {				\
414 	if (wmi_log_max_entry <=					\
415 		*(h->log_info.wmi_command_tx_cmp_log_buf_info.p_buf_tail_idx))\
416 		*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
417 				p_buf_tail_idx) = 0;			\
418 	((struct wmi_command_debug *)h->log_info.			\
419 		wmi_command_tx_cmp_log_buf_info.buf)			\
420 		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
421 				p_buf_tail_idx)].			\
422 							command	= a;	\
423 	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.		\
424 				wmi_command_tx_cmp_log_buf_info.buf)	\
425 		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
426 			p_buf_tail_idx)].				\
427 		data, b, wmi_record_max_length);			\
428 	((struct wmi_command_debug *)h->log_info.			\
429 		wmi_command_tx_cmp_log_buf_info.buf)			\
430 		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
431 				p_buf_tail_idx)].			\
432 		time = qdf_get_log_timestamp();				\
433 	(*(h->log_info.wmi_command_tx_cmp_log_buf_info.p_buf_tail_idx))++;\
434 	h->log_info.wmi_command_tx_cmp_log_buf_info.length++;		\
435 }
436 
437 #define WMI_EVENT_RECORD(h, a, b) {					\
438 	if (wmi_log_max_entry <=					\
439 		*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx))	\
440 		*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx) = 0;\
441 	((struct wmi_event_debug *)h->log_info.wmi_event_log_buf_info.buf)\
442 		[*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].	\
443 		event = a;						\
444 	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.		\
445 				wmi_event_log_buf_info.buf)		\
446 		[*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].data, b,\
447 		wmi_record_max_length);					\
448 	((struct wmi_event_debug *)h->log_info.wmi_event_log_buf_info.buf)\
449 		[*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].time =\
450 		qdf_get_log_timestamp();				\
451 	(*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx))++;	\
452 	h->log_info.wmi_event_log_buf_info.length++;			\
453 }
454 
455 #define WMI_RX_EVENT_RECORD(h, a, b) {					\
456 	if (wmi_log_max_entry <=					\
457 		*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx))\
458 		*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx) = 0;\
459 	((struct wmi_event_debug *)h->log_info.wmi_rx_event_log_buf_info.buf)\
460 		[*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\
461 		event = a;						\
462 	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.		\
463 				wmi_rx_event_log_buf_info.buf)		\
464 		[*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\
465 			data, b, wmi_record_max_length);		\
466 	((struct wmi_event_debug *)h->log_info.wmi_rx_event_log_buf_info.buf)\
467 		[*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\
468 		time =	qdf_get_log_timestamp();			\
469 	(*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx))++;	\
470 	h->log_info.wmi_rx_event_log_buf_info.length++;			\
471 }
472 
473 #ifdef CONFIG_MCL
474 uint32_t g_wmi_mgmt_command_buf_idx = 0;
475 struct
476 wmi_command_debug wmi_mgmt_command_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY];
477 
478 /* wmi_mgmt commands TX completed */
479 uint32_t g_wmi_mgmt_command_tx_cmp_buf_idx = 0;
480 struct wmi_command_debug
481 wmi_mgmt_command_tx_cmp_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY];
482 
483 /* wmi_mgmt events when processed */
484 uint32_t g_wmi_mgmt_event_buf_idx = 0;
485 struct wmi_event_debug
486 wmi_mgmt_event_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY];
487 #endif
488 
489 #define WMI_MGMT_COMMAND_RECORD(h, a, b) {                              \
490 	if (wmi_mgmt_log_max_entry <=                                   \
491 		*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)) \
492 		*(h->log_info.wmi_mgmt_command_log_buf_info.		\
493 				p_buf_tail_idx) = 0;			\
494 	((struct wmi_command_debug *)h->log_info.                       \
495 		 wmi_mgmt_command_log_buf_info.buf)                     \
496 		[*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\
497 			command = a;                                    \
498 	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.          \
499 				wmi_mgmt_command_log_buf_info.buf)      \
500 		[*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\
501 		data, b,                                                \
502 		wmi_record_max_length);                                	\
503 	((struct wmi_command_debug *)h->log_info.                       \
504 		 wmi_mgmt_command_log_buf_info.buf)                     \
505 		[*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\
506 			time =        qdf_get_log_timestamp();          \
507 	(*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx))++;\
508 	h->log_info.wmi_mgmt_command_log_buf_info.length++;             \
509 }
510 
511 #define WMI_MGMT_COMMAND_TX_CMP_RECORD(h, a, b) {			\
512 	if (wmi_mgmt_log_max_entry <=					\
513 		*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
514 			p_buf_tail_idx))				\
515 		*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
516 			p_buf_tail_idx) = 0;				\
517 	((struct wmi_command_debug *)h->log_info.			\
518 			wmi_mgmt_command_tx_cmp_log_buf_info.buf)	\
519 		[*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
520 				p_buf_tail_idx)].command = a;		\
521 	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.		\
522 				wmi_mgmt_command_tx_cmp_log_buf_info.buf)\
523 		[*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
524 			p_buf_tail_idx)].data, b,			\
525 			wmi_record_max_length);				\
526 	((struct wmi_command_debug *)h->log_info.			\
527 			wmi_mgmt_command_tx_cmp_log_buf_info.buf)	\
528 		[*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
529 				p_buf_tail_idx)].time =			\
530 		qdf_get_log_timestamp();				\
531 	(*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.		\
532 			p_buf_tail_idx))++;				\
533 	h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.length++;	\
534 }
535 
536 #define WMI_MGMT_EVENT_RECORD(h, a, b) {				\
537 	if (wmi_mgmt_log_max_entry <=					\
538 		*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx))\
539 		*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx) = 0;\
540 	((struct wmi_event_debug *)h->log_info.wmi_mgmt_event_log_buf_info.buf)\
541 		[*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)]\
542 					.event = a;			\
543 	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.		\
544 				wmi_mgmt_event_log_buf_info.buf)	\
545 		[*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)].\
546 			data, b, wmi_record_max_length);		\
547 	((struct wmi_event_debug *)h->log_info.wmi_mgmt_event_log_buf_info.buf)\
548 		[*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)].\
549 			time = qdf_get_log_timestamp();			\
550 	(*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx))++;	\
551 	h->log_info.wmi_mgmt_event_log_buf_info.length++;		\
552 }
553 
554 /* These are defined to made it as module param, which can be configured */
555 uint32_t wmi_log_max_entry = WMI_EVENT_DEBUG_MAX_ENTRY;
556 uint32_t wmi_mgmt_log_max_entry = WMI_MGMT_EVENT_DEBUG_MAX_ENTRY;
557 uint32_t wmi_record_max_length = WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH;
558 uint32_t wmi_display_size = 100;
559 
560 /**
561  * wmi_log_init() - Initialize WMI event logging
562  * @wmi_handle: WMI handle.
563  *
564  * Return: Initialization status
565  */
566 #ifdef CONFIG_MCL
567 static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle)
568 {
569 	struct wmi_log_buf_t *cmd_log_buf =
570 			&wmi_handle->log_info.wmi_command_log_buf_info;
571 	struct wmi_log_buf_t *cmd_tx_cmpl_log_buf =
572 			&wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info;
573 
574 	struct wmi_log_buf_t *event_log_buf =
575 			&wmi_handle->log_info.wmi_event_log_buf_info;
576 	struct wmi_log_buf_t *rx_event_log_buf =
577 			&wmi_handle->log_info.wmi_rx_event_log_buf_info;
578 
579 	struct wmi_log_buf_t *mgmt_cmd_log_buf =
580 			&wmi_handle->log_info.wmi_mgmt_command_log_buf_info;
581 	struct wmi_log_buf_t *mgmt_cmd_tx_cmp_log_buf =
582 		&wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info;
583 	struct wmi_log_buf_t *mgmt_event_log_buf =
584 			&wmi_handle->log_info.wmi_mgmt_event_log_buf_info;
585 
586 	/* WMI commands */
587 	cmd_log_buf->length = 0;
588 	cmd_log_buf->buf_tail_idx = 0;
589 	cmd_log_buf->buf = wmi_command_log_buffer;
590 	cmd_log_buf->p_buf_tail_idx = &g_wmi_command_buf_idx;
591 	cmd_log_buf->size = WMI_EVENT_DEBUG_MAX_ENTRY;
592 
593 	/* WMI commands TX completed */
594 	cmd_tx_cmpl_log_buf->length = 0;
595 	cmd_tx_cmpl_log_buf->buf_tail_idx = 0;
596 	cmd_tx_cmpl_log_buf->buf = wmi_command_tx_cmp_log_buffer;
597 	cmd_tx_cmpl_log_buf->p_buf_tail_idx = &g_wmi_command_tx_cmp_buf_idx;
598 	cmd_tx_cmpl_log_buf->size = WMI_EVENT_DEBUG_MAX_ENTRY;
599 
600 	/* WMI events when processed */
601 	event_log_buf->length = 0;
602 	event_log_buf->buf_tail_idx = 0;
603 	event_log_buf->buf = wmi_event_log_buffer;
604 	event_log_buf->p_buf_tail_idx = &g_wmi_event_buf_idx;
605 	event_log_buf->size = WMI_EVENT_DEBUG_MAX_ENTRY;
606 
607 	/* WMI events when queued */
608 	rx_event_log_buf->length = 0;
609 	rx_event_log_buf->buf_tail_idx = 0;
610 	rx_event_log_buf->buf = wmi_rx_event_log_buffer;
611 	rx_event_log_buf->p_buf_tail_idx = &g_wmi_rx_event_buf_idx;
612 	rx_event_log_buf->size = WMI_EVENT_DEBUG_MAX_ENTRY;
613 
614 	/* WMI Management commands */
615 	mgmt_cmd_log_buf->length = 0;
616 	mgmt_cmd_log_buf->buf_tail_idx = 0;
617 	mgmt_cmd_log_buf->buf = wmi_mgmt_command_log_buffer;
618 	mgmt_cmd_log_buf->p_buf_tail_idx = &g_wmi_mgmt_command_buf_idx;
619 	mgmt_cmd_log_buf->size = WMI_MGMT_EVENT_DEBUG_MAX_ENTRY;
620 
621 	/* WMI Management commands Tx completed*/
622 	mgmt_cmd_tx_cmp_log_buf->length = 0;
623 	mgmt_cmd_tx_cmp_log_buf->buf_tail_idx = 0;
624 	mgmt_cmd_tx_cmp_log_buf->buf = wmi_mgmt_command_tx_cmp_log_buffer;
625 	mgmt_cmd_tx_cmp_log_buf->p_buf_tail_idx =
626 		&g_wmi_mgmt_command_tx_cmp_buf_idx;
627 	mgmt_cmd_tx_cmp_log_buf->size = WMI_MGMT_EVENT_DEBUG_MAX_ENTRY;
628 
629 	/* WMI Management events when processed*/
630 	mgmt_event_log_buf->length = 0;
631 	mgmt_event_log_buf->buf_tail_idx = 0;
632 	mgmt_event_log_buf->buf = wmi_mgmt_event_log_buffer;
633 	mgmt_event_log_buf->p_buf_tail_idx = &g_wmi_mgmt_event_buf_idx;
634 	mgmt_event_log_buf->size = WMI_MGMT_EVENT_DEBUG_MAX_ENTRY;
635 
636 	qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock);
637 	wmi_handle->log_info.wmi_logging_enable = 1;
638 
639 	return QDF_STATUS_SUCCESS;
640 }
641 #else
642 static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle)
643 {
644 	struct wmi_log_buf_t *cmd_log_buf =
645 			&wmi_handle->log_info.wmi_command_log_buf_info;
646 	struct wmi_log_buf_t *cmd_tx_cmpl_log_buf =
647 			&wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info;
648 
649 	struct wmi_log_buf_t *event_log_buf =
650 			&wmi_handle->log_info.wmi_event_log_buf_info;
651 	struct wmi_log_buf_t *rx_event_log_buf =
652 			&wmi_handle->log_info.wmi_rx_event_log_buf_info;
653 
654 	struct wmi_log_buf_t *mgmt_cmd_log_buf =
655 			&wmi_handle->log_info.wmi_mgmt_command_log_buf_info;
656 	struct wmi_log_buf_t *mgmt_cmd_tx_cmp_log_buf =
657 		&wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info;
658 	struct wmi_log_buf_t *mgmt_event_log_buf =
659 			&wmi_handle->log_info.wmi_mgmt_event_log_buf_info;
660 
661 	wmi_handle->log_info.wmi_logging_enable = 0;
662 
663 	/* WMI commands */
664 	cmd_log_buf->length = 0;
665 	cmd_log_buf->buf_tail_idx = 0;
666 	cmd_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc(
667 		wmi_log_max_entry * sizeof(struct wmi_command_debug));
668 	cmd_log_buf->size = wmi_log_max_entry;
669 
670 	if (!cmd_log_buf->buf) {
671 		qdf_print("no memory for WMI command log buffer..");
672 		return QDF_STATUS_E_NOMEM;
673 	}
674 	cmd_log_buf->p_buf_tail_idx = &cmd_log_buf->buf_tail_idx;
675 
676 	/* WMI commands TX completed */
677 	cmd_tx_cmpl_log_buf->length = 0;
678 	cmd_tx_cmpl_log_buf->buf_tail_idx = 0;
679 	cmd_tx_cmpl_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc(
680 		wmi_log_max_entry * sizeof(struct wmi_command_debug));
681 	cmd_tx_cmpl_log_buf->size = wmi_log_max_entry;
682 
683 	if (!cmd_tx_cmpl_log_buf->buf) {
684 		qdf_print("no memory for WMI Command Tx Complete log buffer..");
685 		return QDF_STATUS_E_NOMEM;
686 	}
687 	cmd_tx_cmpl_log_buf->p_buf_tail_idx =
688 		&cmd_tx_cmpl_log_buf->buf_tail_idx;
689 
690 	/* WMI events when processed */
691 	event_log_buf->length = 0;
692 	event_log_buf->buf_tail_idx = 0;
693 	event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
694 		wmi_log_max_entry * sizeof(struct wmi_event_debug));
695 	event_log_buf->size = wmi_log_max_entry;
696 
697 	if (!event_log_buf->buf) {
698 		qdf_print("no memory for WMI Event log buffer..");
699 		return QDF_STATUS_E_NOMEM;
700 	}
701 	event_log_buf->p_buf_tail_idx = &event_log_buf->buf_tail_idx;
702 
703 	/* WMI events when queued */
704 	rx_event_log_buf->length = 0;
705 	rx_event_log_buf->buf_tail_idx = 0;
706 	rx_event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
707 		wmi_log_max_entry * sizeof(struct wmi_event_debug));
708 	rx_event_log_buf->size = wmi_log_max_entry;
709 
710 	if (!rx_event_log_buf->buf) {
711 		qdf_print("no memory for WMI Event Rx log buffer..");
712 		return QDF_STATUS_E_NOMEM;
713 	}
714 	rx_event_log_buf->p_buf_tail_idx = &rx_event_log_buf->buf_tail_idx;
715 
716 	/* WMI Management commands */
717 	mgmt_cmd_log_buf->length = 0;
718 	mgmt_cmd_log_buf->buf_tail_idx = 0;
719 	mgmt_cmd_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc(
720 		wmi_mgmt_log_max_entry * sizeof(struct wmi_command_debug));
721 	mgmt_cmd_log_buf->size = wmi_mgmt_log_max_entry;
722 
723 	if (!mgmt_cmd_log_buf->buf) {
724 		qdf_print("no memory for WMI Management Command log buffer..");
725 		return QDF_STATUS_E_NOMEM;
726 	}
727 	mgmt_cmd_log_buf->p_buf_tail_idx = &mgmt_cmd_log_buf->buf_tail_idx;
728 
729 	/* WMI Management commands Tx completed*/
730 	mgmt_cmd_tx_cmp_log_buf->length = 0;
731 	mgmt_cmd_tx_cmp_log_buf->buf_tail_idx = 0;
732 	mgmt_cmd_tx_cmp_log_buf->buf = (struct wmi_command_debug *)
733 		qdf_mem_malloc(
734 		wmi_mgmt_log_max_entry *
735 		sizeof(struct wmi_command_debug));
736 	mgmt_cmd_tx_cmp_log_buf->size = wmi_mgmt_log_max_entry;
737 
738 	if (!mgmt_cmd_tx_cmp_log_buf->buf) {
739 		qdf_print("no memory for WMI Management Command Tx complete log buffer..");
740 		return QDF_STATUS_E_NOMEM;
741 	}
742 	mgmt_cmd_tx_cmp_log_buf->p_buf_tail_idx =
743 		&mgmt_cmd_tx_cmp_log_buf->buf_tail_idx;
744 
745 	/* WMI Management events when processed*/
746 	mgmt_event_log_buf->length = 0;
747 	mgmt_event_log_buf->buf_tail_idx = 0;
748 
749 	mgmt_event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
750 		wmi_mgmt_log_max_entry *
751 		sizeof(struct wmi_event_debug));
752 	mgmt_event_log_buf->size = wmi_mgmt_log_max_entry;
753 
754 	if (!mgmt_event_log_buf->buf) {
755 		qdf_print("no memory for WMI Management Event log buffer..");
756 		return QDF_STATUS_E_NOMEM;
757 	}
758 	mgmt_event_log_buf->p_buf_tail_idx = &mgmt_event_log_buf->buf_tail_idx;
759 
760 	qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock);
761 	wmi_handle->log_info.wmi_logging_enable = 1;
762 
763 	return QDF_STATUS_SUCCESS;
764 }
765 #endif
766 
767 /**
768  * wmi_log_buffer_free() - Free all dynamic allocated buffer memory for
769  * event logging
770  * @wmi_handle: WMI handle.
771  *
772  * Return: None
773  */
774 #ifndef CONFIG_MCL
775 static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle)
776 {
777 	if (wmi_handle->log_info.wmi_command_log_buf_info.buf)
778 		qdf_mem_free(wmi_handle->log_info.wmi_command_log_buf_info.buf);
779 	if (wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info.buf)
780 		qdf_mem_free(
781 		wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info.buf);
782 	if (wmi_handle->log_info.wmi_event_log_buf_info.buf)
783 		qdf_mem_free(wmi_handle->log_info.wmi_event_log_buf_info.buf);
784 	if (wmi_handle->log_info.wmi_rx_event_log_buf_info.buf)
785 		qdf_mem_free(
786 			wmi_handle->log_info.wmi_rx_event_log_buf_info.buf);
787 	if (wmi_handle->log_info.wmi_mgmt_command_log_buf_info.buf)
788 		qdf_mem_free(
789 			wmi_handle->log_info.wmi_mgmt_command_log_buf_info.buf);
790 	if (wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.buf)
791 		qdf_mem_free(
792 		wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.buf);
793 	if (wmi_handle->log_info.wmi_mgmt_event_log_buf_info.buf)
794 		qdf_mem_free(
795 			wmi_handle->log_info.wmi_mgmt_event_log_buf_info.buf);
796 	wmi_handle->log_info.wmi_logging_enable = 0;
797 	qdf_spinlock_destroy(&wmi_handle->log_info.wmi_record_lock);
798 }
799 #else
800 static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle)
801 {
802 	/* Do Nothing */
803 }
804 #endif
805 
806 /**
807  * wmi_print_cmd_log_buffer() - an output agnostic wmi command log printer
808  * @log_buffer: the command log buffer metadata of the buffer to print
809  * @count: the maximum number of entries to print
810  * @print: an abstract print method, e.g. a qdf_print() or seq_printf() wrapper
811  * @print_priv: any data required by the print method, e.g. a file handle
812  *
813  * Return: None
814  */
815 static void
816 wmi_print_cmd_log_buffer(struct wmi_log_buf_t *log_buffer, uint32_t count,
817 			 qdf_abstract_print *print, void *print_priv)
818 {
819 	static const int data_len =
820 		WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH / sizeof(uint32_t);
821 	char str[128];
822 	uint32_t idx;
823 
824 	if (count > log_buffer->size)
825 		count = log_buffer->size;
826 	if (count > log_buffer->length)
827 		count = log_buffer->length;
828 
829 	/* subtract count from index, and wrap if necessary */
830 	idx = log_buffer->size + *log_buffer->p_buf_tail_idx - count;
831 	idx %= log_buffer->size;
832 
833 	print(print_priv, "Time (seconds)      Cmd Id              Payload");
834 	while (count) {
835 		struct wmi_command_debug *cmd_log = (struct wmi_command_debug *)
836 			&((struct wmi_command_debug *)log_buffer->buf)[idx];
837 		uint64_t secs, usecs;
838 		int len = 0;
839 		int i;
840 
841 		qdf_log_timestamp_to_secs(cmd_log->time, &secs, &usecs);
842 		len += scnprintf(str + len, sizeof(str) - len,
843 				 "% 8lld.%06lld    %6u (0x%06x)    ",
844 				 secs, usecs,
845 				 cmd_log->command, cmd_log->command);
846 		for (i = 0; i < data_len; ++i) {
847 			len += scnprintf(str + len, sizeof(str) - len,
848 					 "0x%08x ", cmd_log->data[i]);
849 		}
850 
851 		print(print_priv, str);
852 
853 		--count;
854 		++idx;
855 		if (idx >= log_buffer->size)
856 			idx = 0;
857 	}
858 }
859 
860 /**
861  * wmi_print_event_log_buffer() - an output agnostic wmi event log printer
862  * @log_buffer: the event log buffer metadata of the buffer to print
863  * @count: the maximum number of entries to print
864  * @print: an abstract print method, e.g. a qdf_print() or seq_printf() wrapper
865  * @print_priv: any data required by the print method, e.g. a file handle
866  *
867  * Return: None
868  */
869 static void
870 wmi_print_event_log_buffer(struct wmi_log_buf_t *log_buffer, uint32_t count,
871 			   qdf_abstract_print *print, void *print_priv)
872 {
873 	static const int data_len =
874 		WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH / sizeof(uint32_t);
875 	char str[128];
876 	uint32_t idx;
877 
878 	if (count > log_buffer->size)
879 		count = log_buffer->size;
880 	if (count > log_buffer->length)
881 		count = log_buffer->length;
882 
883 	/* subtract count from index, and wrap if necessary */
884 	idx = log_buffer->size + *log_buffer->p_buf_tail_idx - count;
885 	idx %= log_buffer->size;
886 
887 	print(print_priv, "Time (seconds)      Event Id             Payload");
888 	while (count) {
889 		struct wmi_event_debug *event_log = (struct wmi_event_debug *)
890 			&((struct wmi_event_debug *)log_buffer->buf)[idx];
891 		uint64_t secs, usecs;
892 		int len = 0;
893 		int i;
894 
895 		qdf_log_timestamp_to_secs(event_log->time, &secs, &usecs);
896 		len += scnprintf(str + len, sizeof(str) - len,
897 				 "% 8lld.%06lld    %6u (0x%06x)    ",
898 				 secs, usecs,
899 				 event_log->event, event_log->event);
900 		for (i = 0; i < data_len; ++i) {
901 			len += scnprintf(str + len, sizeof(str) - len,
902 					 "0x%08x ", event_log->data[i]);
903 		}
904 
905 		print(print_priv, str);
906 
907 		--count;
908 		++idx;
909 		if (idx >= log_buffer->size)
910 			idx = 0;
911 	}
912 }
913 
914 inline void
915 wmi_print_cmd_log(wmi_unified_t wmi, uint32_t count,
916 		  qdf_abstract_print *print, void *print_priv)
917 {
918 	wmi_print_cmd_log_buffer(
919 		&wmi->log_info.wmi_command_log_buf_info,
920 		count, print, print_priv);
921 }
922 
923 inline void
924 wmi_print_cmd_tx_cmp_log(wmi_unified_t wmi, uint32_t count,
925 			 qdf_abstract_print *print, void *print_priv)
926 {
927 	wmi_print_cmd_log_buffer(
928 		&wmi->log_info.wmi_command_tx_cmp_log_buf_info,
929 		count, print, print_priv);
930 }
931 
932 inline void
933 wmi_print_mgmt_cmd_log(wmi_unified_t wmi, uint32_t count,
934 		       qdf_abstract_print *print, void *print_priv)
935 {
936 	wmi_print_cmd_log_buffer(
937 		&wmi->log_info.wmi_mgmt_command_log_buf_info,
938 		count, print, print_priv);
939 }
940 
941 inline void
942 wmi_print_mgmt_cmd_tx_cmp_log(wmi_unified_t wmi, uint32_t count,
943 			      qdf_abstract_print *print, void *print_priv)
944 {
945 	wmi_print_cmd_log_buffer(
946 		&wmi->log_info.wmi_mgmt_command_tx_cmp_log_buf_info,
947 		count, print, print_priv);
948 }
949 
950 inline void
951 wmi_print_event_log(wmi_unified_t wmi, uint32_t count,
952 		    qdf_abstract_print *print, void *print_priv)
953 {
954 	wmi_print_event_log_buffer(
955 		&wmi->log_info.wmi_event_log_buf_info,
956 		count, print, print_priv);
957 }
958 
959 inline void
960 wmi_print_rx_event_log(wmi_unified_t wmi, uint32_t count,
961 		       qdf_abstract_print *print, void *print_priv)
962 {
963 	wmi_print_event_log_buffer(
964 		&wmi->log_info.wmi_rx_event_log_buf_info,
965 		count, print, print_priv);
966 }
967 
968 inline void
969 wmi_print_mgmt_event_log(wmi_unified_t wmi, uint32_t count,
970 			 qdf_abstract_print *print, void *print_priv)
971 {
972 	wmi_print_event_log_buffer(
973 		&wmi->log_info.wmi_mgmt_event_log_buf_info,
974 		count, print, print_priv);
975 }
976 
977 
978 /* debugfs routines*/
979 
980 /**
981  * debug_wmi_##func_base##_show() - debugfs functions to display content of
982  * command and event buffers. Macro uses max buffer length to display
983  * buffer when it is wraparound.
984  *
985  * @m: debugfs handler to access wmi_handle
986  * @v: Variable arguments (not used)
987  *
988  * Return: Length of characters printed
989  */
990 #define GENERATE_COMMAND_DEBUG_SHOW_FUNCS(func_base, wmi_ring_size)	\
991 	static int debug_wmi_##func_base##_show(struct seq_file *m,	\
992 						void *v)		\
993 	{								\
994 		wmi_unified_t wmi_handle = (wmi_unified_t) m->private;	\
995 		struct wmi_log_buf_t *wmi_log =				\
996 			&wmi_handle->log_info.wmi_##func_base##_buf_info;\
997 		int pos, nread, outlen;					\
998 		int i;							\
999 		uint64_t secs, usecs;					\
1000 									\
1001 		qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock);	\
1002 		if (!wmi_log->length) {					\
1003 			qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\
1004 			return wmi_bp_seq_printf(m,			\
1005 			"no elements to read from ring buffer!\n");	\
1006 		}							\
1007 									\
1008 		if (wmi_log->length <= wmi_ring_size)			\
1009 			nread = wmi_log->length;			\
1010 		else							\
1011 			nread = wmi_ring_size;				\
1012 									\
1013 		if (*(wmi_log->p_buf_tail_idx) == 0)			\
1014 			/* tail can be 0 after wrap-around */		\
1015 			pos = wmi_ring_size - 1;			\
1016 		else							\
1017 			pos = *(wmi_log->p_buf_tail_idx) - 1;		\
1018 									\
1019 		outlen = wmi_bp_seq_printf(m, "Length = %d\n", wmi_log->length);\
1020 		qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);	\
1021 		while (nread--) {					\
1022 			struct wmi_command_debug *wmi_record;		\
1023 									\
1024 			wmi_record = (struct wmi_command_debug *)	\
1025 			&(((struct wmi_command_debug *)wmi_log->buf)[pos]);\
1026 			outlen += wmi_bp_seq_printf(m, "CMD ID = %x\n",	\
1027 				(wmi_record->command));			\
1028 			qdf_log_timestamp_to_secs(wmi_record->time, &secs,\
1029 				&usecs);				\
1030 			outlen +=					\
1031 			wmi_bp_seq_printf(m, "CMD TIME = [%llu.%06llu]\n",\
1032 				secs, usecs);				\
1033 			outlen += wmi_bp_seq_printf(m, "CMD = ");	\
1034 			for (i = 0; i < (wmi_record_max_length/		\
1035 					sizeof(uint32_t)); i++)		\
1036 				outlen += wmi_bp_seq_printf(m, "%x ",	\
1037 					wmi_record->data[i]);		\
1038 			outlen += wmi_bp_seq_printf(m, "\n");		\
1039 									\
1040 			if (pos == 0)					\
1041 				pos = wmi_ring_size - 1;		\
1042 			else						\
1043 				pos--;					\
1044 		}							\
1045 		return outlen;						\
1046 	}								\
1047 
1048 #define GENERATE_EVENT_DEBUG_SHOW_FUNCS(func_base, wmi_ring_size)	\
1049 	static int debug_wmi_##func_base##_show(struct seq_file *m,	\
1050 						void *v)		\
1051 	{								\
1052 		wmi_unified_t wmi_handle = (wmi_unified_t) m->private;	\
1053 		struct wmi_log_buf_t *wmi_log =				\
1054 			&wmi_handle->log_info.wmi_##func_base##_buf_info;\
1055 		int pos, nread, outlen;					\
1056 		int i;							\
1057 		uint64_t secs, usecs;					\
1058 									\
1059 		qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock);	\
1060 		if (!wmi_log->length) {					\
1061 			qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\
1062 			return wmi_bp_seq_printf(m,			\
1063 			"no elements to read from ring buffer!\n");	\
1064 		}							\
1065 									\
1066 		if (wmi_log->length <= wmi_ring_size)			\
1067 			nread = wmi_log->length;			\
1068 		else							\
1069 			nread = wmi_ring_size;				\
1070 									\
1071 		if (*(wmi_log->p_buf_tail_idx) == 0)			\
1072 			/* tail can be 0 after wrap-around */		\
1073 			pos = wmi_ring_size - 1;			\
1074 		else							\
1075 			pos = *(wmi_log->p_buf_tail_idx) - 1;		\
1076 									\
1077 		outlen = wmi_bp_seq_printf(m, "Length = %d\n", wmi_log->length);\
1078 		qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);	\
1079 		while (nread--) {					\
1080 			struct wmi_event_debug *wmi_record;		\
1081 									\
1082 			wmi_record = (struct wmi_event_debug *)		\
1083 			&(((struct wmi_event_debug *)wmi_log->buf)[pos]);\
1084 			qdf_log_timestamp_to_secs(wmi_record->time, &secs,\
1085 				&usecs);				\
1086 			outlen += wmi_bp_seq_printf(m, "Event ID = %x\n",\
1087 				(wmi_record->event));			\
1088 			outlen +=					\
1089 			wmi_bp_seq_printf(m, "Event TIME = [%llu.%06llu]\n",\
1090 				secs, usecs);				\
1091 			outlen += wmi_bp_seq_printf(m, "CMD = ");	\
1092 			for (i = 0; i < (wmi_record_max_length/		\
1093 					sizeof(uint32_t)); i++)		\
1094 				outlen += wmi_bp_seq_printf(m, "%x ",	\
1095 					wmi_record->data[i]);		\
1096 			outlen += wmi_bp_seq_printf(m, "\n");		\
1097 									\
1098 			if (pos == 0)					\
1099 				pos = wmi_ring_size - 1;		\
1100 			else						\
1101 				pos--;					\
1102 		}							\
1103 		return outlen;						\
1104 	}
1105 
1106 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(command_log, wmi_display_size);
1107 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(command_tx_cmp_log, wmi_display_size);
1108 GENERATE_EVENT_DEBUG_SHOW_FUNCS(event_log, wmi_display_size);
1109 GENERATE_EVENT_DEBUG_SHOW_FUNCS(rx_event_log, wmi_display_size);
1110 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(mgmt_command_log, wmi_display_size);
1111 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(mgmt_command_tx_cmp_log,
1112 					wmi_display_size);
1113 GENERATE_EVENT_DEBUG_SHOW_FUNCS(mgmt_event_log, wmi_display_size);
1114 
1115 /**
1116  * debug_wmi_enable_show() - debugfs functions to display enable state of
1117  * wmi logging feature.
1118  *
1119  * @m: debugfs handler to access wmi_handle
1120  * @v: Variable arguments (not used)
1121  *
1122  * Return: always 1
1123  */
1124 static int debug_wmi_enable_show(struct seq_file *m, void *v)
1125 {
1126 	wmi_unified_t wmi_handle = (wmi_unified_t) m->private;
1127 
1128 	return wmi_bp_seq_printf(m, "%d\n",
1129 			wmi_handle->log_info.wmi_logging_enable);
1130 }
1131 
1132 /**
1133  * debug_wmi_log_size_show() - debugfs functions to display configured size of
1134  * wmi logging command/event buffer and management command/event buffer.
1135  *
1136  * @m: debugfs handler to access wmi_handle
1137  * @v: Variable arguments (not used)
1138  *
1139  * Return: Length of characters printed
1140  */
1141 static int debug_wmi_log_size_show(struct seq_file *m, void *v)
1142 {
1143 
1144 	wmi_bp_seq_printf(m, "WMI command/event log max size:%d\n",
1145 				wmi_log_max_entry);
1146 	return wmi_bp_seq_printf(m,
1147 			"WMI management command/events log max size:%d\n",
1148 			wmi_mgmt_log_max_entry);
1149 }
1150 
1151 /**
1152  * debug_wmi_##func_base##_write() - debugfs functions to clear
1153  * wmi logging command/event buffer and management command/event buffer.
1154  *
1155  * @file: file handler to access wmi_handle
1156  * @buf: received data buffer
1157  * @count: length of received buffer
1158  * @ppos: Not used
1159  *
1160  * Return: count
1161  */
1162 #define GENERATE_DEBUG_WRITE_FUNCS(func_base, wmi_ring_size, wmi_record_type)\
1163 	static ssize_t debug_wmi_##func_base##_write(struct file *file,	\
1164 				const char __user *buf,			\
1165 				size_t count, loff_t *ppos)		\
1166 	{								\
1167 		int k, ret;						\
1168 		wmi_unified_t wmi_handle =				\
1169 			((struct seq_file *)file->private_data)->private;\
1170 		struct wmi_log_buf_t *wmi_log = &wmi_handle->log_info.	\
1171 				wmi_##func_base##_buf_info;		\
1172 		char locbuf[50];					\
1173 									\
1174 		if ((!buf) || (count > 50))				\
1175 			return -EFAULT;					\
1176 									\
1177 		if (copy_from_user(locbuf, buf, count))			\
1178 			return -EFAULT;					\
1179 									\
1180 		ret = sscanf(locbuf, "%d", &k);				\
1181 		if ((ret != 1) || (k != 0)) {                           \
1182 			qdf_print("Wrong input, echo 0 to clear the wmi buffer");\
1183 			return -EINVAL;					\
1184 		}							\
1185 									\
1186 		qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock);	\
1187 		qdf_mem_zero(wmi_log->buf, wmi_ring_size *		\
1188 				sizeof(struct wmi_record_type));	\
1189 		wmi_log->length = 0;					\
1190 		*(wmi_log->p_buf_tail_idx) = 0;				\
1191 		qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);	\
1192 									\
1193 		return count;						\
1194 	}
1195 
1196 GENERATE_DEBUG_WRITE_FUNCS(command_log, wmi_log_max_entry,
1197 					wmi_command_debug);
1198 GENERATE_DEBUG_WRITE_FUNCS(command_tx_cmp_log, wmi_log_max_entry,
1199 					wmi_command_debug);
1200 GENERATE_DEBUG_WRITE_FUNCS(event_log, wmi_log_max_entry,
1201 					wmi_event_debug);
1202 GENERATE_DEBUG_WRITE_FUNCS(rx_event_log, wmi_log_max_entry,
1203 					wmi_event_debug);
1204 GENERATE_DEBUG_WRITE_FUNCS(mgmt_command_log, wmi_mgmt_log_max_entry,
1205 					wmi_command_debug);
1206 GENERATE_DEBUG_WRITE_FUNCS(mgmt_command_tx_cmp_log,
1207 		wmi_mgmt_log_max_entry, wmi_command_debug);
1208 GENERATE_DEBUG_WRITE_FUNCS(mgmt_event_log, wmi_mgmt_log_max_entry,
1209 					wmi_event_debug);
1210 
1211 /**
1212  * debug_wmi_enable_write() - debugfs functions to enable/disable
1213  * wmi logging feature.
1214  *
1215  * @file: file handler to access wmi_handle
1216  * @buf: received data buffer
1217  * @count: length of received buffer
1218  * @ppos: Not used
1219  *
1220  * Return: count
1221  */
1222 static ssize_t debug_wmi_enable_write(struct file *file, const char __user *buf,
1223 					size_t count, loff_t *ppos)
1224 {
1225 	wmi_unified_t wmi_handle =
1226 		((struct seq_file *)file->private_data)->private;
1227 	int k, ret;
1228 	char locbuf[50];
1229 
1230 	if ((!buf) || (count > 50))
1231 		return -EFAULT;
1232 
1233 	if (copy_from_user(locbuf, buf, count))
1234 		return -EFAULT;
1235 
1236 	ret = sscanf(locbuf, "%d", &k);
1237 	if ((ret != 1) || ((k != 0) && (k != 1)))
1238 		return -EINVAL;
1239 
1240 	wmi_handle->log_info.wmi_logging_enable = k;
1241 	return count;
1242 }
1243 
1244 /**
1245  * debug_wmi_log_size_write() - reserved.
1246  *
1247  * @file: file handler to access wmi_handle
1248  * @buf: received data buffer
1249  * @count: length of received buffer
1250  * @ppos: Not used
1251  *
1252  * Return: count
1253  */
1254 static ssize_t debug_wmi_log_size_write(struct file *file,
1255 		const char __user *buf, size_t count, loff_t *ppos)
1256 {
1257 	return -EINVAL;
1258 }
1259 
1260 /* Structure to maintain debug information */
1261 struct wmi_debugfs_info {
1262 	const char *name;
1263 	const struct file_operations *ops;
1264 };
1265 
1266 #define DEBUG_FOO(func_base) { .name = #func_base,			\
1267 	.ops = &debug_##func_base##_ops }
1268 
1269 /**
1270  * debug_##func_base##_open() - Open debugfs entry for respective command
1271  * and event buffer.
1272  *
1273  * @inode: node for debug dir entry
1274  * @file: file handler
1275  *
1276  * Return: open status
1277  */
1278 #define GENERATE_DEBUG_STRUCTS(func_base)				\
1279 	static int debug_##func_base##_open(struct inode *inode,	\
1280 						struct file *file)	\
1281 	{								\
1282 		return single_open(file, debug_##func_base##_show,	\
1283 				inode->i_private);			\
1284 	}								\
1285 									\
1286 									\
1287 	static struct file_operations debug_##func_base##_ops = {	\
1288 		.open		= debug_##func_base##_open,		\
1289 		.read		= seq_read,				\
1290 		.llseek		= seq_lseek,				\
1291 		.write		= debug_##func_base##_write,		\
1292 		.release	= single_release,			\
1293 	};
1294 
1295 GENERATE_DEBUG_STRUCTS(wmi_command_log);
1296 GENERATE_DEBUG_STRUCTS(wmi_command_tx_cmp_log);
1297 GENERATE_DEBUG_STRUCTS(wmi_event_log);
1298 GENERATE_DEBUG_STRUCTS(wmi_rx_event_log);
1299 GENERATE_DEBUG_STRUCTS(wmi_mgmt_command_log);
1300 GENERATE_DEBUG_STRUCTS(wmi_mgmt_command_tx_cmp_log);
1301 GENERATE_DEBUG_STRUCTS(wmi_mgmt_event_log);
1302 GENERATE_DEBUG_STRUCTS(wmi_enable);
1303 GENERATE_DEBUG_STRUCTS(wmi_log_size);
1304 
1305 struct wmi_debugfs_info wmi_debugfs_infos[NUM_DEBUG_INFOS] = {
1306 	DEBUG_FOO(wmi_command_log),
1307 	DEBUG_FOO(wmi_command_tx_cmp_log),
1308 	DEBUG_FOO(wmi_event_log),
1309 	DEBUG_FOO(wmi_rx_event_log),
1310 	DEBUG_FOO(wmi_mgmt_command_log),
1311 	DEBUG_FOO(wmi_mgmt_command_tx_cmp_log),
1312 	DEBUG_FOO(wmi_mgmt_event_log),
1313 	DEBUG_FOO(wmi_enable),
1314 	DEBUG_FOO(wmi_log_size),
1315 };
1316 
1317 
1318 /**
1319  * wmi_debugfs_create() - Create debug_fs entry for wmi logging.
1320  *
1321  * @wmi_handle: wmi handle
1322  * @par_entry: debug directory entry
1323  * @id: Index to debug info data array
1324  *
1325  * Return: none
1326  */
1327 static void wmi_debugfs_create(wmi_unified_t wmi_handle,
1328 			       struct dentry *par_entry)
1329 {
1330 	int i;
1331 
1332 	if (!par_entry)
1333 		goto out;
1334 
1335 	for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
1336 		wmi_handle->debugfs_de[i] = debugfs_create_file(
1337 				wmi_debugfs_infos[i].name, 0644, par_entry,
1338 				wmi_handle, wmi_debugfs_infos[i].ops);
1339 
1340 		if (!wmi_handle->debugfs_de[i]) {
1341 			qdf_print("debug Entry creation failed!");
1342 			goto out;
1343 		}
1344 	}
1345 
1346 	return;
1347 
1348 out:
1349 	qdf_print("debug Entry creation failed!");
1350 	wmi_log_buffer_free(wmi_handle);
1351 	return;
1352 }
1353 
1354 /**
1355  * wmi_debugfs_remove() - Remove debugfs entry for wmi logging.
1356  * @wmi_handle: wmi handle
1357  * @dentry: debugfs directory entry
1358  * @id: Index to debug info data array
1359  *
1360  * Return: none
1361  */
1362 static void wmi_debugfs_remove(wmi_unified_t wmi_handle)
1363 {
1364 	int i;
1365 	struct dentry *dentry = wmi_handle->log_info.wmi_log_debugfs_dir;
1366 
1367 	if (dentry) {
1368 		for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
1369 			if (wmi_handle->debugfs_de[i])
1370 				wmi_handle->debugfs_de[i] = NULL;
1371 		}
1372 	}
1373 
1374 	if (dentry)
1375 		debugfs_remove_recursive(dentry);
1376 }
1377 
1378 /**
1379  * wmi_debugfs_init() - debugfs functions to create debugfs directory and to
1380  * create debugfs enteries.
1381  *
1382  * @h: wmi handler
1383  *
1384  * Return: init status
1385  */
1386 static QDF_STATUS wmi_debugfs_init(wmi_unified_t wmi_handle, uint32_t pdev_idx)
1387 {
1388 	char buf[32];
1389 
1390 	snprintf(buf, sizeof(buf), "WMI_SOC%u_PDEV%u",
1391 		 wmi_handle->soc->soc_idx, pdev_idx);
1392 
1393 	wmi_handle->log_info.wmi_log_debugfs_dir =
1394 		debugfs_create_dir(buf, NULL);
1395 
1396 	if (!wmi_handle->log_info.wmi_log_debugfs_dir) {
1397 		qdf_print("error while creating debugfs dir for %s", buf);
1398 		return QDF_STATUS_E_FAILURE;
1399 	}
1400 	wmi_debugfs_create(wmi_handle,
1401 			   wmi_handle->log_info.wmi_log_debugfs_dir);
1402 
1403 	return QDF_STATUS_SUCCESS;
1404 }
1405 
1406 /**
1407  * wmi_mgmt_cmd_record() - Wrapper function for mgmt command logging macro
1408  *
1409  * @wmi_handle: wmi handle
1410  * @cmd: mgmt command
1411  * @header: pointer to 802.11 header
1412  * @vdev_id: vdev id
1413  * @chanfreq: channel frequency
1414  *
1415  * Return: none
1416  */
1417 void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
1418 			void *header, uint32_t vdev_id, uint32_t chanfreq)
1419 {
1420 
1421 	uint32_t data[CUSTOM_MGMT_CMD_DATA_SIZE];
1422 
1423 	data[0] = ((struct wmi_command_header *)header)->type;
1424 	data[1] = ((struct wmi_command_header *)header)->sub_type;
1425 	data[2] = vdev_id;
1426 	data[3] = chanfreq;
1427 
1428 	qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
1429 
1430 	WMI_MGMT_COMMAND_RECORD(wmi_handle, cmd, (uint8_t *)data);
1431 
1432 	qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
1433 }
1434 #else
1435 /**
1436  * wmi_debugfs_remove() - Remove debugfs entry for wmi logging.
1437  * @wmi_handle: wmi handle
1438  * @dentry: debugfs directory entry
1439  * @id: Index to debug info data array
1440  *
1441  * Return: none
1442  */
1443 static void wmi_debugfs_remove(wmi_unified_t wmi_handle) { }
1444 void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
1445 			void *header, uint32_t vdev_id, uint32_t chanfreq) { }
1446 static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle) { }
1447 #endif /*WMI_INTERFACE_EVENT_LOGGING */
1448 qdf_export_symbol(wmi_mgmt_cmd_record);
1449 
1450 int wmi_get_host_credits(wmi_unified_t wmi_handle);
1451 /* WMI buffer APIs */
1452 
1453 #ifdef NBUF_MEMORY_DEBUG
1454 wmi_buf_t
1455 wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint32_t len, uint8_t *file_name,
1456 		    uint32_t line_num)
1457 {
1458 	wmi_buf_t wmi_buf;
1459 
1460 	if (roundup(len + WMI_MIN_HEAD_ROOM, 4) > wmi_handle->max_msg_len) {
1461 		QDF_ASSERT(0);
1462 		return NULL;
1463 	}
1464 
1465 	wmi_buf = qdf_nbuf_alloc_debug(NULL,
1466 					roundup(len + WMI_MIN_HEAD_ROOM, 4),
1467 					WMI_MIN_HEAD_ROOM, 4, false, file_name,
1468 					line_num);
1469 
1470 	if (!wmi_buf)
1471 		return NULL;
1472 
1473 	/* Clear the wmi buffer */
1474 	OS_MEMZERO(qdf_nbuf_data(wmi_buf), len);
1475 
1476 	/*
1477 	 * Set the length of the buffer to match the allocation size.
1478 	 */
1479 	qdf_nbuf_set_pktlen(wmi_buf, len);
1480 
1481 	return wmi_buf;
1482 }
1483 qdf_export_symbol(wmi_buf_alloc_debug);
1484 
1485 void wmi_buf_free(wmi_buf_t net_buf)
1486 {
1487 	qdf_nbuf_free(net_buf);
1488 }
1489 qdf_export_symbol(wmi_buf_free);
1490 #else
1491 wmi_buf_t wmi_buf_alloc_fl(wmi_unified_t wmi_handle, uint32_t len,
1492 			   const char *func, uint32_t line)
1493 {
1494 	wmi_buf_t wmi_buf;
1495 
1496 	if (roundup(len + WMI_MIN_HEAD_ROOM, 4) > wmi_handle->max_msg_len) {
1497 		wmi_nofl_err("%s:%d, Invalid len:%d", func, line, len);
1498 		QDF_DEBUG_PANIC();
1499 		return NULL;
1500 	}
1501 
1502 	wmi_buf = qdf_nbuf_alloc_fl(NULL, roundup(len + WMI_MIN_HEAD_ROOM, 4),
1503 				    WMI_MIN_HEAD_ROOM, 4, false, func, line);
1504 	if (!wmi_buf)
1505 		return NULL;
1506 
1507 	/* Clear the wmi buffer */
1508 	OS_MEMZERO(qdf_nbuf_data(wmi_buf), len);
1509 
1510 	/*
1511 	 * Set the length of the buffer to match the allocation size.
1512 	 */
1513 	qdf_nbuf_set_pktlen(wmi_buf, len);
1514 	return wmi_buf;
1515 }
1516 qdf_export_symbol(wmi_buf_alloc_fl);
1517 
1518 void wmi_buf_free(wmi_buf_t net_buf)
1519 {
1520 	qdf_nbuf_free(net_buf);
1521 }
1522 qdf_export_symbol(wmi_buf_free);
1523 #endif
1524 
1525 /**
1526  * wmi_get_max_msg_len() - get maximum WMI message length
1527  * @wmi_handle: WMI handle.
1528  *
1529  * This function returns the maximum WMI message length
1530  *
1531  * Return: maximum WMI message length
1532  */
1533 uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle)
1534 {
1535 	return wmi_handle->max_msg_len - WMI_MIN_HEAD_ROOM;
1536 }
1537 qdf_export_symbol(wmi_get_max_msg_len);
1538 
1539 #ifndef WMI_CMD_STRINGS
1540 static uint8_t *wmi_id_to_name(uint32_t wmi_command)
1541 {
1542 	return "Invalid WMI cmd";
1543 }
1544 
1545 #endif
1546 
1547 #ifdef CONFIG_MCL
1548 static inline void wmi_log_cmd_id(uint32_t cmd_id, uint32_t tag)
1549 {
1550 	WMI_LOGD("Send WMI command:%s command_id:%d htc_tag:%d\n",
1551 		 wmi_id_to_name(cmd_id), cmd_id, tag);
1552 }
1553 
1554 /**
1555  * wmi_is_pm_resume_cmd() - check if a cmd is part of the resume sequence
1556  * @cmd_id: command to check
1557  *
1558  * Return: true if the command is part of the resume sequence.
1559  */
1560 static bool wmi_is_pm_resume_cmd(uint32_t cmd_id)
1561 {
1562 	switch (cmd_id) {
1563 	case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID:
1564 	case WMI_PDEV_RESUME_CMDID:
1565 		return true;
1566 
1567 	default:
1568 		return false;
1569 	}
1570 }
1571 #else
1572 static bool wmi_is_pm_resume_cmd(uint32_t cmd_id)
1573 {
1574 	return false;
1575 }
1576 #endif
1577 
1578 QDF_STATUS wmi_unified_cmd_send_fl(wmi_unified_t wmi_handle, wmi_buf_t buf,
1579 				   uint32_t len, uint32_t cmd_id,
1580 				   const char *func, uint32_t line)
1581 {
1582 	HTC_PACKET *pkt;
1583 	QDF_STATUS status;
1584 	uint16_t htc_tag = 0;
1585 
1586 	if (wmi_get_runtime_pm_inprogress(wmi_handle)) {
1587 		htc_tag =
1588 			(uint16_t)wmi_handle->ops->wmi_set_htc_tx_tag(
1589 						wmi_handle, buf, cmd_id);
1590 	} else if (qdf_atomic_read(&wmi_handle->is_target_suspended) &&
1591 		(!wmi_is_pm_resume_cmd(cmd_id))) {
1592 		wmi_nofl_err("%s:%d, Target is suspended", func, line);
1593 		QDF_DEBUG_PANIC();
1594 		return QDF_STATUS_E_BUSY;
1595 	}
1596 	if (wmi_handle->wmi_stopinprogress) {
1597 		wmi_nofl_err("%s:%d, WMI stop in progress", func, line);
1598 		return QDF_STATUS_E_INVAL;
1599 	}
1600 
1601 #ifndef WMI_NON_TLV_SUPPORT
1602 	/* Do sanity check on the TLV parameter structure */
1603 	if (wmi_handle->target_type == WMI_TLV_TARGET) {
1604 		void *buf_ptr = (void *)qdf_nbuf_data(buf);
1605 
1606 		if (wmi_handle->ops->wmi_check_command_params(NULL, buf_ptr, len, cmd_id)
1607 			!= 0) {
1608 			wmi_nofl_err("%s:%d, Invalid WMI Param Buffer for Cmd:%d",
1609 				     func, line, cmd_id);
1610 			return QDF_STATUS_E_INVAL;
1611 		}
1612 	}
1613 #endif
1614 
1615 	if (qdf_nbuf_push_head(buf, sizeof(WMI_CMD_HDR)) == NULL) {
1616 		wmi_nofl_err("%s:%d, Failed to send cmd %x, no memory",
1617 			     func, line, cmd_id);
1618 		return QDF_STATUS_E_NOMEM;
1619 	}
1620 
1621 	qdf_mem_zero(qdf_nbuf_data(buf), sizeof(WMI_CMD_HDR));
1622 	WMI_SET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id);
1623 
1624 	qdf_atomic_inc(&wmi_handle->pending_cmds);
1625 	if (qdf_atomic_read(&wmi_handle->pending_cmds) >=
1626 			wmi_handle->wmi_max_cmds) {
1627 		wmi_nofl_err("hostcredits = %d",
1628 			     wmi_get_host_credits(wmi_handle));
1629 		htc_dump_counter_info(wmi_handle->htc_handle);
1630 		qdf_atomic_dec(&wmi_handle->pending_cmds);
1631 		wmi_nofl_err("%s:%d, MAX %d WMI Pending cmds reached",
1632 			     func, line, wmi_handle->wmi_max_cmds);
1633 		QDF_BUG(0);
1634 		return QDF_STATUS_E_BUSY;
1635 	}
1636 
1637 	pkt = qdf_mem_malloc_fl(sizeof(*pkt), func, line);
1638 	if (!pkt) {
1639 		qdf_atomic_dec(&wmi_handle->pending_cmds);
1640 		return QDF_STATUS_E_NOMEM;
1641 	}
1642 
1643 	SET_HTC_PACKET_INFO_TX(pkt,
1644 			       NULL,
1645 			       qdf_nbuf_data(buf), len + sizeof(WMI_CMD_HDR),
1646 			       wmi_handle->wmi_endpoint_id, htc_tag);
1647 
1648 	SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf);
1649 #ifdef CONFIG_MCL
1650 	wmi_log_cmd_id(cmd_id, htc_tag);
1651 #endif
1652 	wmi_ext_dbg_msg_cmd_record(wmi_handle,
1653 				   qdf_nbuf_data(buf), qdf_nbuf_len(buf));
1654 #ifdef WMI_INTERFACE_EVENT_LOGGING
1655 	if (wmi_handle->log_info.wmi_logging_enable) {
1656 		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
1657 		/*
1658 		 * Record 16 bytes of WMI cmd data -
1659 		 * exclude TLV and WMI headers
1660 		 *
1661 		 * WMI mgmt command already recorded in wmi_mgmt_cmd_record
1662 		 */
1663 		if (wmi_handle->ops->is_management_record(cmd_id) == false) {
1664 			WMI_COMMAND_RECORD(wmi_handle, cmd_id,
1665 					qdf_nbuf_data(buf) +
1666 			 wmi_handle->log_info.buf_offset_command);
1667 		}
1668 		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
1669 	}
1670 #endif
1671 
1672 	status = htc_send_pkt(wmi_handle->htc_handle, pkt);
1673 
1674 	if (QDF_STATUS_SUCCESS != status) {
1675 		qdf_atomic_dec(&wmi_handle->pending_cmds);
1676 		wmi_nofl_err("%s:%d, htc_send_pkt failed, status:%d",
1677 			     func, line, status);
1678 		qdf_mem_free(pkt);
1679 		return status;
1680 	}
1681 
1682 	return QDF_STATUS_SUCCESS;
1683 }
1684 qdf_export_symbol(wmi_unified_cmd_send_fl);
1685 
1686 /**
1687  * wmi_unified_get_event_handler_ix() - gives event handler's index
1688  * @wmi_handle: handle to wmi
1689  * @event_id: wmi  event id
1690  *
1691  * Return: event handler's index
1692  */
1693 static int wmi_unified_get_event_handler_ix(wmi_unified_t wmi_handle,
1694 					    uint32_t event_id)
1695 {
1696 	uint32_t idx = 0;
1697 	int32_t invalid_idx = -1;
1698 	struct wmi_soc *soc = wmi_handle->soc;
1699 
1700 	for (idx = 0; (idx < soc->max_event_idx &&
1701 		       idx < WMI_UNIFIED_MAX_EVENT); ++idx) {
1702 		if (wmi_handle->event_id[idx] == event_id &&
1703 		    wmi_handle->event_handler[idx] != NULL) {
1704 			return idx;
1705 		}
1706 	}
1707 
1708 	return invalid_idx;
1709 }
1710 
1711 /**
1712  * wmi_unified_register_event() - register wmi event handler
1713  * @wmi_handle: handle to wmi
1714  * @event_id: wmi event id
1715  * @handler_func: wmi event handler function
1716  *
1717  * Return: 0 on success
1718  */
1719 int wmi_unified_register_event(wmi_unified_t wmi_handle,
1720 				       uint32_t event_id,
1721 				       wmi_unified_event_handler handler_func)
1722 {
1723 	uint32_t idx = 0;
1724 	uint32_t evt_id;
1725 	struct wmi_soc *soc = wmi_handle->soc;
1726 
1727 	if (event_id >= wmi_events_max ||
1728 		wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) {
1729 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1730 			  "%s: Event id %d is unavailable",
1731 					__func__, event_id);
1732 		return QDF_STATUS_E_FAILURE;
1733 	}
1734 	evt_id = wmi_handle->wmi_events[event_id];
1735 	if (wmi_unified_get_event_handler_ix(wmi_handle, evt_id) != -1) {
1736 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1737 			  "%s : event handler already registered 0x%x",
1738 				__func__, evt_id);
1739 		return QDF_STATUS_E_FAILURE;
1740 	}
1741 	if (soc->max_event_idx == WMI_UNIFIED_MAX_EVENT) {
1742 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1743 			  "%s : no more event handlers 0x%x",
1744 					__func__, evt_id);
1745 		return QDF_STATUS_E_FAILURE;
1746 	}
1747 	idx = soc->max_event_idx;
1748 	wmi_handle->event_handler[idx] = handler_func;
1749 	wmi_handle->event_id[idx] = evt_id;
1750 	qdf_spin_lock_bh(&soc->ctx_lock);
1751 	wmi_handle->ctx[idx] = WMI_RX_UMAC_CTX;
1752 	qdf_spin_unlock_bh(&soc->ctx_lock);
1753 	soc->max_event_idx++;
1754 
1755 	return 0;
1756 }
1757 
1758 /**
1759  * wmi_unified_register_event_handler() - register wmi event handler
1760  * @wmi_handle: handle to wmi
1761  * @event_id: wmi event id
1762  * @handler_func: wmi event handler function
1763  * @rx_ctx: rx execution context for wmi rx events
1764  *
1765  * This API is to support legacy requirements. Will be deprecated in future.
1766  * Return: 0 on success
1767  */
1768 int wmi_unified_register_event_handler(wmi_unified_t wmi_handle,
1769 				       wmi_conv_event_id event_id,
1770 				       wmi_unified_event_handler handler_func,
1771 				       uint8_t rx_ctx)
1772 {
1773 	uint32_t idx = 0;
1774 	uint32_t evt_id;
1775 	struct wmi_soc *soc = wmi_handle->soc;
1776 
1777 	if (event_id >= wmi_events_max ||
1778 		wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) {
1779 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1780 			  "%s: Event id %d is unavailable",
1781 					__func__, event_id);
1782 		return QDF_STATUS_E_FAILURE;
1783 	}
1784 	evt_id = wmi_handle->wmi_events[event_id];
1785 
1786 	if (wmi_unified_get_event_handler_ix(wmi_handle, evt_id) != -1) {
1787 		qdf_print("event handler already registered 0x%x",
1788 			  evt_id);
1789 		return QDF_STATUS_E_FAILURE;
1790 	}
1791 	if (soc->max_event_idx == WMI_UNIFIED_MAX_EVENT) {
1792 		qdf_print("no more event handlers 0x%x",
1793 			  evt_id);
1794 		return QDF_STATUS_E_FAILURE;
1795 	}
1796 	QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
1797 		  "Registered event handler for event 0x%8x", evt_id);
1798 	idx = soc->max_event_idx;
1799 	wmi_handle->event_handler[idx] = handler_func;
1800 	wmi_handle->event_id[idx] = evt_id;
1801 	qdf_spin_lock_bh(&soc->ctx_lock);
1802 	wmi_handle->ctx[idx] = rx_ctx;
1803 	qdf_spin_unlock_bh(&soc->ctx_lock);
1804 	soc->max_event_idx++;
1805 
1806 	return 0;
1807 }
1808 qdf_export_symbol(wmi_unified_register_event_handler);
1809 
1810 /**
1811  * wmi_unified_unregister_event() - unregister wmi event handler
1812  * @wmi_handle: handle to wmi
1813  * @event_id: wmi event id
1814  *
1815  * Return: 0 on success
1816  */
1817 int wmi_unified_unregister_event(wmi_unified_t wmi_handle,
1818 					 uint32_t event_id)
1819 {
1820 	uint32_t idx = 0;
1821 	uint32_t evt_id;
1822 	struct wmi_soc *soc = wmi_handle->soc;
1823 
1824 	if (event_id >= wmi_events_max ||
1825 		wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) {
1826 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1827 			  "%s: Event id %d is unavailable",
1828 					__func__, event_id);
1829 		return QDF_STATUS_E_FAILURE;
1830 	}
1831 	evt_id = wmi_handle->wmi_events[event_id];
1832 
1833 	idx = wmi_unified_get_event_handler_ix(wmi_handle, evt_id);
1834 	if (idx == -1) {
1835 		qdf_print("event handler is not registered: evt id 0x%x",
1836 			  evt_id);
1837 		return QDF_STATUS_E_FAILURE;
1838 	}
1839 	wmi_handle->event_handler[idx] = NULL;
1840 	wmi_handle->event_id[idx] = 0;
1841 	--soc->max_event_idx;
1842 	wmi_handle->event_handler[idx] =
1843 		wmi_handle->event_handler[soc->max_event_idx];
1844 	wmi_handle->event_id[idx] =
1845 		wmi_handle->event_id[soc->max_event_idx];
1846 
1847 	return 0;
1848 }
1849 
1850 /**
1851  * wmi_unified_unregister_event_handler() - unregister wmi event handler
1852  * @wmi_handle: handle to wmi
1853  * @event_id: wmi event id
1854  *
1855  * Return: 0 on success
1856  */
1857 int wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle,
1858 					 wmi_conv_event_id event_id)
1859 {
1860 	uint32_t idx = 0;
1861 	uint32_t evt_id;
1862 	struct wmi_soc *soc = wmi_handle->soc;
1863 
1864 	if (event_id >= wmi_events_max ||
1865 		wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) {
1866 		qdf_print("Event id %d is unavailable",
1867 			  event_id);
1868 		return QDF_STATUS_E_FAILURE;
1869 	}
1870 	evt_id = wmi_handle->wmi_events[event_id];
1871 
1872 	idx = wmi_unified_get_event_handler_ix(wmi_handle, evt_id);
1873 	if (idx == -1) {
1874 		qdf_print("event handler is not registered: evt id 0x%x",
1875 			  evt_id);
1876 		return QDF_STATUS_E_FAILURE;
1877 	}
1878 	wmi_handle->event_handler[idx] = NULL;
1879 	wmi_handle->event_id[idx] = 0;
1880 	--soc->max_event_idx;
1881 	wmi_handle->event_handler[idx] =
1882 		wmi_handle->event_handler[soc->max_event_idx];
1883 	wmi_handle->event_id[idx] =
1884 		wmi_handle->event_id[soc->max_event_idx];
1885 
1886 	return 0;
1887 }
1888 qdf_export_symbol(wmi_unified_unregister_event_handler);
1889 
1890 /**
1891  * wmi_process_fw_event_default_ctx() - process in default caller context
1892  * @wmi_handle: handle to wmi
1893  * @htc_packet: pointer to htc packet
1894  * @exec_ctx: execution context for wmi fw event
1895  *
1896  * Event process by below function will be in default caller context.
1897  * wmi internally provides rx work thread processing context.
1898  *
1899  * Return: none
1900  */
1901 static void wmi_process_fw_event_default_ctx(struct wmi_unified *wmi_handle,
1902 		       HTC_PACKET *htc_packet, uint8_t exec_ctx)
1903 {
1904 	wmi_buf_t evt_buf;
1905 	evt_buf = (wmi_buf_t) htc_packet->pPktContext;
1906 
1907 #ifndef CONFIG_MCL
1908 	wmi_handle->rx_ops.wma_process_fw_event_handler_cbk
1909 		(wmi_handle->scn_handle, evt_buf, exec_ctx);
1910 #else
1911 	wmi_handle->rx_ops.wma_process_fw_event_handler_cbk(wmi_handle,
1912 					 htc_packet, exec_ctx);
1913 #endif
1914 
1915 	return;
1916 }
1917 
1918 /**
1919  * wmi_process_fw_event_worker_thread_ctx() - process in worker thread context
1920  * @wmi_handle: handle to wmi
1921  * @htc_packet: pointer to htc packet
1922  *
1923  * Event process by below function will be in worker thread context.
1924  * Use this method for events which are not critical and not
1925  * handled in protocol stack.
1926  *
1927  * Return: none
1928  */
1929 void wmi_process_fw_event_worker_thread_ctx(struct wmi_unified *wmi_handle,
1930 					    HTC_PACKET *htc_packet)
1931 {
1932 	wmi_buf_t evt_buf;
1933 
1934 	evt_buf = (wmi_buf_t) htc_packet->pPktContext;
1935 
1936 	qdf_spin_lock_bh(&wmi_handle->eventq_lock);
1937 	qdf_nbuf_queue_add(&wmi_handle->event_queue, evt_buf);
1938 	qdf_spin_unlock_bh(&wmi_handle->eventq_lock);
1939 	qdf_queue_work(0, wmi_handle->wmi_rx_work_queue,
1940 			&wmi_handle->rx_event_work);
1941 
1942 	return;
1943 }
1944 
1945 qdf_export_symbol(wmi_process_fw_event_worker_thread_ctx);
1946 
1947 /**
1948  * wmi_get_pdev_ep: Get wmi handle based on endpoint
1949  * @soc: handle to wmi soc
1950  * @ep: endpoint id
1951  *
1952  * Return: none
1953  */
1954 static struct wmi_unified *wmi_get_pdev_ep(struct wmi_soc *soc,
1955 						HTC_ENDPOINT_ID ep)
1956 {
1957 	uint32_t i;
1958 
1959 	for (i = 0; i < WMI_MAX_RADIOS; i++)
1960 		if (soc->wmi_endpoint_id[i] == ep)
1961 			break;
1962 
1963 	if (i == WMI_MAX_RADIOS)
1964 		return NULL;
1965 
1966 	return soc->wmi_pdev[i];
1967 }
1968 
1969 /**
1970  * wmi_control_rx() - process fw events callbacks
1971  * @ctx: handle to wmi
1972  * @htc_packet: pointer to htc packet
1973  *
1974  * Return: none
1975  */
1976 static void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet)
1977 {
1978 	struct wmi_soc *soc = (struct wmi_soc *) ctx;
1979 	struct wmi_unified *wmi_handle;
1980 	wmi_buf_t evt_buf;
1981 	uint32_t id;
1982 	uint32_t idx = 0;
1983 	enum wmi_rx_exec_ctx exec_ctx;
1984 
1985 	evt_buf = (wmi_buf_t) htc_packet->pPktContext;
1986 
1987 	wmi_handle = wmi_get_pdev_ep(soc, htc_packet->Endpoint);
1988 	if (wmi_handle == NULL) {
1989 		qdf_print
1990 		("unable to get wmi_handle to Endpoint %d\n",
1991 		 htc_packet->Endpoint);
1992 		qdf_nbuf_free(evt_buf);
1993 		return;
1994 	}
1995 
1996 	id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
1997 	idx = wmi_unified_get_event_handler_ix(wmi_handle, id);
1998 	if (qdf_unlikely(idx == A_ERROR)) {
1999 		WMI_LOGD("%s :event handler is not registered: event id 0x%x\n",
2000 				 __func__, id);
2001 		qdf_nbuf_free(evt_buf);
2002 		return;
2003 	}
2004 	qdf_spin_lock_bh(&soc->ctx_lock);
2005 	exec_ctx = wmi_handle->ctx[idx];
2006 	qdf_spin_unlock_bh(&soc->ctx_lock);
2007 
2008 #ifdef WMI_INTERFACE_EVENT_LOGGING
2009 	if (wmi_handle->log_info.wmi_logging_enable) {
2010 		uint8_t *data;
2011 		data = qdf_nbuf_data(evt_buf);
2012 
2013 		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
2014 		/* Exclude 4 bytes of TLV header */
2015 		WMI_RX_EVENT_RECORD(wmi_handle, id, data +
2016 				wmi_handle->log_info.buf_offset_event);
2017 		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
2018 	}
2019 #endif
2020 
2021 	if (exec_ctx == WMI_RX_WORK_CTX) {
2022 		wmi_process_fw_event_worker_thread_ctx
2023 					(wmi_handle, htc_packet);
2024 	} else if (exec_ctx > WMI_RX_WORK_CTX) {
2025 		wmi_process_fw_event_default_ctx
2026 					(wmi_handle, htc_packet, exec_ctx);
2027 	} else {
2028 		qdf_print("Invalid event context %d", exec_ctx);
2029 		qdf_nbuf_free(evt_buf);
2030 	}
2031 
2032 }
2033 
2034 /**
2035  * wmi_process_fw_event() - process any fw event
2036  * @wmi_handle: wmi handle
2037  * @evt_buf: fw event buffer
2038  *
2039  * This function process fw event in caller context
2040  *
2041  * Return: none
2042  */
2043 void wmi_process_fw_event(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf)
2044 {
2045 	__wmi_control_rx(wmi_handle, evt_buf);
2046 }
2047 
2048 /**
2049  * __wmi_control_rx() - process serialize wmi event callback
2050  * @wmi_handle: wmi handle
2051  * @evt_buf: fw event buffer
2052  *
2053  * Return: none
2054  */
2055 void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf)
2056 {
2057 	uint32_t id;
2058 	uint8_t *data;
2059 	uint32_t len;
2060 	void *wmi_cmd_struct_ptr = NULL;
2061 #ifndef WMI_NON_TLV_SUPPORT
2062 	int tlv_ok_status = 0;
2063 #endif
2064 	uint32_t idx = 0;
2065 
2066 	id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
2067 
2068 	wmi_ext_dbg_msg_event_record(wmi_handle, qdf_nbuf_data(evt_buf),
2069 				     qdf_nbuf_len(evt_buf));
2070 
2071 	if (qdf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
2072 		goto end;
2073 
2074 	data = qdf_nbuf_data(evt_buf);
2075 	len = qdf_nbuf_len(evt_buf);
2076 
2077 #ifndef WMI_NON_TLV_SUPPORT
2078 	if (wmi_handle->target_type == WMI_TLV_TARGET) {
2079 		/* Validate and pad(if necessary) the TLVs */
2080 		tlv_ok_status =
2081 			wmi_handle->ops->wmi_check_and_pad_event(wmi_handle->scn_handle,
2082 							data, len, id,
2083 							&wmi_cmd_struct_ptr);
2084 		if (tlv_ok_status != 0) {
2085 			QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
2086 				  "%s: Error: id=0x%x, wmitlv check status=%d",
2087 				  __func__, id, tlv_ok_status);
2088 			goto end;
2089 		}
2090 	}
2091 #endif
2092 
2093 	idx = wmi_unified_get_event_handler_ix(wmi_handle, id);
2094 	if (idx == A_ERROR) {
2095 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
2096 		   "%s : event handler is not registered: event id 0x%x",
2097 			__func__, id);
2098 		goto end;
2099 	}
2100 #ifdef WMI_INTERFACE_EVENT_LOGGING
2101 	if (wmi_handle->log_info.wmi_logging_enable) {
2102 		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
2103 		/* Exclude 4 bytes of TLV header */
2104 		if (wmi_handle->ops->is_management_record(id)) {
2105 			WMI_MGMT_EVENT_RECORD(wmi_handle, id, data
2106 				+ wmi_handle->log_info.buf_offset_event);
2107 		} else {
2108 			WMI_EVENT_RECORD(wmi_handle, id, data +
2109 					wmi_handle->log_info.buf_offset_event);
2110 		}
2111 		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
2112 	}
2113 #endif
2114 	/* Call the WMI registered event handler */
2115 	if (wmi_handle->target_type == WMI_TLV_TARGET)
2116 		wmi_handle->event_handler[idx] (wmi_handle->scn_handle,
2117 			wmi_cmd_struct_ptr, len);
2118 	else
2119 		wmi_handle->event_handler[idx] (wmi_handle->scn_handle,
2120 			data, len);
2121 
2122 end:
2123 	/* Free event buffer and allocated event tlv */
2124 #ifndef WMI_NON_TLV_SUPPORT
2125 	if (wmi_handle->target_type == WMI_TLV_TARGET)
2126 		wmi_handle->ops->wmi_free_allocated_event(id, &wmi_cmd_struct_ptr);
2127 #endif
2128 
2129 	qdf_nbuf_free(evt_buf);
2130 
2131 }
2132 
2133 #define WMI_WQ_WD_TIMEOUT (30 * 1000) /* 30s */
2134 
2135 static inline void wmi_workqueue_watchdog_warn(uint32_t msg_type_id)
2136 {
2137 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2138 		  "%s: WLAN_BUG_RCA: Message type %x has exceeded its alloted time of %ds",
2139 		  __func__, msg_type_id, WMI_WQ_WD_TIMEOUT / 1000);
2140 }
2141 
2142 #ifdef CONFIG_SLUB_DEBUG_ON
2143 static void wmi_workqueue_watchdog_bite(void *arg)
2144 {
2145 	struct wmi_wq_dbg_info *info = arg;
2146 
2147 	wmi_workqueue_watchdog_warn(info->wd_msg_type_id);
2148 	qdf_print_thread_trace(info->task);
2149 
2150 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2151 		  "%s: Going down for WMI WQ Watchdog Bite!", __func__);
2152 	QDF_BUG(0);
2153 }
2154 #else
2155 static inline void wmi_workqueue_watchdog_bite(void *arg)
2156 {
2157 	struct wmi_wq_dbg_info *info = arg;
2158 
2159 	wmi_workqueue_watchdog_warn(info->wd_msg_type_id);
2160 }
2161 #endif
2162 
2163 /**
2164  * wmi_rx_event_work() - process rx event in rx work queue context
2165  * @arg: opaque pointer to wmi handle
2166  *
2167  * This function process any fw event to serialize it through rx worker thread.
2168  *
2169  * Return: none
2170  */
2171 static void wmi_rx_event_work(void *arg)
2172 {
2173 	wmi_buf_t buf;
2174 	struct wmi_unified *wmi = arg;
2175 	qdf_timer_t wd_timer;
2176 	struct wmi_wq_dbg_info info;
2177 
2178 	/* initialize WMI workqueue watchdog timer */
2179 	qdf_timer_init(NULL, &wd_timer, &wmi_workqueue_watchdog_bite,
2180 			&info, QDF_TIMER_TYPE_SW);
2181 	qdf_spin_lock_bh(&wmi->eventq_lock);
2182 	buf = qdf_nbuf_queue_remove(&wmi->event_queue);
2183 	qdf_spin_unlock_bh(&wmi->eventq_lock);
2184 	while (buf) {
2185 		qdf_timer_start(&wd_timer, WMI_WQ_WD_TIMEOUT);
2186 		info.wd_msg_type_id =
2187 		   WMI_GET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID);
2188 		info.wmi_wq = wmi->wmi_rx_work_queue;
2189 		info.task = qdf_get_current_task();
2190 		__wmi_control_rx(wmi, buf);
2191 		qdf_timer_stop(&wd_timer);
2192 		qdf_spin_lock_bh(&wmi->eventq_lock);
2193 		buf = qdf_nbuf_queue_remove(&wmi->event_queue);
2194 		qdf_spin_unlock_bh(&wmi->eventq_lock);
2195 	}
2196 	qdf_timer_free(&wd_timer);
2197 }
2198 
2199 #ifdef FEATURE_RUNTIME_PM
2200 /**
2201  * wmi_runtime_pm_init() - initialize runtime pm wmi variables
2202  * @wmi_handle: wmi context
2203  */
2204 static void wmi_runtime_pm_init(struct wmi_unified *wmi_handle)
2205 {
2206 	qdf_atomic_init(&wmi_handle->runtime_pm_inprogress);
2207 }
2208 
2209 /**
2210  * wmi_set_runtime_pm_inprogress() - set runtime pm progress flag
2211  * @wmi_handle: wmi context
2212  * @val: runtime pm progress flag
2213  */
2214 void wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, A_BOOL val)
2215 {
2216 	qdf_atomic_set(&wmi_handle->runtime_pm_inprogress, val);
2217 }
2218 
2219 /**
2220  * wmi_get_runtime_pm_inprogress() - get runtime pm progress flag
2221  * @wmi_handle: wmi context
2222  */
2223 inline bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle)
2224 {
2225 	return qdf_atomic_read(&wmi_handle->runtime_pm_inprogress);
2226 }
2227 #else
2228 static void wmi_runtime_pm_init(struct wmi_unified *wmi_handle)
2229 {
2230 }
2231 #endif
2232 
2233 /**
2234  * wmi_unified_get_soc_handle: Get WMI SoC handle
2235  * @param wmi_handle: WMI context got from wmi_attach
2236  *
2237  * return: Pointer to Soc handle
2238  */
2239 void *wmi_unified_get_soc_handle(struct wmi_unified *wmi_handle)
2240 {
2241 	return wmi_handle->soc;
2242 }
2243 
2244 /**
2245  * wmi_interface_logging_init: Interface looging init
2246  * @param wmi_handle: Pointer to wmi handle object
2247  *
2248  * return: None
2249  */
2250 #ifdef WMI_INTERFACE_EVENT_LOGGING
2251 static inline void wmi_interface_logging_init(struct wmi_unified *wmi_handle,
2252 					      uint32_t pdev_idx)
2253 {
2254 	if (QDF_STATUS_SUCCESS == wmi_log_init(wmi_handle)) {
2255 		qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock);
2256 		wmi_debugfs_init(wmi_handle, pdev_idx);
2257 	}
2258 }
2259 #else
2260 static inline void wmi_interface_logging_init(struct wmi_unified *wmi_handle,
2261 					      uint32_t pdev_idx)
2262 {
2263 }
2264 #endif
2265 
2266 /**
2267  * wmi_target_params_init: Target specific params init
2268  * @param wmi_soc: Pointer to wmi soc object
2269  * @param wmi_handle: Pointer to wmi handle object
2270  *
2271  * return: None
2272  */
2273 #ifndef CONFIG_MCL
2274 static inline void wmi_target_params_init(struct wmi_soc *soc,
2275 				struct wmi_unified *wmi_handle)
2276 {
2277 	wmi_handle->pdev_param = soc->pdev_param;
2278 	wmi_handle->vdev_param = soc->vdev_param;
2279 	wmi_handle->services = soc->services;
2280 }
2281 #else
2282 static inline void wmi_target_params_init(struct wmi_soc *soc,
2283 				struct wmi_unified *wmi_handle)
2284 {
2285 	wmi_handle->services = soc->services;
2286 }
2287 #endif
2288 
2289 /**
2290  * wmi_unified_get_pdev_handle: Get WMI SoC handle
2291  * @param wmi_soc: Pointer to wmi soc object
2292  * @param pdev_idx: pdev index
2293  *
2294  * return: Pointer to wmi handle or NULL on failure
2295  */
2296 void *wmi_unified_get_pdev_handle(struct wmi_soc *soc, uint32_t pdev_idx)
2297 {
2298 	struct wmi_unified *wmi_handle;
2299 
2300 	if (pdev_idx >= WMI_MAX_RADIOS)
2301 		return NULL;
2302 
2303 	if (soc->wmi_pdev[pdev_idx] == NULL) {
2304 		wmi_handle =
2305 			(struct wmi_unified *) qdf_mem_malloc(
2306 					sizeof(struct wmi_unified));
2307 		if (wmi_handle == NULL) {
2308 			qdf_print("allocation of wmi handle failed %zu",
2309 				  sizeof(struct wmi_unified));
2310 			return NULL;
2311 		}
2312 		wmi_handle->scn_handle = soc->scn_handle;
2313 		wmi_handle->event_id = soc->event_id;
2314 		wmi_handle->event_handler = soc->event_handler;
2315 		wmi_handle->ctx = soc->ctx;
2316 		wmi_handle->ops = soc->ops;
2317 		qdf_spinlock_create(&wmi_handle->eventq_lock);
2318 		qdf_nbuf_queue_init(&wmi_handle->event_queue);
2319 
2320 		qdf_create_work(0, &wmi_handle->rx_event_work,
2321 				wmi_rx_event_work, wmi_handle);
2322 		wmi_handle->wmi_rx_work_queue =
2323 			qdf_create_workqueue("wmi_rx_event_work_queue");
2324 		if (NULL == wmi_handle->wmi_rx_work_queue) {
2325 			WMI_LOGE("failed to create wmi_rx_event_work_queue");
2326 			goto error;
2327 		}
2328 		wmi_handle->wmi_events = soc->wmi_events;
2329 		wmi_target_params_init(soc, wmi_handle);
2330 		wmi_handle->soc = soc;
2331 		wmi_interface_logging_init(wmi_handle, pdev_idx);
2332 		qdf_atomic_init(&wmi_handle->pending_cmds);
2333 		qdf_atomic_init(&wmi_handle->is_target_suspended);
2334 		wmi_handle->target_type = soc->target_type;
2335 		wmi_handle->wmi_max_cmds = soc->wmi_max_cmds;
2336 
2337 		soc->wmi_pdev[pdev_idx] = wmi_handle;
2338 	} else
2339 		wmi_handle = soc->wmi_pdev[pdev_idx];
2340 
2341 	wmi_handle->wmi_stopinprogress = 0;
2342 	wmi_handle->wmi_endpoint_id = soc->wmi_endpoint_id[pdev_idx];
2343 	wmi_handle->htc_handle = soc->htc_handle;
2344 	wmi_handle->max_msg_len = soc->max_msg_len[pdev_idx];
2345 
2346 	return wmi_handle;
2347 
2348 error:
2349 	qdf_mem_free(wmi_handle);
2350 
2351 	return NULL;
2352 }
2353 qdf_export_symbol(wmi_unified_get_pdev_handle);
2354 
2355 static void (*wmi_attach_register[WMI_MAX_TARGET_TYPE])(wmi_unified_t);
2356 
2357 void wmi_unified_register_module(enum wmi_target_type target_type,
2358 			void (*wmi_attach)(wmi_unified_t wmi_handle))
2359 {
2360 	if (target_type < WMI_MAX_TARGET_TYPE)
2361 		wmi_attach_register[target_type] = wmi_attach;
2362 
2363 	return;
2364 }
2365 qdf_export_symbol(wmi_unified_register_module);
2366 
2367 /**
2368  * wmi_unified_attach() -  attach for unified WMI
2369  * @scn_handle: handle to SCN
2370  * @osdev: OS device context
2371  * @target_type: TLV or not-TLV based target
2372  * @use_cookie: cookie based allocation enabled/disabled
2373  * @ops: umac rx callbacks
2374  * @psoc: objmgr psoc
2375  *
2376  * @Return: wmi handle.
2377  */
2378 void *wmi_unified_attach(void *scn_handle,
2379 			 struct wmi_unified_attach_params *param)
2380 {
2381 	struct wmi_unified *wmi_handle;
2382 	struct wmi_soc *soc;
2383 
2384 	soc = (struct wmi_soc *) qdf_mem_malloc(sizeof(struct wmi_soc));
2385 	if (soc == NULL) {
2386 		qdf_print("Allocation of wmi_soc failed %zu",
2387 			  sizeof(struct wmi_soc));
2388 		return NULL;
2389 	}
2390 
2391 	wmi_handle =
2392 		(struct wmi_unified *) qdf_mem_malloc(
2393 			sizeof(struct wmi_unified));
2394 	if (wmi_handle == NULL) {
2395 		qdf_mem_free(soc);
2396 		qdf_print("allocation of wmi handle failed %zu",
2397 			  sizeof(struct wmi_unified));
2398 		return NULL;
2399 	}
2400 	wmi_handle->soc = soc;
2401 	wmi_handle->soc->soc_idx = param->soc_id;
2402 	wmi_handle->event_id = soc->event_id;
2403 	wmi_handle->event_handler = soc->event_handler;
2404 	wmi_handle->ctx = soc->ctx;
2405 	wmi_handle->wmi_events = soc->wmi_events;
2406 	wmi_target_params_init(soc, wmi_handle);
2407 	wmi_handle->scn_handle = scn_handle;
2408 	soc->scn_handle = scn_handle;
2409 	qdf_atomic_init(&wmi_handle->pending_cmds);
2410 	qdf_atomic_init(&wmi_handle->is_target_suspended);
2411 	wmi_runtime_pm_init(wmi_handle);
2412 	qdf_spinlock_create(&wmi_handle->eventq_lock);
2413 	qdf_nbuf_queue_init(&wmi_handle->event_queue);
2414 	qdf_create_work(0, &wmi_handle->rx_event_work,
2415 			wmi_rx_event_work, wmi_handle);
2416 	wmi_handle->wmi_rx_work_queue =
2417 		qdf_create_workqueue("wmi_rx_event_work_queue");
2418 	if (NULL == wmi_handle->wmi_rx_work_queue) {
2419 		WMI_LOGE("failed to create wmi_rx_event_work_queue");
2420 		goto error;
2421 	}
2422 	wmi_interface_logging_init(wmi_handle, WMI_HOST_PDEV_ID_0);
2423 	/* Attach mc_thread context processing function */
2424 	wmi_handle->rx_ops.wma_process_fw_event_handler_cbk =
2425 				param->rx_ops->wma_process_fw_event_handler_cbk;
2426 	wmi_handle->target_type = param->target_type;
2427 	soc->target_type = param->target_type;
2428 
2429 	if (param->target_type >= WMI_MAX_TARGET_TYPE)
2430 		goto error;
2431 
2432 	if (wmi_attach_register[param->target_type]) {
2433 		wmi_attach_register[param->target_type](wmi_handle);
2434 	} else {
2435 		WMI_LOGE("wmi attach is not registered");
2436 		goto error;
2437 	}
2438 	/* Assign target cookie capablity */
2439 	wmi_handle->use_cookie = param->use_cookie;
2440 	wmi_handle->osdev = param->osdev;
2441 	wmi_handle->wmi_stopinprogress = 0;
2442 	wmi_handle->wmi_max_cmds = param->max_commands;
2443 	soc->wmi_max_cmds = param->max_commands;
2444 	/* Increase the ref count once refcount infra is present */
2445 	soc->wmi_psoc = param->psoc;
2446 	qdf_spinlock_create(&soc->ctx_lock);
2447 
2448 	soc->ops = wmi_handle->ops;
2449 	soc->wmi_pdev[0] = wmi_handle;
2450 	if (wmi_ext_dbgfs_init(wmi_handle) != QDF_STATUS_SUCCESS)
2451 		qdf_print("failed to initialize wmi extended debugfs");
2452 
2453 	return wmi_handle;
2454 
2455 error:
2456 	qdf_mem_free(soc);
2457 	qdf_mem_free(wmi_handle);
2458 
2459 	return NULL;
2460 }
2461 
2462 /**
2463  * wmi_unified_detach() -  detach for unified WMI
2464  *
2465  * @wmi_handle  : handle to wmi.
2466  *
2467  * @Return: none.
2468  */
2469 void wmi_unified_detach(struct wmi_unified *wmi_handle)
2470 {
2471 	wmi_buf_t buf;
2472 	struct wmi_soc *soc;
2473 	uint8_t i;
2474 
2475 	wmi_ext_dbgfs_deinit(wmi_handle);
2476 	soc = wmi_handle->soc;
2477 	for (i = 0; i < WMI_MAX_RADIOS; i++) {
2478 		if (soc->wmi_pdev[i]) {
2479 			qdf_flush_workqueue(0,
2480 				soc->wmi_pdev[i]->wmi_rx_work_queue);
2481 			qdf_destroy_workqueue(0,
2482 				soc->wmi_pdev[i]->wmi_rx_work_queue);
2483 			wmi_debugfs_remove(soc->wmi_pdev[i]);
2484 			buf = qdf_nbuf_queue_remove(
2485 					&soc->wmi_pdev[i]->event_queue);
2486 			while (buf) {
2487 				qdf_nbuf_free(buf);
2488 				buf = qdf_nbuf_queue_remove(
2489 						&soc->wmi_pdev[i]->event_queue);
2490 			}
2491 
2492 			wmi_log_buffer_free(soc->wmi_pdev[i]);
2493 
2494 			/* Free events logs list */
2495 			if (soc->wmi_pdev[i]->events_logs_list)
2496 				qdf_mem_free(
2497 					soc->wmi_pdev[i]->events_logs_list);
2498 
2499 			qdf_spinlock_destroy(&soc->wmi_pdev[i]->eventq_lock);
2500 			qdf_mem_free(soc->wmi_pdev[i]);
2501 		}
2502 	}
2503 	qdf_spinlock_destroy(&soc->ctx_lock);
2504 
2505 	if (soc->wmi_service_bitmap) {
2506 		qdf_mem_free(soc->wmi_service_bitmap);
2507 		soc->wmi_service_bitmap = NULL;
2508 	}
2509 
2510 	if (soc->wmi_ext_service_bitmap) {
2511 		qdf_mem_free(soc->wmi_ext_service_bitmap);
2512 		soc->wmi_ext_service_bitmap = NULL;
2513 	}
2514 
2515 	/* Decrease the ref count once refcount infra is present */
2516 	soc->wmi_psoc = NULL;
2517 	qdf_mem_free(soc);
2518 }
2519 
2520 /**
2521  * wmi_unified_remove_work() - detach for WMI work
2522  * @wmi_handle: handle to WMI
2523  *
2524  * A function that does not fully detach WMI, but just remove work
2525  * queue items associated with it. This is used to make sure that
2526  * before any other processing code that may destroy related contexts
2527  * (HTC, etc), work queue processing on WMI has already been stopped.
2528  *
2529  * Return: None
2530  */
2531 void
2532 wmi_unified_remove_work(struct wmi_unified *wmi_handle)
2533 {
2534 	wmi_buf_t buf;
2535 
2536 	qdf_flush_workqueue(0, wmi_handle->wmi_rx_work_queue);
2537 	qdf_spin_lock_bh(&wmi_handle->eventq_lock);
2538 	buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue);
2539 	while (buf) {
2540 		qdf_nbuf_free(buf);
2541 		buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue);
2542 	}
2543 	qdf_spin_unlock_bh(&wmi_handle->eventq_lock);
2544 }
2545 
2546 /**
2547  * wmi_htc_tx_complete() - Process htc tx completion
2548  *
2549  * @ctx: handle to wmi
2550  * @htc_packet: pointer to htc packet
2551  *
2552  * @Return: none.
2553  */
2554 static void wmi_htc_tx_complete(void *ctx, HTC_PACKET *htc_pkt)
2555 {
2556 	struct wmi_soc *soc = (struct wmi_soc *) ctx;
2557 	wmi_buf_t wmi_cmd_buf = GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt);
2558 	u_int8_t *buf_ptr;
2559 	u_int32_t len;
2560 	struct wmi_unified *wmi_handle;
2561 #ifdef WMI_INTERFACE_EVENT_LOGGING
2562 	uint32_t cmd_id;
2563 #endif
2564 
2565 	ASSERT(wmi_cmd_buf);
2566 	wmi_handle = wmi_get_pdev_ep(soc, htc_pkt->Endpoint);
2567 	if (wmi_handle == NULL) {
2568 		WMI_LOGE("%s: Unable to get wmi handle\n", __func__);
2569 		QDF_ASSERT(0);
2570 		return;
2571 	}
2572 #ifdef WMI_INTERFACE_EVENT_LOGGING
2573 	if (wmi_handle && wmi_handle->log_info.wmi_logging_enable) {
2574 		cmd_id = WMI_GET_FIELD(qdf_nbuf_data(wmi_cmd_buf),
2575 				WMI_CMD_HDR, COMMANDID);
2576 
2577 	qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
2578 	/* Record 16 bytes of WMI cmd tx complete data
2579 	- exclude TLV and WMI headers */
2580 	if (wmi_handle->ops->is_management_record(cmd_id)) {
2581 		WMI_MGMT_COMMAND_TX_CMP_RECORD(wmi_handle, cmd_id,
2582 			qdf_nbuf_data(wmi_cmd_buf) +
2583 			wmi_handle->log_info.buf_offset_command);
2584 	} else {
2585 		WMI_COMMAND_TX_CMP_RECORD(wmi_handle, cmd_id,
2586 			qdf_nbuf_data(wmi_cmd_buf) +
2587 			wmi_handle->log_info.buf_offset_command);
2588 	}
2589 
2590 	qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
2591 	}
2592 #endif
2593 	buf_ptr = (u_int8_t *) wmi_buf_data(wmi_cmd_buf);
2594 	len = qdf_nbuf_len(wmi_cmd_buf);
2595 	qdf_mem_zero(buf_ptr, len);
2596 	qdf_nbuf_free(wmi_cmd_buf);
2597 	qdf_mem_free(htc_pkt);
2598 	qdf_atomic_dec(&wmi_handle->pending_cmds);
2599 }
2600 
2601 /**
2602  * wmi_connect_pdev_htc_service() -  WMI API to get connect to HTC service
2603  *
2604  * @wmi_handle: handle to WMI.
2605  * @pdev_idx: Pdev index
2606  *
2607  * @Return: status.
2608  */
2609 static int wmi_connect_pdev_htc_service(struct wmi_soc *soc,
2610 						uint32_t pdev_idx)
2611 {
2612 	int status;
2613 	struct htc_service_connect_resp response;
2614 	struct htc_service_connect_req connect;
2615 
2616 	OS_MEMZERO(&connect, sizeof(connect));
2617 	OS_MEMZERO(&response, sizeof(response));
2618 
2619 	/* meta data is unused for now */
2620 	connect.pMetaData = NULL;
2621 	connect.MetaDataLength = 0;
2622 	/* these fields are the same for all service endpoints */
2623 	connect.EpCallbacks.pContext = soc;
2624 	connect.EpCallbacks.EpTxCompleteMultiple =
2625 		NULL /* Control path completion ar6000_tx_complete */;
2626 	connect.EpCallbacks.EpRecv = wmi_control_rx /* Control path rx */;
2627 	connect.EpCallbacks.EpRecvRefill = NULL /* ar6000_rx_refill */;
2628 	connect.EpCallbacks.EpSendFull = NULL /* ar6000_tx_queue_full */;
2629 	connect.EpCallbacks.EpTxComplete =
2630 		wmi_htc_tx_complete /* ar6000_tx_queue_full */;
2631 
2632 	/* connect to control service */
2633 	connect.service_id = soc->svc_ids[pdev_idx];
2634 	status = htc_connect_service(soc->htc_handle, &connect,
2635 				&response);
2636 
2637 
2638 	if (status != EOK) {
2639 		qdf_print
2640 			("Failed to connect to WMI CONTROL service status:%d\n",
2641 			status);
2642 		return status;
2643 	}
2644 
2645 	soc->wmi_endpoint_id[pdev_idx] = response.Endpoint;
2646 	soc->max_msg_len[pdev_idx] = response.MaxMsgLength;
2647 
2648 	return 0;
2649 }
2650 
2651 /**
2652  * wmi_unified_connect_htc_service() -  WMI API to get connect to HTC service
2653  *
2654  * @wmi_handle: handle to WMI.
2655  *
2656  * @Return: status.
2657  */
2658 QDF_STATUS
2659 wmi_unified_connect_htc_service(struct wmi_unified *wmi_handle,
2660 				void *htc_handle)
2661 {
2662 	uint32_t i;
2663 	uint8_t wmi_ep_count;
2664 
2665 	wmi_handle->soc->htc_handle = htc_handle;
2666 
2667 	wmi_ep_count = htc_get_wmi_endpoint_count(htc_handle);
2668 	if (wmi_ep_count > WMI_MAX_RADIOS)
2669 		return QDF_STATUS_E_FAULT;
2670 
2671 	for (i = 0; i < wmi_ep_count; i++)
2672 		wmi_connect_pdev_htc_service(wmi_handle->soc, i);
2673 
2674 	wmi_handle->htc_handle = htc_handle;
2675 	wmi_handle->wmi_endpoint_id = wmi_handle->soc->wmi_endpoint_id[0];
2676 	wmi_handle->max_msg_len = wmi_handle->soc->max_msg_len[0];
2677 
2678 	return QDF_STATUS_SUCCESS;
2679 }
2680 
2681 /**
2682  * wmi_get_host_credits() -  WMI API to get updated host_credits
2683  *
2684  * @wmi_handle: handle to WMI.
2685  *
2686  * @Return: updated host_credits.
2687  */
2688 int wmi_get_host_credits(wmi_unified_t wmi_handle)
2689 {
2690 	int host_credits = 0;
2691 
2692 	htc_get_control_endpoint_tx_host_credits(wmi_handle->htc_handle,
2693 						 &host_credits);
2694 	return host_credits;
2695 }
2696 
2697 /**
2698  * wmi_get_pending_cmds() - WMI API to get WMI Pending Commands in the HTC
2699  *                          queue
2700  *
2701  * @wmi_handle: handle to WMI.
2702  *
2703  * @Return: Pending Commands in the HTC queue.
2704  */
2705 int wmi_get_pending_cmds(wmi_unified_t wmi_handle)
2706 {
2707 	return qdf_atomic_read(&wmi_handle->pending_cmds);
2708 }
2709 
2710 /**
2711  * wmi_set_target_suspend() -  WMI API to set target suspend state
2712  *
2713  * @wmi_handle: handle to WMI.
2714  * @val: suspend state boolean.
2715  *
2716  * @Return: none.
2717  */
2718 void wmi_set_target_suspend(wmi_unified_t wmi_handle, A_BOOL val)
2719 {
2720 	qdf_atomic_set(&wmi_handle->is_target_suspended, val);
2721 }
2722 
2723 /**
2724  * WMI API to set crash injection state
2725  * @param wmi_handle:	handle to WMI.
2726  * @param val:		crash injection state boolean.
2727  */
2728 void wmi_tag_crash_inject(wmi_unified_t wmi_handle, A_BOOL flag)
2729 {
2730 	wmi_handle->tag_crash_inject = flag;
2731 }
2732 
2733 /**
2734  * WMI API to set bus suspend state
2735  * @param wmi_handle:	handle to WMI.
2736  * @param val:		suspend state boolean.
2737  */
2738 void wmi_set_is_wow_bus_suspended(wmi_unified_t wmi_handle, A_BOOL val)
2739 {
2740 	qdf_atomic_set(&wmi_handle->is_wow_bus_suspended, val);
2741 }
2742 
2743 void wmi_set_tgt_assert(wmi_unified_t wmi_handle, bool val)
2744 {
2745 	wmi_handle->tgt_force_assert_enable = val;
2746 }
2747 
2748 /**
2749  * wmi_stop() - generic function to block unified WMI command
2750  * @wmi_handle: handle to WMI.
2751  *
2752  * @Return: success always.
2753  */
2754 int
2755 wmi_stop(wmi_unified_t wmi_handle)
2756 {
2757 	QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO,
2758 		  "WMI Stop");
2759 	wmi_handle->wmi_stopinprogress = 1;
2760 	return 0;
2761 }
2762 
2763 #ifndef CONFIG_MCL
2764 /**
2765  * API to flush all the previous packets  associated with the wmi endpoint
2766  *
2767  * @param wmi_handle      : handle to WMI.
2768  */
2769 void
2770 wmi_flush_endpoint(wmi_unified_t wmi_handle)
2771 {
2772 	htc_flush_endpoint(wmi_handle->htc_handle,
2773 		wmi_handle->wmi_endpoint_id, 0);
2774 }
2775 qdf_export_symbol(wmi_flush_endpoint);
2776 
2777 /**
2778  * wmi_pdev_id_conversion_enable() - API to enable pdev_id conversion in WMI
2779  *                     By default pdev_id conversion is not done in WMI.
2780  *                     This API can be used enable conversion in WMI.
2781  * @param wmi_handle   : handle to WMI
2782  * Return none
2783  */
2784 void wmi_pdev_id_conversion_enable(wmi_unified_t wmi_handle)
2785 {
2786 	if (wmi_handle->target_type == WMI_TLV_TARGET)
2787 		wmi_handle->ops->wmi_pdev_id_conversion_enable(wmi_handle);
2788 }
2789 
2790 #endif
2791