xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified.c (revision cd39549564686e1d60a410c477b7c6e9e19791fd)
1 /*
2  * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
3  *
4  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5  *
6  *
7  * Permission to use, copy, modify, and/or distribute this software for
8  * any purpose with or without fee is hereby granted, provided that the
9  * above copyright notice and this permission notice appear in all
10  * copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19  * PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 /*
23  * This file was originally distributed by Qualcomm Atheros, Inc.
24  * under proprietary terms before Copyright ownership was assigned
25  * to the Linux Foundation.
26  */
27 
28 /*
29  * Host WMI unified implementation
30  */
31 #include "athdefs.h"
32 #include "osapi_linux.h"
33 #include "a_types.h"
34 #include "a_debug.h"
35 #include "ol_if_athvar.h"
36 #include "ol_defines.h"
37 #include "htc_api.h"
38 #include "htc_api.h"
39 #include "dbglog_host.h"
40 #include "wmi_unified_priv.h"
41 #include "wmi_unified_param.h"
42 
43 #ifndef WMI_NON_TLV_SUPPORT
44 #include "wmi_tlv_helper.h"
45 #endif
46 
47 #include <linux/debugfs.h>
48 
49 /* This check for CONFIG_WIN temporary added due to redeclaration compilation
50 error in MCL. Error is caused due to inclusion of wmi.h in wmi_unified_api.h
51 which gets included here through ol_if_athvar.h. Eventually it is expected that
52 wmi.h will be removed from wmi_unified_api.h after cleanup, which will need
53 WMI_CMD_HDR to be defined here. */
54 #ifdef CONFIG_WIN
55 /* Copied from wmi.h */
56 #undef MS
57 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
58 #undef SM
59 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
60 #undef WO
61 #define WO(_f)      ((_f##_OFFSET) >> 2)
62 
63 #undef GET_FIELD
64 #define GET_FIELD(_addr, _f) MS(*((A_UINT32 *)(_addr) + WO(_f)), _f)
65 #undef SET_FIELD
66 #define SET_FIELD(_addr, _f, _val)  \
67 	    (*((A_UINT32 *)(_addr) + WO(_f)) = \
68 		(*((A_UINT32 *)(_addr) + WO(_f)) & ~_f##_MASK) | SM(_val, _f))
69 
70 #define WMI_GET_FIELD(_msg_buf, _msg_type, _f) \
71 	    GET_FIELD(_msg_buf, _msg_type ## _ ## _f)
72 
73 #define WMI_SET_FIELD(_msg_buf, _msg_type, _f, _val) \
74 	    SET_FIELD(_msg_buf, _msg_type ## _ ## _f, _val)
75 
76 #define WMI_EP_APASS           0x0
77 #define WMI_EP_LPASS           0x1
78 #define WMI_EP_SENSOR          0x2
79 
80 /*
81  *  * Control Path
82  *   */
83 typedef PREPACK struct {
84 	A_UINT32	commandId:24,
85 			reserved:2, /* used for WMI endpoint ID */
86 			plt_priv:6; /* platform private */
87 } POSTPACK WMI_CMD_HDR;        /* used for commands and events */
88 
89 #define WMI_CMD_HDR_COMMANDID_LSB           0
90 #define WMI_CMD_HDR_COMMANDID_MASK          0x00ffffff
91 #define WMI_CMD_HDR_COMMANDID_OFFSET        0x00000000
92 #define WMI_CMD_HDR_WMI_ENDPOINTID_MASK        0x03000000
93 #define WMI_CMD_HDR_WMI_ENDPOINTID_OFFSET      24
94 #define WMI_CMD_HDR_PLT_PRIV_LSB               24
95 #define WMI_CMD_HDR_PLT_PRIV_MASK              0xff000000
96 #define WMI_CMD_HDR_PLT_PRIV_OFFSET            0x00000000
97 /* end of copy wmi.h */
98 #endif /* CONFIG_WIN */
99 
100 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0))
101 /* TODO Cleanup this backported function */
102 static int qcacld_bp_seq_printf(struct seq_file *m, const char *f, ...)
103 {
104 	va_list args;
105 
106 	va_start(args, f);
107 	seq_printf(m, f, args);
108 	va_end(args);
109 
110 	return m->count;
111 }
112 
113 #define seq_printf(m, fmt, ...) qcacld_bp_seq_printf((m), fmt, ##__VA_ARGS__)
114 #endif
115 
116 #define WMI_MIN_HEAD_ROOM 64
117 
118 #ifdef WMI_INTERFACE_EVENT_LOGGING
119 #ifndef MAX_WMI_INSTANCES
120 #ifdef CONFIG_MCL
121 #define MAX_WMI_INSTANCES 1
122 #else
123 #define MAX_WMI_INSTANCES 3
124 #endif
125 #define CUSTOM_MGMT_CMD_DATA_SIZE 4
126 #endif
127 
128 #ifdef CONFIG_MCL
129 /* WMI commands */
130 uint32_t g_wmi_command_buf_idx = 0;
131 struct wmi_command_debug wmi_command_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
132 
133 /* WMI commands TX completed */
134 uint32_t g_wmi_command_tx_cmp_buf_idx = 0;
135 struct wmi_command_debug
136 	wmi_command_tx_cmp_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
137 
138 /* WMI events when processed */
139 uint32_t g_wmi_event_buf_idx = 0;
140 struct wmi_event_debug wmi_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
141 
142 /* WMI events when queued */
143 uint32_t g_wmi_rx_event_buf_idx = 0;
144 struct wmi_event_debug wmi_rx_event_log_buffer[WMI_EVENT_DEBUG_MAX_ENTRY];
145 #endif
146 
147 #define WMI_COMMAND_RECORD(h, a, b) {					\
148 	if (wmi_log_max_entry <=					\
149 		*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx))	\
150 		*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx) = 0;\
151 	((struct wmi_command_debug *)h->log_info.wmi_command_log_buf_info.buf)\
152 		[*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)]\
153 						.command = a;		\
154 	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.		\
155 				wmi_command_log_buf_info.buf)		\
156 		[*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)].data,\
157 			b, wmi_record_max_length);			\
158 	((struct wmi_command_debug *)h->log_info.wmi_command_log_buf_info.buf)\
159 		[*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx)].\
160 		time = qdf_get_log_timestamp();			\
161 	(*(h->log_info.wmi_command_log_buf_info.p_buf_tail_idx))++;	\
162 	h->log_info.wmi_command_log_buf_info.length++;			\
163 }
164 
165 #define WMI_COMMAND_TX_CMP_RECORD(h, a, b) {				\
166 	if (wmi_log_max_entry <=					\
167 		*(h->log_info.wmi_command_tx_cmp_log_buf_info.p_buf_tail_idx))\
168 		*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
169 				p_buf_tail_idx) = 0;			\
170 	((struct wmi_command_debug *)h->log_info.			\
171 		wmi_command_tx_cmp_log_buf_info.buf)			\
172 		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
173 				p_buf_tail_idx)].			\
174 							command	= a;	\
175 	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.		\
176 				wmi_command_tx_cmp_log_buf_info.buf)	\
177 		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
178 			p_buf_tail_idx)].				\
179 		data, b, wmi_record_max_length);			\
180 	((struct wmi_command_debug *)h->log_info.			\
181 		wmi_command_tx_cmp_log_buf_info.buf)			\
182 		[*(h->log_info.wmi_command_tx_cmp_log_buf_info.		\
183 				p_buf_tail_idx)].			\
184 		time = qdf_get_log_timestamp();				\
185 	(*(h->log_info.wmi_command_tx_cmp_log_buf_info.p_buf_tail_idx))++;\
186 	h->log_info.wmi_command_tx_cmp_log_buf_info.length++;		\
187 }
188 
189 #define WMI_EVENT_RECORD(h, a, b) {					\
190 	if (wmi_log_max_entry <=					\
191 		*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx))	\
192 		*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx) = 0;\
193 	((struct wmi_event_debug *)h->log_info.wmi_event_log_buf_info.buf)\
194 		[*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].	\
195 		event = a;						\
196 	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.		\
197 				wmi_event_log_buf_info.buf)		\
198 		[*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].data, b,\
199 		wmi_record_max_length);					\
200 	((struct wmi_event_debug *)h->log_info.wmi_event_log_buf_info.buf)\
201 		[*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx)].time =\
202 		qdf_get_log_timestamp();				\
203 	(*(h->log_info.wmi_event_log_buf_info.p_buf_tail_idx))++;	\
204 	h->log_info.wmi_event_log_buf_info.length++;			\
205 }
206 
207 #define WMI_RX_EVENT_RECORD(h, a, b) {					\
208 	if (wmi_log_max_entry <=					\
209 		*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx))\
210 		*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx) = 0;\
211 	((struct wmi_event_debug *)h->log_info.wmi_rx_event_log_buf_info.buf)\
212 		[*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\
213 		event = a;						\
214 	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.		\
215 				wmi_rx_event_log_buf_info.buf)		\
216 		[*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\
217 			data, b, wmi_record_max_length);		\
218 	((struct wmi_event_debug *)h->log_info.wmi_rx_event_log_buf_info.buf)\
219 		[*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx)].\
220 		time =	qdf_get_log_timestamp();			\
221 	(*(h->log_info.wmi_rx_event_log_buf_info.p_buf_tail_idx))++;	\
222 	h->log_info.wmi_rx_event_log_buf_info.length++;			\
223 }
224 
225 #ifdef CONFIG_MCL
226 uint32_t g_wmi_mgmt_command_buf_idx = 0;
227 struct
228 wmi_command_debug wmi_mgmt_command_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY];
229 
230 /* wmi_mgmt commands TX completed */
231 uint32_t g_wmi_mgmt_command_tx_cmp_buf_idx = 0;
232 struct wmi_command_debug
233 wmi_mgmt_command_tx_cmp_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY];
234 
235 /* wmi_mgmt events when processed */
236 uint32_t g_wmi_mgmt_event_buf_idx = 0;
237 struct wmi_event_debug
238 wmi_mgmt_event_log_buffer[WMI_MGMT_EVENT_DEBUG_MAX_ENTRY];
239 #endif
240 
241 #define WMI_MGMT_COMMAND_RECORD(h, a, b) {                              \
242 	if (wmi_mgmt_log_max_entry <=                                   \
243 		*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)) \
244 		*(h->log_info.wmi_mgmt_command_log_buf_info.		\
245 				p_buf_tail_idx) = 0;			\
246 	((struct wmi_command_debug *)h->log_info.                       \
247 		 wmi_mgmt_command_log_buf_info.buf)                     \
248 		[*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\
249 			command = a;                                    \
250 	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.          \
251 				wmi_mgmt_command_log_buf_info.buf)      \
252 		[*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\
253 		data, b,                                                \
254 		wmi_record_max_length);                                	\
255 	((struct wmi_command_debug *)h->log_info.                       \
256 		 wmi_mgmt_command_log_buf_info.buf)                     \
257 		[*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx)].\
258 			time =        qdf_get_log_timestamp();          \
259 	(*(h->log_info.wmi_mgmt_command_log_buf_info.p_buf_tail_idx))++;\
260 	h->log_info.wmi_mgmt_command_log_buf_info.length++;             \
261 }
262 
263 #define WMI_MGMT_COMMAND_TX_CMP_RECORD(h, a, b) {			\
264 	if (wmi_mgmt_log_max_entry <=					\
265 		*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
266 			p_buf_tail_idx))				\
267 		*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
268 			p_buf_tail_idx) = 0;				\
269 	((struct wmi_command_debug *)h->log_info.			\
270 			wmi_mgmt_command_tx_cmp_log_buf_info.buf)	\
271 		[*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
272 				p_buf_tail_idx)].command = a;		\
273 	qdf_mem_copy(((struct wmi_command_debug *)h->log_info.		\
274 				wmi_mgmt_command_tx_cmp_log_buf_info.buf)\
275 		[*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
276 			p_buf_tail_idx)].data, b,			\
277 			wmi_record_max_length);				\
278 	((struct wmi_command_debug *)h->log_info.			\
279 			wmi_mgmt_command_tx_cmp_log_buf_info.buf)	\
280 		[*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.	\
281 				p_buf_tail_idx)].time =			\
282 		qdf_get_log_timestamp();				\
283 	(*(h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.		\
284 			p_buf_tail_idx))++;				\
285 	h->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.length++;	\
286 }
287 
288 #define WMI_MGMT_EVENT_RECORD(h, a, b) {				\
289 	if (wmi_mgmt_log_max_entry <=					\
290 		*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx))\
291 		*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx) = 0;\
292 	((struct wmi_event_debug *)h->log_info.wmi_mgmt_event_log_buf_info.buf)\
293 		[*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)]\
294 					.event = a;			\
295 	qdf_mem_copy(((struct wmi_event_debug *)h->log_info.		\
296 				wmi_mgmt_event_log_buf_info.buf)	\
297 		[*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)].\
298 			data, b, wmi_record_max_length);		\
299 	((struct wmi_event_debug *)h->log_info.wmi_mgmt_event_log_buf_info.buf)\
300 		[*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx)].\
301 			time = qdf_get_log_timestamp();			\
302 	(*(h->log_info.wmi_mgmt_event_log_buf_info.p_buf_tail_idx))++;	\
303 	h->log_info.wmi_mgmt_event_log_buf_info.length++;		\
304 }
305 
306 /* These are defined to made it as module param, which can be configured */
307 uint32_t wmi_log_max_entry = WMI_EVENT_DEBUG_MAX_ENTRY;
308 uint32_t wmi_mgmt_log_max_entry = WMI_MGMT_EVENT_DEBUG_MAX_ENTRY;
309 uint32_t wmi_record_max_length = WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH;
310 uint32_t wmi_display_size = 100;
311 
312 static uint8_t *wmi_id_to_name(uint32_t wmi_command);
313 
314 /**
315  * wmi_log_init() - Initialize WMI event logging
316  * @wmi_handle: WMI handle.
317  *
318  * Return: Initialization status
319  */
320 #ifdef CONFIG_MCL
321 static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle)
322 {
323 	struct wmi_log_buf_t *cmd_log_buf =
324 			&wmi_handle->log_info.wmi_command_log_buf_info;
325 	struct wmi_log_buf_t *cmd_tx_cmpl_log_buf =
326 			&wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info;
327 
328 	struct wmi_log_buf_t *event_log_buf =
329 			&wmi_handle->log_info.wmi_event_log_buf_info;
330 	struct wmi_log_buf_t *rx_event_log_buf =
331 			&wmi_handle->log_info.wmi_rx_event_log_buf_info;
332 
333 	struct wmi_log_buf_t *mgmt_cmd_log_buf =
334 			&wmi_handle->log_info.wmi_mgmt_command_log_buf_info;
335 	struct wmi_log_buf_t *mgmt_cmd_tx_cmp_log_buf =
336 		&wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info;
337 	struct wmi_log_buf_t *mgmt_event_log_buf =
338 			&wmi_handle->log_info.wmi_mgmt_event_log_buf_info;
339 
340 	/* WMI commands */
341 	cmd_log_buf->length = 0;
342 	cmd_log_buf->buf_tail_idx = 0;
343 	cmd_log_buf->buf = wmi_command_log_buffer;
344 	cmd_log_buf->p_buf_tail_idx = &g_wmi_command_buf_idx;
345 
346 	/* WMI commands TX completed */
347 	cmd_tx_cmpl_log_buf->length = 0;
348 	cmd_tx_cmpl_log_buf->buf_tail_idx = 0;
349 	cmd_tx_cmpl_log_buf->buf = wmi_command_tx_cmp_log_buffer;
350 	cmd_tx_cmpl_log_buf->p_buf_tail_idx = &g_wmi_command_tx_cmp_buf_idx;
351 
352 	/* WMI events when processed */
353 	event_log_buf->length = 0;
354 	event_log_buf->buf_tail_idx = 0;
355 	event_log_buf->buf = wmi_event_log_buffer;
356 	event_log_buf->p_buf_tail_idx = &g_wmi_event_buf_idx;
357 
358 	/* WMI events when queued */
359 	rx_event_log_buf->length = 0;
360 	rx_event_log_buf->buf_tail_idx = 0;
361 	rx_event_log_buf->buf = wmi_rx_event_log_buffer;
362 	rx_event_log_buf->p_buf_tail_idx = &g_wmi_rx_event_buf_idx;
363 
364 	/* WMI Management commands */
365 	mgmt_cmd_log_buf->length = 0;
366 	mgmt_cmd_log_buf->buf_tail_idx = 0;
367 	mgmt_cmd_log_buf->buf = wmi_mgmt_command_log_buffer;
368 	mgmt_cmd_log_buf->p_buf_tail_idx = &g_wmi_mgmt_command_buf_idx;
369 
370 	/* WMI Management commands Tx completed*/
371 	mgmt_cmd_tx_cmp_log_buf->length = 0;
372 	mgmt_cmd_tx_cmp_log_buf->buf_tail_idx = 0;
373 	mgmt_cmd_tx_cmp_log_buf->buf = wmi_mgmt_command_tx_cmp_log_buffer;
374 	mgmt_cmd_tx_cmp_log_buf->p_buf_tail_idx =
375 		&g_wmi_mgmt_command_tx_cmp_buf_idx;
376 
377 	/* WMI Management events when processed*/
378 	mgmt_event_log_buf->length = 0;
379 	mgmt_event_log_buf->buf_tail_idx = 0;
380 	mgmt_event_log_buf->buf = wmi_mgmt_event_log_buffer;
381 	mgmt_event_log_buf->p_buf_tail_idx = &g_wmi_mgmt_event_buf_idx;
382 
383 	qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock);
384 	wmi_handle->log_info.wmi_logging_enable = 1;
385 
386 	return QDF_STATUS_SUCCESS;
387 }
388 #else
389 static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle)
390 {
391 	struct wmi_log_buf_t *cmd_log_buf =
392 			&wmi_handle->log_info.wmi_command_log_buf_info;
393 	struct wmi_log_buf_t *cmd_tx_cmpl_log_buf =
394 			&wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info;
395 
396 	struct wmi_log_buf_t *event_log_buf =
397 			&wmi_handle->log_info.wmi_event_log_buf_info;
398 	struct wmi_log_buf_t *rx_event_log_buf =
399 			&wmi_handle->log_info.wmi_rx_event_log_buf_info;
400 
401 	struct wmi_log_buf_t *mgmt_cmd_log_buf =
402 			&wmi_handle->log_info.wmi_mgmt_command_log_buf_info;
403 	struct wmi_log_buf_t *mgmt_cmd_tx_cmp_log_buf =
404 		&wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info;
405 	struct wmi_log_buf_t *mgmt_event_log_buf =
406 			&wmi_handle->log_info.wmi_mgmt_event_log_buf_info;
407 
408 	wmi_handle->log_info.wmi_logging_enable = 0;
409 
410 	/* WMI commands */
411 	cmd_log_buf->length = 0;
412 	cmd_log_buf->buf_tail_idx = 0;
413 	cmd_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc(
414 		wmi_log_max_entry * sizeof(struct wmi_command_debug));
415 
416 	if (!cmd_log_buf->buf) {
417 		qdf_print("no memory for WMI command log buffer..\n");
418 		return QDF_STATUS_E_NOMEM;
419 	}
420 	cmd_log_buf->p_buf_tail_idx = &cmd_log_buf->buf_tail_idx;
421 
422 	/* WMI commands TX completed */
423 	cmd_tx_cmpl_log_buf->length = 0;
424 	cmd_tx_cmpl_log_buf->buf_tail_idx = 0;
425 	cmd_tx_cmpl_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc(
426 		wmi_log_max_entry * sizeof(struct wmi_command_debug));
427 
428 	if (!cmd_tx_cmpl_log_buf->buf) {
429 		qdf_print("no memory for WMI Command Tx Complete log buffer..\n");
430 		return QDF_STATUS_E_NOMEM;
431 	}
432 	cmd_tx_cmpl_log_buf->p_buf_tail_idx =
433 		&cmd_tx_cmpl_log_buf->buf_tail_idx;
434 
435 	/* WMI events when processed */
436 	event_log_buf->length = 0;
437 	event_log_buf->buf_tail_idx = 0;
438 	event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
439 		wmi_log_max_entry * sizeof(struct wmi_event_debug));
440 
441 	if (!event_log_buf->buf) {
442 		qdf_print("no memory for WMI Event log buffer..\n");
443 		return QDF_STATUS_E_NOMEM;
444 	}
445 	event_log_buf->p_buf_tail_idx = &event_log_buf->buf_tail_idx;
446 
447 	/* WMI events when queued */
448 	rx_event_log_buf->length = 0;
449 	rx_event_log_buf->buf_tail_idx = 0;
450 	rx_event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
451 		wmi_log_max_entry * sizeof(struct wmi_event_debug));
452 
453 	if (!rx_event_log_buf->buf) {
454 		qdf_print("no memory for WMI Event Rx log buffer..\n");
455 		return QDF_STATUS_E_NOMEM;
456 	}
457 	rx_event_log_buf->p_buf_tail_idx = &rx_event_log_buf->buf_tail_idx;
458 
459 	/* WMI Management commands */
460 	mgmt_cmd_log_buf->length = 0;
461 	mgmt_cmd_log_buf->buf_tail_idx = 0;
462 	mgmt_cmd_log_buf->buf = (struct wmi_command_debug *) qdf_mem_malloc(
463 		wmi_mgmt_log_max_entry *
464 		sizeof(struct wmi_command_debug));
465 
466 	if (!mgmt_cmd_log_buf->buf) {
467 		qdf_print("no memory for WMI Management Command log buffer..\n");
468 		return QDF_STATUS_E_NOMEM;
469 	}
470 	mgmt_cmd_log_buf->p_buf_tail_idx = &mgmt_cmd_log_buf->buf_tail_idx;
471 
472 	/* WMI Management commands Tx completed*/
473 	mgmt_cmd_tx_cmp_log_buf->length = 0;
474 	mgmt_cmd_tx_cmp_log_buf->buf_tail_idx = 0;
475 	mgmt_cmd_tx_cmp_log_buf->buf = (struct wmi_command_debug *)
476 		qdf_mem_malloc(
477 		wmi_mgmt_log_max_entry *
478 		sizeof(struct wmi_command_debug));
479 
480 	if (!mgmt_cmd_tx_cmp_log_buf->buf) {
481 		qdf_print("no memory for WMI Management Command Tx complete log buffer..\n");
482 		return QDF_STATUS_E_NOMEM;
483 	}
484 	mgmt_cmd_tx_cmp_log_buf->p_buf_tail_idx =
485 		&mgmt_cmd_tx_cmp_log_buf->buf_tail_idx;
486 
487 	/* WMI Management events when processed*/
488 	mgmt_event_log_buf->length = 0;
489 	mgmt_event_log_buf->buf_tail_idx = 0;
490 
491 	mgmt_event_log_buf->buf = (struct wmi_event_debug *) qdf_mem_malloc(
492 		wmi_mgmt_log_max_entry *
493 		sizeof(struct wmi_event_debug));
494 
495 	if (!mgmt_event_log_buf->buf) {
496 		qdf_print("no memory for WMI Management Event log buffer..\n");
497 		return QDF_STATUS_E_NOMEM;
498 	}
499 	mgmt_event_log_buf->p_buf_tail_idx = &mgmt_event_log_buf->buf_tail_idx;
500 
501 	qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock);
502 	wmi_handle->log_info.wmi_logging_enable = 1;
503 
504 	return QDF_STATUS_SUCCESS;
505 }
506 #endif
507 
508 /**
509  * wmi_log_buffer_free() - Free all dynamic allocated buffer memory for
510  * event logging
511  * @wmi_handle: WMI handle.
512  *
513  * Return: None
514  */
515 #ifndef CONFIG_MCL
516 static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle)
517 {
518 	if (wmi_handle->log_info.wmi_command_log_buf_info.buf)
519 		qdf_mem_free(wmi_handle->log_info.wmi_command_log_buf_info.buf);
520 	if (wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info.buf)
521 		qdf_mem_free(
522 		wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info.buf);
523 	if (wmi_handle->log_info.wmi_event_log_buf_info.buf)
524 		qdf_mem_free(wmi_handle->log_info.wmi_event_log_buf_info.buf);
525 	if (wmi_handle->log_info.wmi_rx_event_log_buf_info.buf)
526 		qdf_mem_free(
527 			wmi_handle->log_info.wmi_rx_event_log_buf_info.buf);
528 	if (wmi_handle->log_info.wmi_mgmt_command_log_buf_info.buf)
529 		qdf_mem_free(
530 			wmi_handle->log_info.wmi_mgmt_command_log_buf_info.buf);
531 	if (wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.buf)
532 		qdf_mem_free(
533 		wmi_handle->log_info.wmi_mgmt_command_tx_cmp_log_buf_info.buf);
534 	if (wmi_handle->log_info.wmi_mgmt_event_log_buf_info.buf)
535 		qdf_mem_free(
536 			wmi_handle->log_info.wmi_mgmt_event_log_buf_info.buf);
537 	wmi_handle->log_info.wmi_logging_enable = 0;
538 	qdf_spinlock_destroy(&wmi_handle->log_info.wmi_record_lock);
539 }
540 #else
541 static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle)
542 {
543 	/* Do Nothing */
544 }
545 #endif
546 
547 #ifdef CONFIG_MCL
548 const int8_t * const debugfs_dir[MAX_WMI_INSTANCES] = {"WMI0"};
549 #else
550 const int8_t * const debugfs_dir[MAX_WMI_INSTANCES] = {"WMI0", "WMI1", "WMI2"};
551 #endif
552 
553 /* debugfs routines*/
554 
555 /**
556  * debug_wmi_##func_base##_show() - debugfs functions to display content of
557  * command and event buffers. Macro uses max buffer length to display
558  * buffer when it is wraparound.
559  *
560  * @m: debugfs handler to access wmi_handle
561  * @v: Variable arguments (not used)
562  *
563  * Return: Length of characters printed
564  */
565 #define GENERATE_COMMAND_DEBUG_SHOW_FUNCS(func_base, wmi_ring_size)	\
566 	static int debug_wmi_##func_base##_show(struct seq_file *m,	\
567 						void *v)		\
568 	{								\
569 		wmi_unified_t wmi_handle = (wmi_unified_t) m->private;	\
570 		struct wmi_log_buf_t *wmi_log =				\
571 			&wmi_handle->log_info.wmi_##func_base##_buf_info;\
572 		int pos, nread, outlen;					\
573 		int i;							\
574 									\
575 		qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock);	\
576 		if (!wmi_log->length) {					\
577 			qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\
578 			return seq_printf(m,				\
579 			"no elements to read from ring buffer!\n");	\
580 		}							\
581 									\
582 		if (wmi_log->length <= wmi_ring_size)			\
583 			nread = wmi_log->length;			\
584 		else							\
585 			nread = wmi_ring_size;				\
586 									\
587 		if (*(wmi_log->p_buf_tail_idx) == 0)			\
588 			/* tail can be 0 after wrap-around */		\
589 			pos = wmi_ring_size - 1;			\
590 		else							\
591 			pos = *(wmi_log->p_buf_tail_idx) - 1;		\
592 									\
593 		outlen = seq_printf(m, "Length = %d\n", wmi_log->length);\
594 		qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);	\
595 		while (nread--) {					\
596 			struct wmi_command_debug *wmi_record;		\
597 									\
598 			wmi_record = (struct wmi_command_debug *)	\
599 			&(((struct wmi_command_debug *)wmi_log->buf)[pos]);\
600 			outlen += seq_printf(m, "CMD ID = %x\n",	\
601 				(wmi_record->command));			\
602 			outlen += seq_printf(m, "CMD = ");		\
603 			for (i = 0; i < (wmi_record_max_length/		\
604 					sizeof(uint32_t)); i++)		\
605 				outlen += seq_printf(m, "%x ",		\
606 					wmi_record->data[i]);		\
607 			outlen += seq_printf(m, "\n");			\
608 									\
609 			if (pos == 0)					\
610 				pos = wmi_ring_size - 1;		\
611 			else						\
612 				pos--;					\
613 		}							\
614 									\
615 		return outlen;						\
616 	}								\
617 
618 #define GENERATE_EVENT_DEBUG_SHOW_FUNCS(func_base, wmi_ring_size)	\
619 	static int debug_wmi_##func_base##_show(struct seq_file *m,	\
620 						void *v)		\
621 	{								\
622 		wmi_unified_t wmi_handle = (wmi_unified_t) m->private;	\
623 		struct wmi_log_buf_t *wmi_log =				\
624 			&wmi_handle->log_info.wmi_##func_base##_buf_info;\
625 		int pos, nread, outlen;					\
626 		int i;							\
627 									\
628 		qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock);	\
629 		if (!wmi_log->length) {					\
630 			qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);\
631 			return seq_printf(m,				\
632 			"no elements to read from ring buffer!\n");	\
633 		}							\
634 									\
635 		if (wmi_log->length <= wmi_ring_size)			\
636 			nread = wmi_log->length;			\
637 		else							\
638 			nread = wmi_ring_size;				\
639 									\
640 		if (*(wmi_log->p_buf_tail_idx) == 0)			\
641 			/* tail can be 0 after wrap-around */		\
642 			pos = wmi_ring_size - 1;			\
643 		else							\
644 			pos = *(wmi_log->p_buf_tail_idx) - 1;		\
645 									\
646 		outlen = seq_printf(m, "Length = %d\n", wmi_log->length);\
647 		qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);	\
648 		while (nread--) {					\
649 			struct wmi_event_debug *wmi_record;		\
650 									\
651 			wmi_record = (struct wmi_event_debug *)		\
652 			&(((struct wmi_event_debug *)wmi_log->buf)[pos]);\
653 			outlen += seq_printf(m, "Event ID = %x\n",	\
654 				(wmi_record->event));			\
655 			outlen += seq_printf(m, "CMD = ");		\
656 			for (i = 0; i < (wmi_record_max_length/		\
657 					sizeof(uint32_t)); i++)		\
658 				outlen += seq_printf(m, "%x ",		\
659 					wmi_record->data[i]);		\
660 			outlen += seq_printf(m, "\n");			\
661 									\
662 			if (pos == 0)					\
663 				pos = wmi_ring_size - 1;		\
664 			else						\
665 				pos--;					\
666 		}							\
667 									\
668 		return outlen;						\
669 	}
670 
671 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(command_log, wmi_display_size);
672 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(command_tx_cmp_log, wmi_display_size);
673 GENERATE_EVENT_DEBUG_SHOW_FUNCS(event_log, wmi_display_size);
674 GENERATE_EVENT_DEBUG_SHOW_FUNCS(rx_event_log, wmi_display_size);
675 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(mgmt_command_log, wmi_display_size);
676 GENERATE_COMMAND_DEBUG_SHOW_FUNCS(mgmt_command_tx_cmp_log,
677 					wmi_display_size);
678 GENERATE_EVENT_DEBUG_SHOW_FUNCS(mgmt_event_log, wmi_display_size);
679 
680 /**
681  * debug_wmi_enable_show() - debugfs functions to display enable state of
682  * wmi logging feature.
683  *
684  * @m: debugfs handler to access wmi_handle
685  * @v: Variable arguments (not used)
686  *
687  * Return: always 1
688  */
689 static int debug_wmi_enable_show(struct seq_file *m, void *v)
690 {
691 	wmi_unified_t wmi_handle = (wmi_unified_t) m->private;
692 
693 	return seq_printf(m, "%d\n", wmi_handle->log_info.wmi_logging_enable);
694 
695 }
696 
697 /**
698  * debug_wmi_log_size_show() - debugfs functions to display configured size of
699  * wmi logging command/event buffer and management command/event buffer.
700  *
701  * @m: debugfs handler to access wmi_handle
702  * @v: Variable arguments (not used)
703  *
704  * Return: Length of characters printed
705  */
706 static int debug_wmi_log_size_show(struct seq_file *m, void *v)
707 {
708 
709 	seq_printf(m, "WMI command/event log max size:%d\n", wmi_log_max_entry);
710 	return seq_printf(m, "WMI management command/events log max size:%d\n",
711 				wmi_mgmt_log_max_entry);
712 }
713 
714 /**
715  * debug_wmi_##func_base##_write() - debugfs functions to clear
716  * wmi logging command/event buffer and management command/event buffer.
717  *
718  * @file: file handler to access wmi_handle
719  * @buf: received data buffer
720  * @count: length of received buffer
721  * @ppos: Not used
722  *
723  * Return: count
724  */
725 #define GENERATE_DEBUG_WRITE_FUNCS(func_base, wmi_ring_size, wmi_record_type)\
726 	static ssize_t debug_wmi_##func_base##_write(struct file *file,	\
727 				const char __user *buf,			\
728 				size_t count, loff_t *ppos)		\
729 	{								\
730 		int k, ret;						\
731 		wmi_unified_t wmi_handle = file->private_data;		\
732 		struct wmi_log_buf_t *wmi_log = &wmi_handle->log_info.	\
733 				wmi_##func_base##_buf_info;		\
734 									\
735 		ret = sscanf(buf, "%d", &k);				\
736 		if ((ret != 1) || (k != 0)) {				\
737 			qdf_print("Wrong input, echo 0 to clear the wmi	buffer\n");\
738 			return -EINVAL;					\
739 		}							\
740 									\
741 		qdf_spin_lock(&wmi_handle->log_info.wmi_record_lock);	\
742 		qdf_mem_zero(wmi_log->buf, wmi_ring_size *		\
743 				sizeof(struct wmi_record_type));	\
744 		wmi_log->length = 0;					\
745 		*(wmi_log->p_buf_tail_idx) = 0;				\
746 		qdf_spin_unlock(&wmi_handle->log_info.wmi_record_lock);	\
747 									\
748 		return count;						\
749 	}
750 
751 GENERATE_DEBUG_WRITE_FUNCS(command_log, wmi_log_max_entry,
752 					wmi_command_debug);
753 GENERATE_DEBUG_WRITE_FUNCS(command_tx_cmp_log, wmi_log_max_entry,
754 					wmi_command_debug);
755 GENERATE_DEBUG_WRITE_FUNCS(event_log, wmi_log_max_entry,
756 					wmi_event_debug);
757 GENERATE_DEBUG_WRITE_FUNCS(rx_event_log, wmi_log_max_entry,
758 					wmi_event_debug);
759 GENERATE_DEBUG_WRITE_FUNCS(mgmt_command_log, wmi_mgmt_log_max_entry,
760 					wmi_command_debug);
761 GENERATE_DEBUG_WRITE_FUNCS(mgmt_command_tx_cmp_log,
762 		wmi_mgmt_log_max_entry, wmi_command_debug);
763 GENERATE_DEBUG_WRITE_FUNCS(mgmt_event_log, wmi_mgmt_log_max_entry,
764 					wmi_event_debug);
765 
766 /**
767  * debug_wmi_enable_write() - debugfs functions to enable/disable
768  * wmi logging feature.
769  *
770  * @file: file handler to access wmi_handle
771  * @buf: received data buffer
772  * @count: length of received buffer
773  * @ppos: Not used
774  *
775  * Return: count
776  */
777 static ssize_t debug_wmi_enable_write(struct file *file, const char __user *buf,
778 					size_t count, loff_t *ppos)
779 {
780 	wmi_unified_t wmi_handle =  file->private_data;
781 	int k, ret;
782 
783 	ret = sscanf(buf, "%d", &k);
784 	if ((ret != 1) || ((k != 0) && (k != 1)))
785 		return -EINVAL;
786 
787 	wmi_handle->log_info.wmi_logging_enable = k;
788 	return count;
789 }
790 
791 /**
792  * debug_wmi_log_size_write() - reserved.
793  *
794  * @file: file handler to access wmi_handle
795  * @buf: received data buffer
796  * @count: length of received buffer
797  * @ppos: Not used
798  *
799  * Return: count
800  */
801 static ssize_t debug_wmi_log_size_write(struct file *file,
802 		const char __user *buf, size_t count, loff_t *ppos)
803 {
804 	return -EINVAL;
805 }
806 
807 /* Structure to maintain debug information */
808 struct wmi_debugfs_info {
809 	const char *name;
810 	struct dentry *de[MAX_WMI_INSTANCES];
811 	const struct file_operations *ops;
812 };
813 
814 #define DEBUG_FOO(func_base) { .name = #func_base,			\
815 	.ops = &debug_##func_base##_ops }
816 
817 /**
818  * debug_##func_base##_open() - Open debugfs entry for respective command
819  * and event buffer.
820  *
821  * @inode: node for debug dir entry
822  * @file: file handler
823  *
824  * Return: open status
825  */
826 #define GENERATE_DEBUG_STRUCTS(func_base)				\
827 	static int debug_##func_base##_open(struct inode *inode,	\
828 						struct file *file)	\
829 	{								\
830 		return single_open(file, debug_##func_base##_show,	\
831 				inode->i_private);			\
832 	}								\
833 									\
834 									\
835 	static struct file_operations debug_##func_base##_ops = {	\
836 		.open		= debug_##func_base##_open,		\
837 		.read		= seq_read,				\
838 		.llseek		= seq_lseek,				\
839 		.write		= debug_##func_base##_write,		\
840 		.release	= single_release,			\
841 	};
842 
843 GENERATE_DEBUG_STRUCTS(wmi_command_log);
844 GENERATE_DEBUG_STRUCTS(wmi_command_tx_cmp_log);
845 GENERATE_DEBUG_STRUCTS(wmi_event_log);
846 GENERATE_DEBUG_STRUCTS(wmi_rx_event_log);
847 GENERATE_DEBUG_STRUCTS(wmi_mgmt_command_log);
848 GENERATE_DEBUG_STRUCTS(wmi_mgmt_command_tx_cmp_log);
849 GENERATE_DEBUG_STRUCTS(wmi_mgmt_event_log);
850 GENERATE_DEBUG_STRUCTS(wmi_enable);
851 GENERATE_DEBUG_STRUCTS(wmi_log_size);
852 
853 struct wmi_debugfs_info wmi_debugfs_infos[] = {
854 	DEBUG_FOO(wmi_command_log),
855 	DEBUG_FOO(wmi_command_tx_cmp_log),
856 	DEBUG_FOO(wmi_event_log),
857 	DEBUG_FOO(wmi_rx_event_log),
858 	DEBUG_FOO(wmi_mgmt_command_log),
859 	DEBUG_FOO(wmi_mgmt_command_tx_cmp_log),
860 	DEBUG_FOO(wmi_mgmt_event_log),
861 	DEBUG_FOO(wmi_enable),
862 	DEBUG_FOO(wmi_log_size),
863 };
864 
865 #define NUM_DEBUG_INFOS (sizeof(wmi_debugfs_infos) /			\
866 		sizeof(wmi_debugfs_infos[0]))
867 
868 /**
869  * wmi_debugfs_create() - Create debug_fs entry for wmi logging.
870  *
871  * @wmi_handle: wmi handle
872  * @par_entry: debug directory entry
873  * @id: Index to debug info data array
874  *
875  * Return: none
876  */
877 static void wmi_debugfs_create(wmi_unified_t wmi_handle,
878 		struct dentry *par_entry, int id)
879 {
880 	int i;
881 
882 	if (par_entry == NULL || (id < 0) || (id >= MAX_WMI_INSTANCES))
883 		goto out;
884 
885 	for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
886 
887 		wmi_debugfs_infos[i].de[id] = debugfs_create_file(
888 				wmi_debugfs_infos[i].name, 0644, par_entry,
889 				wmi_handle, wmi_debugfs_infos[i].ops);
890 
891 		if (wmi_debugfs_infos[i].de[id] == NULL) {
892 			qdf_print("%s: debug Entry creation failed!\n",
893 					__func__);
894 			goto out;
895 		}
896 	}
897 
898 	return;
899 
900 out:
901 	qdf_print("%s: debug Entry creation failed!\n", __func__);
902 	wmi_log_buffer_free(wmi_handle);
903 	return;
904 }
905 
906 /**
907  * wmi_debugfs_remove() - Remove debugfs entry for wmi logging.
908  * @wmi_handle: wmi handle
909  * @dentry: debugfs directory entry
910  * @id: Index to debug info data array
911  *
912  * Return: none
913  */
914 static void wmi_debugfs_remove(wmi_unified_t wmi_handle)
915 {
916 	int i;
917 	struct dentry *dentry = wmi_handle->log_info.wmi_log_debugfs_dir;
918 	int id = wmi_handle->log_info.wmi_instance_id;
919 
920 	if (dentry && (!(id < 0) || (id >= MAX_WMI_INSTANCES))) {
921 		for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
922 			if (wmi_debugfs_infos[i].de[id])
923 				wmi_debugfs_infos[i].de[id] = NULL;
924 		}
925 	}
926 
927 	if (dentry)
928 		debugfs_remove_recursive(dentry);
929 }
930 
931 /**
932  * wmi_debugfs_init() - debugfs functions to create debugfs directory and to
933  * create debugfs enteries.
934  *
935  * @h: wmi handler
936  *
937  * Return: init status
938  */
939 static QDF_STATUS wmi_debugfs_init(wmi_unified_t wmi_handle)
940 {
941 	static int wmi_index;
942 
943 	if (wmi_index < MAX_WMI_INSTANCES)
944 		wmi_handle->log_info.wmi_log_debugfs_dir =
945 			debugfs_create_dir(debugfs_dir[wmi_index], NULL);
946 
947 	if (wmi_handle->log_info.wmi_log_debugfs_dir == NULL) {
948 		qdf_print("error while creating debugfs dir for %s\n",
949 				debugfs_dir[wmi_index]);
950 		return QDF_STATUS_E_FAILURE;
951 	}
952 
953 	wmi_debugfs_create(wmi_handle, wmi_handle->log_info.wmi_log_debugfs_dir,
954 				wmi_index);
955 	wmi_handle->log_info.wmi_instance_id = wmi_index++;
956 
957 	return QDF_STATUS_SUCCESS;
958 }
959 
960 /**
961  * wmi_mgmt_cmd_record() - Wrapper function for mgmt command logging macro
962  *
963  * @wmi_handle: wmi handle
964  * @cmd: mgmt command
965  * @header: pointer to 802.11 header
966  * @vdev_id: vdev id
967  * @chanfreq: channel frequency
968  *
969  * Return: none
970  */
971 void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
972 			void *header, uint32_t vdev_id, uint32_t chanfreq)
973 {
974 
975 	uint32_t data[CUSTOM_MGMT_CMD_DATA_SIZE];
976 
977 	data[0] = ((struct wmi_command_header *)header)->type;
978 	data[1] = ((struct wmi_command_header *)header)->sub_type;
979 	data[2] = vdev_id;
980 	data[3] = chanfreq;
981 
982 	qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
983 
984 	WMI_MGMT_COMMAND_RECORD(wmi_handle, cmd, data);
985 
986 	qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
987 }
988 #else
989 /**
990  * wmi_debugfs_remove() - Remove debugfs entry for wmi logging.
991  * @wmi_handle: wmi handle
992  * @dentry: debugfs directory entry
993  * @id: Index to debug info data array
994  *
995  * Return: none
996  */
997 static void wmi_debugfs_remove(wmi_unified_t wmi_handle) { }
998 void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
999 			void *header, uint32_t vdev_id, uint32_t chanfreq) { }
1000 #endif /*WMI_INTERFACE_EVENT_LOGGING */
1001 
1002 int wmi_get_host_credits(wmi_unified_t wmi_handle);
1003 /* WMI buffer APIs */
1004 
1005 #ifdef MEMORY_DEBUG
1006 wmi_buf_t
1007 wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint16_t len, uint8_t *file_name,
1008 			uint32_t line_num)
1009 {
1010 	wmi_buf_t wmi_buf;
1011 
1012 	if (roundup(len + WMI_MIN_HEAD_ROOM, 4) > wmi_handle->max_msg_len) {
1013 		QDF_ASSERT(0);
1014 		return NULL;
1015 	}
1016 
1017 	wmi_buf = qdf_nbuf_alloc_debug(NULL,
1018 					roundup(len + WMI_MIN_HEAD_ROOM, 4),
1019 					WMI_MIN_HEAD_ROOM, 4, false, file_name,
1020 					line_num);
1021 
1022 	if (!wmi_buf)
1023 		return NULL;
1024 
1025 	/* Clear the wmi buffer */
1026 	OS_MEMZERO(qdf_nbuf_data(wmi_buf), len);
1027 
1028 	/*
1029 	 * Set the length of the buffer to match the allocation size.
1030 	 */
1031 	qdf_nbuf_set_pktlen(wmi_buf, len);
1032 
1033 	return wmi_buf;
1034 }
1035 
1036 void wmi_buf_free(wmi_buf_t net_buf)
1037 {
1038 	qdf_nbuf_free(net_buf);
1039 }
1040 #else
1041 wmi_buf_t wmi_buf_alloc(wmi_unified_t wmi_handle, uint16_t len)
1042 {
1043 	wmi_buf_t wmi_buf;
1044 
1045 	if (roundup(len + WMI_MIN_HEAD_ROOM, 4) > wmi_handle->max_msg_len) {
1046 		QDF_ASSERT(0);
1047 		return NULL;
1048 	}
1049 
1050 	wmi_buf = qdf_nbuf_alloc(NULL, roundup(len + WMI_MIN_HEAD_ROOM, 4),
1051 				WMI_MIN_HEAD_ROOM, 4, false);
1052 	if (!wmi_buf)
1053 		return NULL;
1054 
1055 	/* Clear the wmi buffer */
1056 	OS_MEMZERO(qdf_nbuf_data(wmi_buf), len);
1057 
1058 	/*
1059 	 * Set the length of the buffer to match the allocation size.
1060 	 */
1061 	qdf_nbuf_set_pktlen(wmi_buf, len);
1062 	return wmi_buf;
1063 }
1064 
1065 void wmi_buf_free(wmi_buf_t net_buf)
1066 {
1067 	qdf_nbuf_free(net_buf);
1068 }
1069 #endif
1070 
1071 /**
1072  * wmi_get_max_msg_len() - get maximum WMI message length
1073  * @wmi_handle: WMI handle.
1074  *
1075  * This function returns the maximum WMI message length
1076  *
1077  * Return: maximum WMI message length
1078  */
1079 uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle)
1080 {
1081 	return wmi_handle->max_msg_len - WMI_MIN_HEAD_ROOM;
1082 }
1083 
1084 #ifdef CONFIG_MCL
1085 static uint8_t *wmi_id_to_name(uint32_t wmi_command)
1086 {
1087 	switch (wmi_command) {
1088 		/* initialize the wlan sub system */
1089 		CASE_RETURN_STRING(WMI_INIT_CMDID);
1090 
1091 		/* Scan specific commands */
1092 
1093 		/* start scan request to FW  */
1094 		CASE_RETURN_STRING(WMI_START_SCAN_CMDID);
1095 		/* stop scan request to FW  */
1096 		CASE_RETURN_STRING(WMI_STOP_SCAN_CMDID);
1097 		/* full list of channels as defined by the regulatory
1098 		 * that will be used by scanner   */
1099 		CASE_RETURN_STRING(WMI_SCAN_CHAN_LIST_CMDID);
1100 		/* overwrite default priority table in scan scheduler   */
1101 		CASE_RETURN_STRING(WMI_SCAN_SCH_PRIO_TBL_CMDID);
1102 		/* This command to adjust the priority and min.max_rest_time
1103 		 * of an on ongoing scan request.
1104 		 */
1105 		CASE_RETURN_STRING(WMI_SCAN_UPDATE_REQUEST_CMDID);
1106 
1107 		/* PDEV(physical device) specific commands */
1108 		/* set regulatorty ctl id used by FW to determine the exact
1109 		 * ctl power limits */
1110 		CASE_RETURN_STRING(WMI_PDEV_SET_REGDOMAIN_CMDID);
1111 		/* set channel. mainly used for supporting monitor mode */
1112 		CASE_RETURN_STRING(WMI_PDEV_SET_CHANNEL_CMDID);
1113 		/* set pdev specific parameters */
1114 		CASE_RETURN_STRING(WMI_PDEV_SET_PARAM_CMDID);
1115 		/* enable packet log */
1116 		CASE_RETURN_STRING(WMI_PDEV_PKTLOG_ENABLE_CMDID);
1117 		/* disable packet log*/
1118 		CASE_RETURN_STRING(WMI_PDEV_PKTLOG_DISABLE_CMDID);
1119 		/* set wmm parameters */
1120 		CASE_RETURN_STRING(WMI_PDEV_SET_WMM_PARAMS_CMDID);
1121 		/* set HT cap ie that needs to be carried probe requests
1122 		 * HT/VHT channels */
1123 		CASE_RETURN_STRING(WMI_PDEV_SET_HT_CAP_IE_CMDID);
1124 		/* set VHT cap ie that needs to be carried on probe
1125 		 * requests on VHT channels */
1126 		CASE_RETURN_STRING(WMI_PDEV_SET_VHT_CAP_IE_CMDID);
1127 
1128 		/* Command to send the DSCP-to-TID map to the target */
1129 		CASE_RETURN_STRING(WMI_PDEV_SET_DSCP_TID_MAP_CMDID);
1130 		/* set quiet ie parameters. primarily used in AP mode */
1131 		CASE_RETURN_STRING(WMI_PDEV_SET_QUIET_MODE_CMDID);
1132 		/* Enable/Disable Green AP Power Save  */
1133 		CASE_RETURN_STRING(WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID);
1134 		/* get TPC config for the current operating channel */
1135 		CASE_RETURN_STRING(WMI_PDEV_GET_TPC_CONFIG_CMDID);
1136 
1137 		/* set the base MAC address for the physical device before
1138 		 * a VDEV is created. For firmware that does not support
1139 		 * this feature and this command, the pdev MAC address will
1140 		 * not be changed. */
1141 		CASE_RETURN_STRING(WMI_PDEV_SET_BASE_MACADDR_CMDID);
1142 
1143 		/* eeprom content dump , the same to bdboard data */
1144 		CASE_RETURN_STRING(WMI_PDEV_DUMP_CMDID);
1145 
1146 		/* VDEV(virtual device) specific commands */
1147 		/* vdev create */
1148 		CASE_RETURN_STRING(WMI_VDEV_CREATE_CMDID);
1149 		/* vdev delete */
1150 		CASE_RETURN_STRING(WMI_VDEV_DELETE_CMDID);
1151 		/* vdev start request */
1152 		CASE_RETURN_STRING(WMI_VDEV_START_REQUEST_CMDID);
1153 		/* vdev restart request (RX only, NO TX, used for CAC period)*/
1154 		CASE_RETURN_STRING(WMI_VDEV_RESTART_REQUEST_CMDID);
1155 		/* vdev up request */
1156 		CASE_RETURN_STRING(WMI_VDEV_UP_CMDID);
1157 		/* vdev stop request */
1158 		CASE_RETURN_STRING(WMI_VDEV_STOP_CMDID);
1159 		/* vdev down request */
1160 		CASE_RETURN_STRING(WMI_VDEV_DOWN_CMDID);
1161 		/* set a vdev param */
1162 		CASE_RETURN_STRING(WMI_VDEV_SET_PARAM_CMDID);
1163 		/* set a key (used for setting per peer unicast
1164 		 * and per vdev multicast) */
1165 		CASE_RETURN_STRING(WMI_VDEV_INSTALL_KEY_CMDID);
1166 
1167 		/* wnm sleep mode command */
1168 		CASE_RETURN_STRING(WMI_VDEV_WNM_SLEEPMODE_CMDID);
1169 		CASE_RETURN_STRING(WMI_VDEV_WMM_ADDTS_CMDID);
1170 		CASE_RETURN_STRING(WMI_VDEV_WMM_DELTS_CMDID);
1171 		CASE_RETURN_STRING(WMI_VDEV_SET_WMM_PARAMS_CMDID);
1172 		CASE_RETURN_STRING(WMI_VDEV_SET_GTX_PARAMS_CMDID);
1173 		CASE_RETURN_STRING(WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID);
1174 
1175 		CASE_RETURN_STRING(WMI_VDEV_PLMREQ_START_CMDID);
1176 		CASE_RETURN_STRING(WMI_VDEV_PLMREQ_STOP_CMDID);
1177 		CASE_RETURN_STRING(WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
1178 		CASE_RETURN_STRING(WMI_VDEV_SET_IE_CMDID);
1179 
1180 		/* peer specific commands */
1181 
1182 		/** create a peer */
1183 		CASE_RETURN_STRING(WMI_PEER_CREATE_CMDID);
1184 		/** delete a peer */
1185 		CASE_RETURN_STRING(WMI_PEER_DELETE_CMDID);
1186 		/** flush specific  tid queues of a peer */
1187 		CASE_RETURN_STRING(WMI_PEER_FLUSH_TIDS_CMDID);
1188 		/** set a parameter of a peer */
1189 		CASE_RETURN_STRING(WMI_PEER_SET_PARAM_CMDID);
1190 		/* set peer to associated state. will cary all parameters
1191 		 * determined during assocication time */
1192 		CASE_RETURN_STRING(WMI_PEER_ASSOC_CMDID);
1193 		/* add a wds  (4 address ) entry. used only for testing
1194 		 * WDS feature on AP products */
1195 		CASE_RETURN_STRING(WMI_PEER_ADD_WDS_ENTRY_CMDID);
1196 		/* remove wds  (4 address ) entry. used only for testing WDS
1197 		 * feature on AP products */
1198 		CASE_RETURN_STRING(WMI_PEER_REMOVE_WDS_ENTRY_CMDID);
1199 		/* set up mcast info for multicast to unicast conversion */
1200 		CASE_RETURN_STRING(WMI_PEER_MCAST_GROUP_CMDID);
1201 		/* request peer info from FW to get PEER_INFO_EVENTID */
1202 		CASE_RETURN_STRING(WMI_PEER_INFO_REQ_CMDID);
1203 
1204 		/* beacon/management specific commands */
1205 
1206 		/* transmit beacon by reference. used for transmitting beacon
1207 		 * on low latency interface like pcie */
1208 		CASE_RETURN_STRING(WMI_BCN_TX_CMDID);
1209 		/* transmit beacon by value */
1210 		CASE_RETURN_STRING(WMI_PDEV_SEND_BCN_CMDID);
1211 		/* set the beacon template. used in beacon offload mode to setup
1212 		 * the common beacon template with the FW to be used by FW to
1213 		 * generate beacons */
1214 		CASE_RETURN_STRING(WMI_BCN_TMPL_CMDID);
1215 		/* set beacon filter with FW */
1216 		CASE_RETURN_STRING(WMI_BCN_FILTER_RX_CMDID);
1217 		/* enable/disable filtering of probe requests in the firmware */
1218 		CASE_RETURN_STRING(WMI_PRB_REQ_FILTER_RX_CMDID);
1219 		/* transmit management frame by value. will be deprecated */
1220 		CASE_RETURN_STRING(WMI_MGMT_TX_CMDID);
1221 		/* set the probe response template. used in beacon offload mode
1222 		 * to setup the common probe response template with the FW to
1223 		 * be used by FW to generate probe responses */
1224 		CASE_RETURN_STRING(WMI_PRB_TMPL_CMDID);
1225 
1226 		/* commands to directly control ba negotiation directly from
1227 		 * host. only used in test mode */
1228 
1229 		/* turn off FW Auto addba mode and let host control addba */
1230 		CASE_RETURN_STRING(WMI_ADDBA_CLEAR_RESP_CMDID);
1231 		/* send add ba request */
1232 		CASE_RETURN_STRING(WMI_ADDBA_SEND_CMDID);
1233 		CASE_RETURN_STRING(WMI_ADDBA_STATUS_CMDID);
1234 		/* send del ba */
1235 		CASE_RETURN_STRING(WMI_DELBA_SEND_CMDID);
1236 		/* set add ba response will be used by FW to generate
1237 		 * addba response*/
1238 		CASE_RETURN_STRING(WMI_ADDBA_SET_RESP_CMDID);
1239 		/* send single VHT MPDU with AMSDU */
1240 		CASE_RETURN_STRING(WMI_SEND_SINGLEAMSDU_CMDID);
1241 
1242 		/* Station power save specific config */
1243 		/* enable/disable station powersave */
1244 		CASE_RETURN_STRING(WMI_STA_POWERSAVE_MODE_CMDID);
1245 		/* set station power save specific parameter */
1246 		CASE_RETURN_STRING(WMI_STA_POWERSAVE_PARAM_CMDID);
1247 		/* set station mimo powersave mode */
1248 		CASE_RETURN_STRING(WMI_STA_MIMO_PS_MODE_CMDID);
1249 
1250 		/* DFS-specific commands */
1251 		/* enable DFS (radar detection)*/
1252 		CASE_RETURN_STRING(WMI_PDEV_DFS_ENABLE_CMDID);
1253 		/* disable DFS (radar detection)*/
1254 		CASE_RETURN_STRING(WMI_PDEV_DFS_DISABLE_CMDID);
1255 		/* enable DFS phyerr/parse filter offload */
1256 		CASE_RETURN_STRING(WMI_DFS_PHYERR_FILTER_ENA_CMDID);
1257 		/* enable DFS phyerr/parse filter offload */
1258 		CASE_RETURN_STRING(WMI_DFS_PHYERR_FILTER_DIS_CMDID);
1259 
1260 		/* Roaming specific  commands */
1261 		/* set roam scan mode */
1262 		CASE_RETURN_STRING(WMI_ROAM_SCAN_MODE);
1263 		/* set roam scan rssi threshold below which roam
1264 		 * scan is enabled  */
1265 		CASE_RETURN_STRING(WMI_ROAM_SCAN_RSSI_THRESHOLD);
1266 		/* set roam scan period for periodic roam scan mode  */
1267 		CASE_RETURN_STRING(WMI_ROAM_SCAN_PERIOD);
1268 		/* set roam scan trigger rssi change threshold   */
1269 		CASE_RETURN_STRING(WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD);
1270 		/* set roam AP profile   */
1271 		CASE_RETURN_STRING(WMI_ROAM_AP_PROFILE);
1272 		/* set channel list for roam scans */
1273 		CASE_RETURN_STRING(WMI_ROAM_CHAN_LIST);
1274 		/* offload scan specific commands */
1275 		/* set offload scan AP profile   */
1276 		CASE_RETURN_STRING(WMI_OFL_SCAN_ADD_AP_PROFILE);
1277 		/* remove offload scan AP profile   */
1278 		CASE_RETURN_STRING(WMI_OFL_SCAN_REMOVE_AP_PROFILE);
1279 		/* set offload scan period   */
1280 		CASE_RETURN_STRING(WMI_OFL_SCAN_PERIOD);
1281 
1282 		/* P2P specific commands */
1283 		/* set P2P device info. FW will used by FW to create P2P IE
1284 		 * to be carried in probe response generated during p2p listen
1285 		 * and for p2p discoverability  */
1286 		CASE_RETURN_STRING(WMI_P2P_DEV_SET_DEVICE_INFO);
1287 		/* enable/disable p2p discoverability on STA/AP VDEVs  */
1288 		CASE_RETURN_STRING(WMI_P2P_DEV_SET_DISCOVERABILITY);
1289 		/* set p2p ie to be carried in beacons generated by FW for GO */
1290 		CASE_RETURN_STRING(WMI_P2P_GO_SET_BEACON_IE);
1291 		/* set p2p ie to be carried in probe response frames generated
1292 		 * by FW for GO  */
1293 		CASE_RETURN_STRING(WMI_P2P_GO_SET_PROBE_RESP_IE);
1294 		/* set the vendor specific p2p ie data.
1295 		 * FW will use this to parse the P2P NoA
1296 		 * attribute in the beacons/probe responses received.
1297 		 */
1298 		CASE_RETURN_STRING(WMI_P2P_SET_VENDOR_IE_DATA_CMDID);
1299 		/* set the configure of p2p find offload */
1300 		CASE_RETURN_STRING(WMI_P2P_DISC_OFFLOAD_CONFIG_CMDID);
1301 		/* set the vendor specific p2p ie data for p2p find offload */
1302 		CASE_RETURN_STRING(WMI_P2P_DISC_OFFLOAD_APPIE_CMDID);
1303 		/* set the BSSID/device name pattern of p2p find offload */
1304 		CASE_RETURN_STRING(WMI_P2P_DISC_OFFLOAD_PATTERN_CMDID);
1305 		/* set OppPS related parameters **/
1306 		CASE_RETURN_STRING(WMI_P2P_SET_OPPPS_PARAM_CMDID);
1307 
1308 		/* AP power save specific config
1309 		 * set AP power save specific param */
1310 		CASE_RETURN_STRING(WMI_AP_PS_PEER_PARAM_CMDID);
1311 		/* set AP UAPSD coex pecific param */
1312 		CASE_RETURN_STRING(WMI_AP_PS_PEER_UAPSD_COEX_CMDID);
1313 
1314 		/* Rate-control specific commands */
1315 		CASE_RETURN_STRING(WMI_PEER_RATE_RETRY_SCHED_CMDID);
1316 
1317 		/* WLAN Profiling commands. */
1318 		CASE_RETURN_STRING(WMI_WLAN_PROFILE_TRIGGER_CMDID);
1319 		CASE_RETURN_STRING(WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID);
1320 		CASE_RETURN_STRING(WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID);
1321 		CASE_RETURN_STRING(WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID);
1322 		CASE_RETURN_STRING(WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID);
1323 
1324 		/* Suspend resume command Ids */
1325 		CASE_RETURN_STRING(WMI_PDEV_SUSPEND_CMDID);
1326 		CASE_RETURN_STRING(WMI_PDEV_RESUME_CMDID);
1327 
1328 		/* Beacon filter commands */
1329 		/* add a beacon filter */
1330 		CASE_RETURN_STRING(WMI_ADD_BCN_FILTER_CMDID);
1331 		/* remove a  beacon filter */
1332 		CASE_RETURN_STRING(WMI_RMV_BCN_FILTER_CMDID);
1333 
1334 		/* WOW Specific WMI commands */
1335 		/* add pattern for awake */
1336 		CASE_RETURN_STRING(WMI_WOW_ADD_WAKE_PATTERN_CMDID);
1337 		/* deleta a wake pattern */
1338 		CASE_RETURN_STRING(WMI_WOW_DEL_WAKE_PATTERN_CMDID);
1339 		/* enable/deisable wake event  */
1340 		CASE_RETURN_STRING(WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
1341 		/* enable WOW  */
1342 		CASE_RETURN_STRING(WMI_WOW_ENABLE_CMDID);
1343 		/* host woke up from sleep event to FW. Generated in response
1344 		 * to WOW Hardware event */
1345 		CASE_RETURN_STRING(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
1346 
1347 		/* RTT measurement related cmd */
1348 		/* reques to make an RTT measurement */
1349 		CASE_RETURN_STRING(WMI_RTT_MEASREQ_CMDID);
1350 		/* reques to report a tsf measurement */
1351 		CASE_RETURN_STRING(WMI_RTT_TSF_CMDID);
1352 
1353 		/* spectral scan command */
1354 		/* configure spectral scan */
1355 		CASE_RETURN_STRING(WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID);
1356 		/* enable/disable spectral scan and trigger */
1357 		CASE_RETURN_STRING(WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID);
1358 
1359 		/* F/W stats */
1360 		/* one time request for stats */
1361 		CASE_RETURN_STRING(WMI_REQUEST_STATS_CMDID);
1362 		/* Push MCC Adaptive Scheduler Stats to Firmware */
1363 		CASE_RETURN_STRING(WMI_MCC_SCHED_TRAFFIC_STATS_CMDID);
1364 
1365 		/* ARP OFFLOAD REQUEST*/
1366 		CASE_RETURN_STRING(WMI_SET_ARP_NS_OFFLOAD_CMDID);
1367 
1368 		/* Proactive ARP Response Add Pattern Command*/
1369 		CASE_RETURN_STRING(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID);
1370 
1371 		/* Proactive ARP Response Del Pattern Command*/
1372 		CASE_RETURN_STRING(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID);
1373 
1374 		/* NS offload confid*/
1375 		CASE_RETURN_STRING(WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
1376 
1377 		/* GTK offload Specific WMI commands */
1378 		CASE_RETURN_STRING(WMI_GTK_OFFLOAD_CMDID);
1379 
1380 		/* CSA offload Specific WMI commands */
1381 		/* csa offload enable */
1382 		CASE_RETURN_STRING(WMI_CSA_OFFLOAD_ENABLE_CMDID);
1383 		/* chan switch command */
1384 		CASE_RETURN_STRING(WMI_CSA_OFFLOAD_CHANSWITCH_CMDID);
1385 
1386 		/* Chatter commands */
1387 		/* Change chatter mode of operation */
1388 		CASE_RETURN_STRING(WMI_CHATTER_SET_MODE_CMDID);
1389 		/* chatter add coalescing filter command */
1390 		CASE_RETURN_STRING(WMI_CHATTER_ADD_COALESCING_FILTER_CMDID);
1391 		/* chatter delete coalescing filter command */
1392 		CASE_RETURN_STRING(WMI_CHATTER_DELETE_COALESCING_FILTER_CMDID);
1393 		/* chatter coalecing query command */
1394 		CASE_RETURN_STRING(WMI_CHATTER_COALESCING_QUERY_CMDID);
1395 
1396 		/* addba specific commands */
1397 		/* start the aggregation on this TID */
1398 		CASE_RETURN_STRING(WMI_PEER_TID_ADDBA_CMDID);
1399 		/* stop the aggregation on this TID */
1400 		CASE_RETURN_STRING(WMI_PEER_TID_DELBA_CMDID);
1401 
1402 		/* set station mimo powersave method */
1403 		CASE_RETURN_STRING(WMI_STA_DTIM_PS_METHOD_CMDID);
1404 		/* Configure the Station UAPSD AC Auto Trigger Parameters */
1405 		CASE_RETURN_STRING(WMI_STA_UAPSD_AUTO_TRIG_CMDID);
1406 		/* Configure the Keep Alive Parameters */
1407 		CASE_RETURN_STRING(WMI_STA_KEEPALIVE_CMDID);
1408 
1409 		/* Request ssn from target for a sta/tid pair */
1410 		CASE_RETURN_STRING(WMI_BA_REQ_SSN_CMDID);
1411 		/* misc command group */
1412 		/* echo command mainly used for testing */
1413 		CASE_RETURN_STRING(WMI_ECHO_CMDID);
1414 
1415 		/* !!IMPORTANT!!
1416 		 * If you need to add a new WMI command to the CASE_RETURN_STRING(WMI_GRP_MISC sub-group,
1417 		 * please make sure you add it BEHIND CASE_RETURN_STRING(WMI_PDEV_UTF_CMDID);
1418 		 * as we MUST have a fixed value here to maintain compatibility between
1419 		 * UTF and the ART2 driver
1420 		 */
1421 		/* UTF WMI commands */
1422 		CASE_RETURN_STRING(WMI_PDEV_UTF_CMDID);
1423 
1424 		/* set debug log config */
1425 		CASE_RETURN_STRING(WMI_DBGLOG_CFG_CMDID);
1426 		/* QVIT specific command id */
1427 		CASE_RETURN_STRING(WMI_PDEV_QVIT_CMDID);
1428 		/* Factory Testing Mode request command
1429 		 * used for integrated chipsets */
1430 		CASE_RETURN_STRING(WMI_PDEV_FTM_INTG_CMDID);
1431 		/* set and get keepalive parameters command */
1432 		CASE_RETURN_STRING(WMI_VDEV_SET_KEEPALIVE_CMDID);
1433 		CASE_RETURN_STRING(WMI_VDEV_GET_KEEPALIVE_CMDID);
1434 		/* For fw recovery test command */
1435 		CASE_RETURN_STRING(WMI_FORCE_FW_HANG_CMDID);
1436 		/* Set Mcast/Bdcast filter */
1437 		CASE_RETURN_STRING(WMI_SET_MCASTBCAST_FILTER_CMDID);
1438 		/* set thermal management params */
1439 		CASE_RETURN_STRING(WMI_THERMAL_MGMT_CMDID);
1440 		CASE_RETURN_STRING(WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID);
1441 		CASE_RETURN_STRING(WMI_LRO_CONFIG_CMDID);
1442 		CASE_RETURN_STRING(WMI_TRANSFER_DATA_TO_FLASH_CMDID);
1443 		CASE_RETURN_STRING(WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
1444 		CASE_RETURN_STRING(WMI_VDEV_WISA_CMDID);
1445 		CASE_RETURN_STRING(WMI_SCAN_ADAPTIVE_DWELL_CONFIG_CMDID);
1446 		CASE_RETURN_STRING(WMI_WOW_SET_ACTION_WAKE_UP_CMDID);
1447 		CASE_RETURN_STRING(WMI_MAWC_SENSOR_REPORT_IND_CMDID);
1448 		CASE_RETURN_STRING(WMI_ROAM_CONFIGURE_MAWC_CMDID);
1449 		CASE_RETURN_STRING(WMI_NLO_CONFIGURE_MAWC_CMDID);
1450 		CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_MAWC_CMDID);
1451 		/* GPIO Configuration */
1452 		CASE_RETURN_STRING(WMI_GPIO_CONFIG_CMDID);
1453 		CASE_RETURN_STRING(WMI_GPIO_OUTPUT_CMDID);
1454 
1455 		/* Txbf configuration command */
1456 		CASE_RETURN_STRING(WMI_TXBF_CMDID);
1457 
1458 		/* FWTEST Commands */
1459 		CASE_RETURN_STRING(WMI_FWTEST_VDEV_MCC_SET_TBTT_MODE_CMDID);
1460 		/* set NoA descs */
1461 		CASE_RETURN_STRING(WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID);
1462 
1463 		/* TDLS Configuration */
1464 		/* enable/disable TDLS */
1465 		CASE_RETURN_STRING(WMI_TDLS_SET_STATE_CMDID);
1466 		/* set tdls peer state */
1467 		CASE_RETURN_STRING(WMI_TDLS_PEER_UPDATE_CMDID);
1468 
1469 		/* Resmgr Configuration */
1470 		/* Adaptive OCS is enabled by default in the FW.
1471 		 * This command is used to disable FW based adaptive OCS.
1472 		 */
1473 		CASE_RETURN_STRING
1474 			(WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID);
1475 		/* set the requested channel time quota for the home channels */
1476 		CASE_RETURN_STRING(WMI_RESMGR_SET_CHAN_TIME_QUOTA_CMDID);
1477 		/* set the requested latency for the home channels */
1478 		CASE_RETURN_STRING(WMI_RESMGR_SET_CHAN_LATENCY_CMDID);
1479 
1480 		/* STA SMPS Configuration */
1481 		/* force SMPS mode */
1482 		CASE_RETURN_STRING(WMI_STA_SMPS_FORCE_MODE_CMDID);
1483 		/* set SMPS parameters */
1484 		CASE_RETURN_STRING(WMI_STA_SMPS_PARAM_CMDID);
1485 
1486 		/* Wlan HB commands */
1487 		/* enalbe/disable wlan HB */
1488 		CASE_RETURN_STRING(WMI_HB_SET_ENABLE_CMDID);
1489 		/* set tcp parameters for wlan HB */
1490 		CASE_RETURN_STRING(WMI_HB_SET_TCP_PARAMS_CMDID);
1491 		/* set tcp pkt filter for wlan HB */
1492 		CASE_RETURN_STRING(WMI_HB_SET_TCP_PKT_FILTER_CMDID);
1493 		/* set udp parameters for wlan HB */
1494 		CASE_RETURN_STRING(WMI_HB_SET_UDP_PARAMS_CMDID);
1495 		/* set udp pkt filter for wlan HB */
1496 		CASE_RETURN_STRING(WMI_HB_SET_UDP_PKT_FILTER_CMDID);
1497 
1498 		/* Wlan RMC commands*/
1499 		/* enable/disable RMC */
1500 		CASE_RETURN_STRING(WMI_RMC_SET_MODE_CMDID);
1501 		/* configure action frame period */
1502 		CASE_RETURN_STRING(WMI_RMC_SET_ACTION_PERIOD_CMDID);
1503 		/* For debug/future enhancement purposes only,
1504 		 * configures/finetunes RMC algorithms */
1505 		CASE_RETURN_STRING(WMI_RMC_CONFIG_CMDID);
1506 
1507 		/* WLAN MHF offload commands */
1508 		/* enable/disable MHF offload */
1509 		CASE_RETURN_STRING(WMI_MHF_OFFLOAD_SET_MODE_CMDID);
1510 		/* Plumb routing table for MHF offload */
1511 		CASE_RETURN_STRING(WMI_MHF_OFFLOAD_PLUMB_ROUTING_TBL_CMDID);
1512 
1513 		/* location scan commands */
1514 		/* start batch scan */
1515 		CASE_RETURN_STRING(WMI_BATCH_SCAN_ENABLE_CMDID);
1516 		/* stop batch scan */
1517 		CASE_RETURN_STRING(WMI_BATCH_SCAN_DISABLE_CMDID);
1518 		/* get batch scan result */
1519 		CASE_RETURN_STRING(WMI_BATCH_SCAN_TRIGGER_RESULT_CMDID);
1520 		/* OEM related cmd */
1521 		CASE_RETURN_STRING(WMI_OEM_REQ_CMDID);
1522 		CASE_RETURN_STRING(WMI_OEM_REQUEST_CMDID);
1523 		/* NAN request cmd */
1524 		CASE_RETURN_STRING(WMI_NAN_CMDID);
1525 		/* Modem power state cmd */
1526 		CASE_RETURN_STRING(WMI_MODEM_POWER_STATE_CMDID);
1527 		CASE_RETURN_STRING(WMI_REQUEST_STATS_EXT_CMDID);
1528 		CASE_RETURN_STRING(WMI_OBSS_SCAN_ENABLE_CMDID);
1529 		CASE_RETURN_STRING(WMI_OBSS_SCAN_DISABLE_CMDID);
1530 		CASE_RETURN_STRING(WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID);
1531 		CASE_RETURN_STRING(WMI_ROAM_SCAN_CMD);
1532 		CASE_RETURN_STRING(WMI_PDEV_SET_LED_CONFIG_CMDID);
1533 		CASE_RETURN_STRING(WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID);
1534 		CASE_RETURN_STRING(WMI_CHAN_AVOID_UPDATE_CMDID);
1535 		CASE_RETURN_STRING(WMI_COEX_CONFIG_CMDID);
1536 		CASE_RETURN_STRING(WMI_WOW_IOAC_ADD_KEEPALIVE_CMDID);
1537 		CASE_RETURN_STRING(WMI_WOW_IOAC_DEL_KEEPALIVE_CMDID);
1538 		CASE_RETURN_STRING(WMI_WOW_IOAC_ADD_WAKE_PATTERN_CMDID);
1539 		CASE_RETURN_STRING(WMI_WOW_IOAC_DEL_WAKE_PATTERN_CMDID);
1540 		CASE_RETURN_STRING(WMI_REQUEST_LINK_STATS_CMDID);
1541 		CASE_RETURN_STRING(WMI_START_LINK_STATS_CMDID);
1542 		CASE_RETURN_STRING(WMI_CLEAR_LINK_STATS_CMDID);
1543 		CASE_RETURN_STRING(WMI_GET_FW_MEM_DUMP_CMDID);
1544 		CASE_RETURN_STRING(WMI_LPI_MGMT_SNOOPING_CONFIG_CMDID);
1545 		CASE_RETURN_STRING(WMI_LPI_START_SCAN_CMDID);
1546 		CASE_RETURN_STRING(WMI_LPI_STOP_SCAN_CMDID);
1547 		CASE_RETURN_STRING(WMI_EXTSCAN_START_CMDID);
1548 		CASE_RETURN_STRING(WMI_EXTSCAN_STOP_CMDID);
1549 		CASE_RETURN_STRING
1550 			(WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID);
1551 		CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID);
1552 		CASE_RETURN_STRING(WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID);
1553 		CASE_RETURN_STRING(WMI_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID);
1554 		CASE_RETURN_STRING(WMI_EXTSCAN_SET_CAPABILITIES_CMDID);
1555 		CASE_RETURN_STRING(WMI_EXTSCAN_GET_CAPABILITIES_CMDID);
1556 		CASE_RETURN_STRING(WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID);
1557 		CASE_RETURN_STRING(WMI_ROAM_SYNCH_COMPLETE);
1558 		CASE_RETURN_STRING(WMI_D0_WOW_ENABLE_DISABLE_CMDID);
1559 		CASE_RETURN_STRING(WMI_EXTWOW_ENABLE_CMDID);
1560 		CASE_RETURN_STRING(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID);
1561 		CASE_RETURN_STRING(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID);
1562 		CASE_RETURN_STRING(WMI_UNIT_TEST_CMDID);
1563 		CASE_RETURN_STRING(WMI_ROAM_SET_RIC_REQUEST_CMDID);
1564 		CASE_RETURN_STRING(WMI_PDEV_GET_TEMPERATURE_CMDID);
1565 		CASE_RETURN_STRING(WMI_SET_DHCP_SERVER_OFFLOAD_CMDID);
1566 		CASE_RETURN_STRING(WMI_TPC_CHAINMASK_CONFIG_CMDID);
1567 		CASE_RETURN_STRING(WMI_IPA_OFFLOAD_ENABLE_DISABLE_CMDID);
1568 		CASE_RETURN_STRING(WMI_SCAN_PROB_REQ_OUI_CMDID);
1569 		CASE_RETURN_STRING(WMI_TDLS_SET_OFFCHAN_MODE_CMDID);
1570 		CASE_RETURN_STRING(WMI_PDEV_SET_LED_FLASHING_CMDID);
1571 		CASE_RETURN_STRING(WMI_MDNS_OFFLOAD_ENABLE_CMDID);
1572 		CASE_RETURN_STRING(WMI_MDNS_SET_FQDN_CMDID);
1573 		CASE_RETURN_STRING(WMI_MDNS_SET_RESPONSE_CMDID);
1574 		CASE_RETURN_STRING(WMI_MDNS_GET_STATS_CMDID);
1575 		CASE_RETURN_STRING(WMI_ROAM_INVOKE_CMDID);
1576 		CASE_RETURN_STRING(WMI_SET_ANTENNA_DIVERSITY_CMDID);
1577 		CASE_RETURN_STRING(WMI_SAP_OFL_ENABLE_CMDID);
1578 		CASE_RETURN_STRING(WMI_APFIND_CMDID);
1579 		CASE_RETURN_STRING(WMI_PASSPOINT_LIST_CONFIG_CMDID);
1580 		CASE_RETURN_STRING(WMI_OCB_SET_SCHED_CMDID);
1581 		CASE_RETURN_STRING(WMI_OCB_SET_CONFIG_CMDID);
1582 		CASE_RETURN_STRING(WMI_OCB_SET_UTC_TIME_CMDID);
1583 		CASE_RETURN_STRING(WMI_OCB_START_TIMING_ADVERT_CMDID);
1584 		CASE_RETURN_STRING(WMI_OCB_STOP_TIMING_ADVERT_CMDID);
1585 		CASE_RETURN_STRING(WMI_OCB_GET_TSF_TIMER_CMDID);
1586 		CASE_RETURN_STRING(WMI_DCC_GET_STATS_CMDID);
1587 		CASE_RETURN_STRING(WMI_DCC_CLEAR_STATS_CMDID);
1588 		CASE_RETURN_STRING(WMI_DCC_UPDATE_NDL_CMDID);
1589 		CASE_RETURN_STRING(WMI_ROAM_FILTER_CMDID);
1590 		CASE_RETURN_STRING(WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID);
1591 		CASE_RETURN_STRING(WMI_DEBUG_MESG_FLUSH_CMDID);
1592 		CASE_RETURN_STRING(WMI_PEER_SET_RATE_REPORT_CONDITION_CMDID);
1593 		CASE_RETURN_STRING(WMI_SOC_SET_PCL_CMDID);
1594 		CASE_RETURN_STRING(WMI_SOC_SET_HW_MODE_CMDID);
1595 		CASE_RETURN_STRING(WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID);
1596 		CASE_RETURN_STRING(WMI_WOW_ENABLE_ICMPV6_NA_FLT_CMDID);
1597 		CASE_RETURN_STRING(WMI_DIAG_EVENT_LOG_CONFIG_CMDID);
1598 		CASE_RETURN_STRING(WMI_PACKET_FILTER_CONFIG_CMDID);
1599 		CASE_RETURN_STRING(WMI_PACKET_FILTER_ENABLE_CMDID);
1600 		CASE_RETURN_STRING(WMI_SAP_SET_BLACKLIST_PARAM_CMDID);
1601 		CASE_RETURN_STRING(WMI_WOW_UDP_SVC_OFLD_CMDID);
1602 		CASE_RETURN_STRING(WMI_MGMT_TX_SEND_CMDID);
1603 		CASE_RETURN_STRING(WMI_SOC_SET_ANTENNA_MODE_CMDID);
1604 		CASE_RETURN_STRING(WMI_WOW_HOSTWAKEUP_GPIO_PIN_PATTERN_CONFIG_CMDID);
1605 		CASE_RETURN_STRING(WMI_AP_PS_EGAP_PARAM_CMDID);
1606 		CASE_RETURN_STRING(WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID);
1607 		CASE_RETURN_STRING(WMI_BPF_GET_CAPABILITY_CMDID);
1608 		CASE_RETURN_STRING(WMI_BPF_GET_VDEV_STATS_CMDID);
1609 		CASE_RETURN_STRING(WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID);
1610 		CASE_RETURN_STRING(WMI_BPF_DEL_VDEV_INSTRUCTIONS_CMDID);
1611 		CASE_RETURN_STRING(WMI_NDI_GET_CAP_REQ_CMDID);
1612 		CASE_RETURN_STRING(WMI_NDP_INITIATOR_REQ_CMDID);
1613 		CASE_RETURN_STRING(WMI_NDP_RESPONDER_REQ_CMDID);
1614 		CASE_RETURN_STRING(WMI_NDP_END_REQ_CMDID);
1615 		CASE_RETURN_STRING(WMI_PEER_UPDATE_WDS_ENTRY_CMDID);
1616 		CASE_RETURN_STRING(WMI_PEER_ADD_PROXY_STA_ENTRY_CMDID);
1617 		CASE_RETURN_STRING(WMI_PDEV_FIPS_CMDID);
1618 		CASE_RETURN_STRING(WMI_PDEV_SMART_ANT_ENABLE_CMDID);
1619 		CASE_RETURN_STRING(WMI_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID);
1620 		CASE_RETURN_STRING(WMI_PDEV_SET_ANTENNA_SWITCH_TABLE_CMDID);
1621 		CASE_RETURN_STRING(WMI_PDEV_SET_CTL_TABLE_CMDID);
1622 		CASE_RETURN_STRING(WMI_PDEV_SET_MIMOGAIN_TABLE_CMDID);
1623 		CASE_RETURN_STRING(WMI_PDEV_GET_TPC_CMDID);
1624 		CASE_RETURN_STRING(WMI_MIB_STATS_ENABLE_CMDID);
1625 		CASE_RETURN_STRING(WMI_PDEV_GET_ANI_CCK_CONFIG_CMDID);
1626 		CASE_RETURN_STRING(WMI_PDEV_GET_ANI_OFDM_CONFIG_CMDID);
1627 		CASE_RETURN_STRING(WMI_VDEV_RATEMASK_CMDID);
1628 		CASE_RETURN_STRING(WMI_VDEV_ATF_REQUEST_CMDID);
1629 		CASE_RETURN_STRING(WMI_VDEV_SET_DSCP_TID_MAP_CMDID);
1630 		CASE_RETURN_STRING(WMI_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID);
1631 		CASE_RETURN_STRING(WMI_VDEV_SET_QUIET_MODE_CMDID);
1632 		CASE_RETURN_STRING(WMI_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID);
1633 		CASE_RETURN_STRING(WMI_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID);
1634 		CASE_RETURN_STRING(WMI_PEER_SMART_ANT_SET_NODE_CONFIG_OPS_CMDID);
1635 		CASE_RETURN_STRING(WMI_PEER_ATF_REQUEST_CMDID);
1636 		CASE_RETURN_STRING(WMI_FWTEST_CMDID);
1637 		CASE_RETURN_STRING(WMI_QBOOST_CFG_CMDID);
1638 		CASE_RETURN_STRING(WMI_PDEV_GET_NFCAL_POWER_CMDID);
1639 		CASE_RETURN_STRING(WMI_PDEV_SET_PCL_CMDID);
1640 		CASE_RETURN_STRING(WMI_PDEV_SET_HW_MODE_CMDID);
1641 		CASE_RETURN_STRING(WMI_PDEV_SET_MAC_CONFIG_CMDID);
1642 		CASE_RETURN_STRING(WMI_PDEV_SET_ANTENNA_MODE_CMDID);
1643 		CASE_RETURN_STRING(WMI_ROAM_SET_MBO_PARAM_CMDID);
1644 		CASE_RETURN_STRING(WMI_CHAN_AVOID_RPT_ALLOW_CMDID);
1645 		CASE_RETURN_STRING(WMI_SET_PERIODIC_CHANNEL_STATS_CONFIG_CMDID);
1646 		CASE_RETURN_STRING(WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID);
1647 		CASE_RETURN_STRING(WMI_PDEV_WAL_POWER_DEBUG_CMDID);
1648 		CASE_RETURN_STRING(WMI_PEER_BWF_REQUEST_CMDID);
1649 		CASE_RETURN_STRING(WMI_DBGLOG_TIME_STAMP_SYNC_CMDID);
1650 		CASE_RETURN_STRING(WMI_P2P_LISTEN_OFFLOAD_START_CMDID);
1651 		CASE_RETURN_STRING(WMI_P2P_LISTEN_OFFLOAD_STOP_CMDID);
1652 		CASE_RETURN_STRING(WMI_PEER_REORDER_QUEUE_SETUP_CMDID);
1653 		CASE_RETURN_STRING(WMI_PEER_REORDER_QUEUE_REMOVE_CMDID);
1654 		CASE_RETURN_STRING(WMI_SET_MULTIPLE_MCAST_FILTER_CMDID);
1655 		CASE_RETURN_STRING(WMI_READ_DATA_FROM_FLASH_CMDID);
1656 		CASE_RETURN_STRING(WMI_PDEV_SET_REORDER_TIMEOUT_VAL_CMDID);
1657 		CASE_RETURN_STRING(WMI_PEER_SET_RX_BLOCKSIZE_CMDID);
1658 		CASE_RETURN_STRING(WMI_PDEV_SET_WAKEUP_CONFIG_CMDID);
1659 		CASE_RETURN_STRING(WMI_PDEV_GET_ANTDIV_STATUS_CMDID);
1660 		CASE_RETURN_STRING(WMI_PEER_ANTDIV_INFO_REQ_CMDID);
1661 		CASE_RETURN_STRING(WMI_MNT_FILTER_CMDID);
1662 		CASE_RETURN_STRING(WMI_PDEV_GET_CHIP_POWER_STATS_CMDID);
1663 		CASE_RETURN_STRING(WMI_COEX_GET_ANTENNA_ISOLATION_CMDID);
1664 		CASE_RETURN_STRING(WMI_PDEV_SET_STATS_THRESHOLD_CMDID);
1665 		CASE_RETURN_STRING(WMI_REQUEST_WLAN_STATS_CMDID);
1666 		CASE_RETURN_STRING(WMI_VDEV_ENCRYPT_DECRYPT_DATA_REQ_CMDID);
1667 	}
1668 
1669 	return "Invalid WMI cmd";
1670 }
1671 
1672 static inline void wma_log_cmd_id(uint32_t cmd_id, uint32_t tag)
1673 {
1674 	WMI_LOGD("Send WMI command:%s command_id:%d htc_tag:%d\n",
1675 		 wmi_id_to_name(cmd_id), cmd_id, tag);
1676 }
1677 #else
1678 static uint8_t *wmi_id_to_name(uint32_t wmi_command)
1679 {
1680 	return "Invalid WMI cmd";
1681 }
1682 #endif
1683 
1684 
1685 /**
1686  * wmi_is_runtime_pm_cmd() - check if a cmd is from suspend resume sequence
1687  * @cmd: command to check
1688  *
1689  * Return: true if the command is part of the suspend resume sequence.
1690  */
1691 #ifdef CONFIG_MCL
1692 static bool wmi_is_runtime_pm_cmd(uint32_t cmd_id)
1693 {
1694 	switch (cmd_id) {
1695 	case WMI_WOW_ENABLE_CMDID:
1696 	case WMI_PDEV_SUSPEND_CMDID:
1697 	case WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID:
1698 	case WMI_WOW_ADD_WAKE_PATTERN_CMDID:
1699 	case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID:
1700 	case WMI_PDEV_RESUME_CMDID:
1701 	case WMI_WOW_DEL_WAKE_PATTERN_CMDID:
1702 	case WMI_D0_WOW_ENABLE_DISABLE_CMDID:
1703 		return true;
1704 
1705 	default:
1706 		return false;
1707 	}
1708 }
1709 
1710 /**
1711  * wmi_is_pm_resume_cmd() - check if a cmd is part of the resume sequence
1712  * @cmd_id: command to check
1713  *
1714  * Return: true if the command is part of the resume sequence.
1715  */
1716 static bool wmi_is_pm_resume_cmd(uint32_t cmd_id)
1717 {
1718 	switch (cmd_id) {
1719 	case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID:
1720 	case WMI_PDEV_RESUME_CMDID:
1721 		return true;
1722 
1723 	default:
1724 		return false;
1725 	}
1726 }
1727 #else
1728 static bool wmi_is_runtime_pm_cmd(uint32_t cmd_id)
1729 {
1730 	return false;
1731 }
1732 static bool wmi_is_pm_resume_cmd(uint32_t cmd_id)
1733 {
1734 	return false;
1735 }
1736 #endif
1737 
1738 /**
1739  * wmi_unified_cmd_send() - WMI command API
1740  * @wmi_handle: handle to wmi
1741  * @buf: wmi buf
1742  * @len: wmi buffer length
1743  * @cmd_id: wmi command id
1744  *
1745  * Note, it is NOT safe to access buf after calling this function!
1746  *
1747  * Return: 0 on success
1748  */
1749 QDF_STATUS wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf,
1750 				uint32_t len, uint32_t cmd_id)
1751 {
1752 	HTC_PACKET *pkt;
1753 	A_STATUS status;
1754 	uint16_t htc_tag = 0;
1755 
1756 	if (wmi_get_runtime_pm_inprogress(wmi_handle)) {
1757 		if (wmi_is_runtime_pm_cmd(cmd_id))
1758 			htc_tag = HTC_TX_PACKET_TAG_AUTO_PM;
1759 	} else if (qdf_atomic_read(&wmi_handle->is_target_suspended) &&
1760 		(!wmi_is_pm_resume_cmd(cmd_id))) {
1761 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1762 				  "%s: Target is suspended", __func__);
1763 		QDF_ASSERT(0);
1764 		return QDF_STATUS_E_BUSY;
1765 	}
1766 	if (wmi_handle->wmi_stopinprogress) {
1767 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1768 			"WMI  stop in progress\n");
1769 		return QDF_STATUS_E_INVAL;
1770 	}
1771 
1772 #ifndef WMI_NON_TLV_SUPPORT
1773 	/* Do sanity check on the TLV parameter structure */
1774 	if (wmi_handle->target_type == WMI_TLV_TARGET) {
1775 		void *buf_ptr = (void *)qdf_nbuf_data(buf);
1776 
1777 		if (wmitlv_check_command_tlv_params(NULL, buf_ptr, len, cmd_id)
1778 			!= 0) {
1779 			QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1780 			"\nERROR: %s: Invalid WMI Param Buffer for Cmd:%d",
1781 				__func__, cmd_id);
1782 			return QDF_STATUS_E_INVAL;
1783 		}
1784 	}
1785 #endif
1786 
1787 	if (qdf_nbuf_push_head(buf, sizeof(WMI_CMD_HDR)) == NULL) {
1788 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1789 			 "%s, Failed to send cmd %x, no memory",
1790 			 __func__, cmd_id);
1791 		return QDF_STATUS_E_NOMEM;
1792 	}
1793 
1794 	WMI_SET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id);
1795 
1796 	qdf_atomic_inc(&wmi_handle->pending_cmds);
1797 	if (qdf_atomic_read(&wmi_handle->pending_cmds) >= WMI_MAX_CMDS) {
1798 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1799 		    "\n%s: hostcredits = %d", __func__,
1800 		wmi_get_host_credits(wmi_handle));
1801 		htc_dump_counter_info(wmi_handle->htc_handle);
1802 		qdf_atomic_dec(&wmi_handle->pending_cmds);
1803 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1804 			"%s: MAX %d WMI Pending cmds reached.", __func__,
1805 			WMI_MAX_CMDS);
1806 		QDF_BUG(0);
1807 		return QDF_STATUS_E_BUSY;
1808 	}
1809 
1810 	pkt = qdf_mem_malloc(sizeof(*pkt));
1811 	if (!pkt) {
1812 		qdf_atomic_dec(&wmi_handle->pending_cmds);
1813 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1814 			 "%s, Failed to alloc htc packet %x, no memory",
1815 			 __func__, cmd_id);
1816 		return QDF_STATUS_E_NOMEM;
1817 	}
1818 
1819 	SET_HTC_PACKET_INFO_TX(pkt,
1820 			       NULL,
1821 			       qdf_nbuf_data(buf), len + sizeof(WMI_CMD_HDR),
1822 			       wmi_handle->wmi_endpoint_id, htc_tag);
1823 
1824 	SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf);
1825 #ifdef CONFIG_MCL
1826 	wma_log_cmd_id(cmd_id, htc_tag);
1827 #endif
1828 
1829 #ifdef WMI_INTERFACE_EVENT_LOGGING
1830 	if (wmi_handle->log_info.wmi_logging_enable) {
1831 		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
1832 		/*Record 16 bytes of WMI cmd data -
1833 		 * * exclude TLV and WMI headers */
1834 		if (wmi_handle->log_info.is_management_record(cmd_id)) {
1835 			WMI_MGMT_COMMAND_RECORD(wmi_handle, cmd_id,
1836 				((uint32_t *) qdf_nbuf_data(buf) +
1837 				 wmi_handle->log_info.buf_offset_command));
1838 		} else {
1839 			WMI_COMMAND_RECORD(wmi_handle, cmd_id,
1840 			((uint32_t *) qdf_nbuf_data(buf) +
1841 			 wmi_handle->log_info.buf_offset_command));
1842 		}
1843 		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
1844 	}
1845 #endif
1846 
1847 	status = htc_send_pkt(wmi_handle->htc_handle, pkt);
1848 
1849 	if (A_OK != status) {
1850 		qdf_atomic_dec(&wmi_handle->pending_cmds);
1851 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
1852 		   "%s %d, htc_send_pkt failed", __func__, __LINE__);
1853 		qdf_mem_free(pkt);
1854 
1855 	}
1856 	if (status)
1857 		return QDF_STATUS_E_FAILURE;
1858 
1859 	return QDF_STATUS_SUCCESS;
1860 }
1861 
1862 /**
1863  * wmi_unified_get_event_handler_ix() - gives event handler's index
1864  * @wmi_handle: handle to wmi
1865  * @event_id: wmi  event id
1866  *
1867  * Return: event handler's index
1868  */
1869 static int wmi_unified_get_event_handler_ix(wmi_unified_t wmi_handle,
1870 					    uint32_t event_id)
1871 {
1872 	uint32_t idx = 0;
1873 	int32_t invalid_idx = -1;
1874 
1875 	for (idx = 0; (idx < wmi_handle->max_event_idx &&
1876 		       idx < WMI_UNIFIED_MAX_EVENT); ++idx) {
1877 		if (wmi_handle->event_id[idx] == event_id &&
1878 		    wmi_handle->event_handler[idx] != NULL) {
1879 			return idx;
1880 		}
1881 	}
1882 
1883 	return invalid_idx;
1884 }
1885 
1886 /**
1887  * wmi_unified_register_event_handler() - register wmi event handler
1888  * @wmi_handle: handle to wmi
1889  * @event_id: wmi event id
1890  * @handler_func: wmi event handler function
1891  * @rx_ctx: rx execution context for wmi rx events
1892  *
1893  * Return: 0 on success
1894  */
1895 int wmi_unified_register_event_handler(wmi_unified_t wmi_handle,
1896 				       uint32_t event_id,
1897 				       wmi_unified_event_handler handler_func,
1898 				       uint8_t rx_ctx)
1899 {
1900 	uint32_t idx = 0;
1901 	uint32_t evt_id;
1902 
1903 #ifndef CONFIG_MCL
1904 	if (event_id >= wmi_events_max ||
1905 		wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) {
1906 		qdf_print("%s: Event id %d is unavailable\n",
1907 				 __func__, event_id);
1908 		return QDF_STATUS_E_FAILURE;
1909 	}
1910 	evt_id = wmi_handle->wmi_events[event_id];
1911 #else
1912 	evt_id = event_id;
1913 #endif
1914 	if (wmi_unified_get_event_handler_ix(wmi_handle, evt_id) != -1) {
1915 		qdf_print("%s : event handler already registered 0x%x\n",
1916 		       __func__, evt_id);
1917 		return QDF_STATUS_E_FAILURE;
1918 	}
1919 	if (wmi_handle->max_event_idx == WMI_UNIFIED_MAX_EVENT) {
1920 		qdf_print("%s : no more event handlers 0x%x\n",
1921 		       __func__, evt_id);
1922 		return QDF_STATUS_E_FAILURE;
1923 	}
1924 	idx = wmi_handle->max_event_idx;
1925 	wmi_handle->event_handler[idx] = handler_func;
1926 	wmi_handle->event_id[idx] = evt_id;
1927 	qdf_spin_lock_bh(&wmi_handle->ctx_lock);
1928 	wmi_handle->ctx[idx] = rx_ctx;
1929 	qdf_spin_unlock_bh(&wmi_handle->ctx_lock);
1930 	wmi_handle->max_event_idx++;
1931 
1932 	return 0;
1933 }
1934 
1935 /**
1936  * wmi_unified_unregister_event_handler() - unregister wmi event handler
1937  * @wmi_handle: handle to wmi
1938  * @event_id: wmi event id
1939  *
1940  * Return: 0 on success
1941  */
1942 int wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle,
1943 					 uint32_t event_id)
1944 {
1945 	uint32_t idx = 0;
1946 	uint32_t evt_id;
1947 
1948 #ifndef CONFIG_MCL
1949 	if (event_id >= wmi_events_max ||
1950 		wmi_handle->wmi_events[event_id] == WMI_EVENT_ID_INVALID) {
1951 		qdf_print("%s: Event id %d is unavailable\n",
1952 				 __func__, event_id);
1953 		return QDF_STATUS_E_FAILURE;
1954 	}
1955 	evt_id = wmi_handle->wmi_events[event_id];
1956 #else
1957 	evt_id = event_id;
1958 #endif
1959 
1960 	idx = wmi_unified_get_event_handler_ix(wmi_handle, evt_id);
1961 	if (idx == -1) {
1962 		qdf_print("%s : event handler is not registered: evt id 0x%x\n",
1963 		       __func__, evt_id);
1964 		return QDF_STATUS_E_FAILURE;
1965 	}
1966 	wmi_handle->event_handler[idx] = NULL;
1967 	wmi_handle->event_id[idx] = 0;
1968 	--wmi_handle->max_event_idx;
1969 	wmi_handle->event_handler[idx] =
1970 		wmi_handle->event_handler[wmi_handle->max_event_idx];
1971 	wmi_handle->event_id[idx] =
1972 		wmi_handle->event_id[wmi_handle->max_event_idx];
1973 
1974 	return 0;
1975 }
1976 
1977 /**
1978  * wmi_process_fw_event_default_ctx() - process in default caller context
1979  * @wmi_handle: handle to wmi
1980  * @htc_packet: pointer to htc packet
1981  * @exec_ctx: execution context for wmi fw event
1982  *
1983  * Event process by below function will be in default caller context.
1984  * wmi internally provides rx work thread processing context.
1985  *
1986  * Return: none
1987  */
1988 static void wmi_process_fw_event_default_ctx(struct wmi_unified *wmi_handle,
1989 		       HTC_PACKET *htc_packet, uint8_t exec_ctx)
1990 {
1991 	wmi_buf_t evt_buf;
1992 	evt_buf = (wmi_buf_t) htc_packet->pPktContext;
1993 
1994 #ifndef CONFIG_MCL
1995 	wmi_handle->rx_ops.wma_process_fw_event_handler_cbk
1996 		(wmi_handle->scn_handle, evt_buf, exec_ctx);
1997 #else
1998 	wmi_handle->rx_ops.wma_process_fw_event_handler_cbk(wmi_handle,
1999 					 evt_buf, exec_ctx);
2000 #endif
2001 
2002 	return;
2003 }
2004 
2005 /**
2006  * wmi_process_fw_event_worker_thread_ctx() - process in worker thread context
2007  * @wmi_handle: handle to wmi
2008  * @htc_packet: pointer to htc packet
2009  *
2010  * Event process by below function will be in worker thread context.
2011  * Use this method for events which are not critical and not
2012  * handled in protocol stack.
2013  *
2014  * Return: none
2015  */
2016 static void wmi_process_fw_event_worker_thread_ctx
2017 		(struct wmi_unified *wmi_handle, HTC_PACKET *htc_packet)
2018 {
2019 	wmi_buf_t evt_buf;
2020 	uint32_t id;
2021 	uint8_t *data;
2022 
2023 	evt_buf = (wmi_buf_t) htc_packet->pPktContext;
2024 	id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
2025 	data = qdf_nbuf_data(evt_buf);
2026 
2027 #ifdef WMI_INTERFACE_EVENT_LOGGING
2028 	if (wmi_handle->log_info.wmi_logging_enable) {
2029 		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
2030 		/* Exclude 4 bytes of TLV header */
2031 		WMI_RX_EVENT_RECORD(wmi_handle, id, ((uint8_t *) data +
2032 				wmi_handle->log_info.buf_offset_event));
2033 		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
2034 	}
2035 #endif
2036 	qdf_spin_lock_bh(&wmi_handle->eventq_lock);
2037 	qdf_nbuf_queue_add(&wmi_handle->event_queue, evt_buf);
2038 	qdf_spin_unlock_bh(&wmi_handle->eventq_lock);
2039 	schedule_work(&wmi_handle->rx_event_work);
2040 	return;
2041 }
2042 
2043 /**
2044  * wmi_control_rx() - process fw events callbacks
2045  * @ctx: handle to wmi
2046  * @htc_packet: pointer to htc packet
2047  *
2048  * Return: none
2049  */
2050 static void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet)
2051 {
2052 	struct wmi_unified *wmi_handle = (struct wmi_unified *)ctx;
2053 	wmi_buf_t evt_buf;
2054 	uint32_t id;
2055 	uint32_t idx = 0;
2056 	enum wmi_rx_exec_ctx exec_ctx;
2057 
2058 	evt_buf = (wmi_buf_t) htc_packet->pPktContext;
2059 	id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
2060 	idx = wmi_unified_get_event_handler_ix(wmi_handle, id);
2061 	if (qdf_unlikely(idx == A_ERROR)) {
2062 		qdf_print
2063 		("%s :event handler is not registered: event id 0x%x\n",
2064 			__func__, id);
2065 		qdf_nbuf_free(evt_buf);
2066 		return;
2067 	}
2068 	qdf_spin_lock_bh(&wmi_handle->ctx_lock);
2069 	exec_ctx = wmi_handle->ctx[idx];
2070 	qdf_spin_unlock_bh(&wmi_handle->ctx_lock);
2071 
2072 	if (exec_ctx == WMI_RX_WORK_CTX) {
2073 		wmi_process_fw_event_worker_thread_ctx
2074 					(wmi_handle, htc_packet);
2075 	} else if (exec_ctx > WMI_RX_WORK_CTX) {
2076 		wmi_process_fw_event_default_ctx
2077 					(wmi_handle, htc_packet, exec_ctx);
2078 	} else {
2079 		qdf_print("%s :Invalid event context %d\n", __func__, exec_ctx);
2080 		qdf_nbuf_free(evt_buf);
2081 	}
2082 
2083 }
2084 
2085 /**
2086  * wmi_process_fw_event() - process any fw event
2087  * @wmi_handle: wmi handle
2088  * @evt_buf: fw event buffer
2089  *
2090  * This function process fw event in caller context
2091  *
2092  * Return: none
2093  */
2094 void wmi_process_fw_event(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf)
2095 {
2096 	__wmi_control_rx(wmi_handle, evt_buf);
2097 }
2098 
2099 /**
2100  * __wmi_control_rx() - process serialize wmi event callback
2101  * @wmi_handle: wmi handle
2102  * @evt_buf: fw event buffer
2103  *
2104  * Return: none
2105  */
2106 void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf)
2107 {
2108 	uint32_t id;
2109 	uint8_t *data;
2110 	uint32_t len;
2111 	void *wmi_cmd_struct_ptr = NULL;
2112 #ifndef WMI_NON_TLV_SUPPORT
2113 	int tlv_ok_status = 0;
2114 #endif
2115 	uint32_t idx = 0;
2116 
2117 	id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
2118 
2119 	if (qdf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
2120 		goto end;
2121 
2122 	data = qdf_nbuf_data(evt_buf);
2123 	len = qdf_nbuf_len(evt_buf);
2124 
2125 #ifndef WMI_NON_TLV_SUPPORT
2126 	if (wmi_handle->target_type == WMI_TLV_TARGET) {
2127 		/* Validate and pad(if necessary) the TLVs */
2128 		tlv_ok_status =
2129 			wmitlv_check_and_pad_event_tlvs(wmi_handle->scn_handle,
2130 							data, len, id,
2131 							&wmi_cmd_struct_ptr);
2132 		if (tlv_ok_status != 0) {
2133 			QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
2134 				"%s: Error: id=0x%d, wmitlv check status=%d\n",
2135 				__func__, id, tlv_ok_status);
2136 			goto end;
2137 		}
2138 	}
2139 #endif
2140 
2141 	idx = wmi_unified_get_event_handler_ix(wmi_handle, id);
2142 	if (idx == A_ERROR) {
2143 		QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_ERROR,
2144 		   "%s : event handler is not registered: event id 0x%x\n",
2145 			__func__, id);
2146 		goto end;
2147 	}
2148 #ifdef WMI_INTERFACE_EVENT_LOGGING
2149 	if (wmi_handle->log_info.wmi_logging_enable) {
2150 		qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
2151 		/* Exclude 4 bytes of TLV header */
2152 		if (wmi_handle->log_info.is_management_record(id)) {
2153 			WMI_MGMT_EVENT_RECORD(wmi_handle, id, ((uint8_t *) data
2154 				+ wmi_handle->log_info.buf_offset_event));
2155 		} else {
2156 			WMI_EVENT_RECORD(wmi_handle, id, ((uint8_t *) data +
2157 					wmi_handle->log_info.buf_offset_event));
2158 		}
2159 		qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
2160 	}
2161 #endif
2162 	/* Call the WMI registered event handler */
2163 	if (wmi_handle->target_type == WMI_TLV_TARGET)
2164 		wmi_handle->event_handler[idx] (wmi_handle->scn_handle,
2165 			wmi_cmd_struct_ptr, len);
2166 	else
2167 		wmi_handle->event_handler[idx] (wmi_handle->scn_handle,
2168 			data, len);
2169 
2170 end:
2171 	/* Free event buffer and allocated event tlv */
2172 #ifndef WMI_NON_TLV_SUPPORT
2173 	if (wmi_handle->target_type == WMI_TLV_TARGET)
2174 		wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr);
2175 #endif
2176 
2177 	qdf_nbuf_free(evt_buf);
2178 
2179 }
2180 
2181 /**
2182  * wmi_rx_event_work() - process rx event in rx work queue context
2183  * @work: rx work queue struct
2184  *
2185  * This function process any fw event to serialize it through rx worker thread.
2186  *
2187  * Return: none
2188  */
2189 static void wmi_rx_event_work(struct work_struct *work)
2190 {
2191 	struct wmi_unified *wmi = container_of(work, struct wmi_unified,
2192 					rx_event_work);
2193 	wmi_buf_t buf;
2194 
2195 	qdf_spin_lock_bh(&wmi->eventq_lock);
2196 	buf = qdf_nbuf_queue_remove(&wmi->event_queue);
2197 	qdf_spin_unlock_bh(&wmi->eventq_lock);
2198 	while (buf) {
2199 		__wmi_control_rx(wmi, buf);
2200 		qdf_spin_lock_bh(&wmi->eventq_lock);
2201 		buf = qdf_nbuf_queue_remove(&wmi->event_queue);
2202 		qdf_spin_unlock_bh(&wmi->eventq_lock);
2203 	}
2204 }
2205 
2206 #ifdef FEATURE_RUNTIME_PM
2207 /**
2208  * wmi_runtime_pm_init() - initialize runtime pm wmi variables
2209  * @wmi_handle: wmi context
2210  */
2211 static void wmi_runtime_pm_init(struct wmi_unified *wmi_handle)
2212 {
2213 	qdf_atomic_init(&wmi_handle->runtime_pm_inprogress);
2214 }
2215 
2216 /**
2217  * wmi_set_runtime_pm_inprogress() - set runtime pm progress flag
2218  * @wmi_handle: wmi context
2219  * @val: runtime pm progress flag
2220  */
2221 void wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, A_BOOL val)
2222 {
2223 	qdf_atomic_set(&wmi_handle->runtime_pm_inprogress, val);
2224 }
2225 
2226 /**
2227  * wmi_get_runtime_pm_inprogress() - get runtime pm progress flag
2228  * @wmi_handle: wmi context
2229  */
2230 inline bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle)
2231 {
2232 	return qdf_atomic_read(&wmi_handle->runtime_pm_inprogress);
2233 }
2234 #else
2235 static void wmi_runtime_pm_init(struct wmi_unified *wmi_handle)
2236 {
2237 }
2238 #endif
2239 
2240 /**
2241  * wmi_unified_attach() -  attach for unified WMI
2242  * @scn_handle: handle to SCN
2243  * @osdev: OS device context
2244  * @target_type: TLV or not-TLV based target
2245  * @use_cookie: cookie based allocation enabled/disabled
2246  * @ops: umac rx callbacks
2247  *
2248  * @Return: wmi handle.
2249  */
2250 void *wmi_unified_attach(void *scn_handle,
2251 			 osdev_t osdev, enum wmi_target_type target_type,
2252 			 bool use_cookie, struct wmi_rx_ops *rx_ops)
2253 {
2254 	struct wmi_unified *wmi_handle;
2255 
2256 #ifdef CONFIG_MCL
2257 	wmi_handle =
2258 		(struct wmi_unified *)os_malloc(NULL,
2259 				sizeof(struct wmi_unified),
2260 				GFP_ATOMIC);
2261 #else
2262 	wmi_handle =
2263 		(struct wmi_unified *) qdf_mem_malloc(
2264 			sizeof(struct wmi_unified));
2265 #endif
2266 	if (wmi_handle == NULL) {
2267 		qdf_print("allocation of wmi handle failed %zu\n",
2268 			sizeof(struct wmi_unified));
2269 		return NULL;
2270 	}
2271 	OS_MEMZERO(wmi_handle, sizeof(struct wmi_unified));
2272 	wmi_handle->scn_handle = scn_handle;
2273 	qdf_atomic_init(&wmi_handle->pending_cmds);
2274 	qdf_atomic_init(&wmi_handle->is_target_suspended);
2275 	wmi_runtime_pm_init(wmi_handle);
2276 	qdf_spinlock_create(&wmi_handle->eventq_lock);
2277 	qdf_nbuf_queue_init(&wmi_handle->event_queue);
2278 	INIT_WORK(&wmi_handle->rx_event_work, wmi_rx_event_work);
2279 #ifdef WMI_INTERFACE_EVENT_LOGGING
2280 	if (QDF_STATUS_SUCCESS == wmi_log_init(wmi_handle)) {
2281 		qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock);
2282 		wmi_debugfs_init(wmi_handle);
2283 	}
2284 #endif
2285 	/* Attach mc_thread context processing function */
2286 	wmi_handle->rx_ops.wma_process_fw_event_handler_cbk =
2287 				rx_ops->wma_process_fw_event_handler_cbk;
2288 	wmi_handle->target_type = target_type;
2289 	if (target_type == WMI_TLV_TARGET)
2290 		wmi_tlv_attach(wmi_handle);
2291 	else
2292 		wmi_non_tlv_attach(wmi_handle);
2293 	/* Assign target cookie capablity */
2294 	wmi_handle->use_cookie = use_cookie;
2295 	wmi_handle->osdev = osdev;
2296 	wmi_handle->wmi_stopinprogress = 0;
2297 	qdf_spinlock_create(&wmi_handle->ctx_lock);
2298 
2299 	return wmi_handle;
2300 }
2301 
2302 /**
2303  * wmi_unified_detach() -  detach for unified WMI
2304  *
2305  * @wmi_handle  : handle to wmi.
2306  *
2307  * @Return: none.
2308  */
2309 void wmi_unified_detach(struct wmi_unified *wmi_handle)
2310 {
2311 	wmi_buf_t buf;
2312 
2313 	cancel_work_sync(&wmi_handle->rx_event_work);
2314 
2315 	wmi_debugfs_remove(wmi_handle);
2316 
2317 	buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue);
2318 	while (buf) {
2319 		qdf_nbuf_free(buf);
2320 		buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue);
2321 	}
2322 
2323 #ifdef WMI_INTERFACE_EVENT_LOGGING
2324 	wmi_log_buffer_free(wmi_handle);
2325 #endif
2326 
2327 	qdf_spinlock_destroy(&wmi_handle->eventq_lock);
2328 	qdf_spinlock_destroy(&wmi_handle->ctx_lock);
2329 	OS_FREE(wmi_handle);
2330 	wmi_handle = NULL;
2331 }
2332 
2333 /**
2334  * wmi_unified_remove_work() - detach for WMI work
2335  * @wmi_handle: handle to WMI
2336  *
2337  * A function that does not fully detach WMI, but just remove work
2338  * queue items associated with it. This is used to make sure that
2339  * before any other processing code that may destroy related contexts
2340  * (HTC, etc), work queue processing on WMI has already been stopped.
2341  *
2342  * Return: None
2343  */
2344 void
2345 wmi_unified_remove_work(struct wmi_unified *wmi_handle)
2346 {
2347 	wmi_buf_t buf;
2348 
2349 	QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO,
2350 		"Enter: %s", __func__);
2351 	cancel_work_sync(&wmi_handle->rx_event_work);
2352 	qdf_spin_lock_bh(&wmi_handle->eventq_lock);
2353 	buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue);
2354 	while (buf) {
2355 		qdf_nbuf_free(buf);
2356 		buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue);
2357 	}
2358 	qdf_spin_unlock_bh(&wmi_handle->eventq_lock);
2359 	QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO,
2360 		"Done: %s", __func__);
2361 }
2362 
2363 /**
2364  * wmi_htc_tx_complete() - Process htc tx completion
2365  *
2366  * @ctx: handle to wmi
2367  * @htc_packet: pointer to htc packet
2368  *
2369  * @Return: none.
2370  */
2371 static void wmi_htc_tx_complete(void *ctx, HTC_PACKET *htc_pkt)
2372 {
2373 	struct wmi_unified *wmi_handle = (struct wmi_unified *)ctx;
2374 	wmi_buf_t wmi_cmd_buf = GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt);
2375 	u_int8_t *buf_ptr;
2376 	u_int32_t len;
2377 #ifdef WMI_INTERFACE_EVENT_LOGGING
2378 	uint32_t cmd_id;
2379 #endif
2380 
2381 	ASSERT(wmi_cmd_buf);
2382 #ifdef WMI_INTERFACE_EVENT_LOGGING
2383 	if (wmi_handle->log_info.wmi_logging_enable) {
2384 		cmd_id = WMI_GET_FIELD(qdf_nbuf_data(wmi_cmd_buf),
2385 				WMI_CMD_HDR, COMMANDID);
2386 
2387 	qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
2388 	/* Record 16 bytes of WMI cmd tx complete data
2389 	- exclude TLV and WMI headers */
2390 	if (wmi_handle->log_info.is_management_record(cmd_id)) {
2391 		WMI_MGMT_COMMAND_TX_CMP_RECORD(wmi_handle, cmd_id,
2392 			((uint32_t *) qdf_nbuf_data(wmi_cmd_buf) +
2393 			wmi_handle->log_info.buf_offset_command));
2394 	} else {
2395 		WMI_COMMAND_TX_CMP_RECORD(wmi_handle, cmd_id,
2396 			((uint32_t *) qdf_nbuf_data(wmi_cmd_buf) +
2397 			wmi_handle->log_info.buf_offset_command));
2398 	}
2399 
2400 	qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
2401 	}
2402 #endif
2403 	buf_ptr = (u_int8_t *) wmi_buf_data(wmi_cmd_buf);
2404 	len = qdf_nbuf_len(wmi_cmd_buf);
2405 	qdf_mem_zero(buf_ptr, len);
2406 	qdf_nbuf_free(wmi_cmd_buf);
2407 	qdf_mem_free(htc_pkt);
2408 	qdf_atomic_dec(&wmi_handle->pending_cmds);
2409 }
2410 
2411 /**
2412  * wmi_get_host_credits() -  WMI API to get updated host_credits
2413  *
2414  * @wmi_handle: handle to WMI.
2415  *
2416  * @Return: updated host_credits.
2417  */
2418 int
2419 wmi_unified_connect_htc_service(struct wmi_unified *wmi_handle,
2420 				void *htc_handle)
2421 {
2422 
2423 	int status;
2424 	HTC_SERVICE_CONNECT_RESP response;
2425 	HTC_SERVICE_CONNECT_REQ connect;
2426 
2427 	OS_MEMZERO(&connect, sizeof(connect));
2428 	OS_MEMZERO(&response, sizeof(response));
2429 
2430 	/* meta data is unused for now */
2431 	connect.pMetaData = NULL;
2432 	connect.MetaDataLength = 0;
2433 	/* these fields are the same for all service endpoints */
2434 	connect.EpCallbacks.pContext = wmi_handle;
2435 	connect.EpCallbacks.EpTxCompleteMultiple =
2436 		NULL /* Control path completion ar6000_tx_complete */;
2437 	connect.EpCallbacks.EpRecv = wmi_control_rx /* Control path rx */;
2438 	connect.EpCallbacks.EpRecvRefill = NULL /* ar6000_rx_refill */;
2439 	connect.EpCallbacks.EpSendFull = NULL /* ar6000_tx_queue_full */;
2440 	connect.EpCallbacks.EpTxComplete =
2441 		wmi_htc_tx_complete /* ar6000_tx_queue_full */;
2442 
2443 	/* connect to control service */
2444 	connect.service_id = WMI_CONTROL_SVC;
2445 	status = htc_connect_service(htc_handle, &connect,
2446 				&response);
2447 
2448 	if (status != EOK) {
2449 		qdf_print
2450 			("Failed to connect to WMI CONTROL service status:%d \n",
2451 			status);
2452 		return status;
2453 	}
2454 	wmi_handle->wmi_endpoint_id = response.Endpoint;
2455 	wmi_handle->htc_handle = htc_handle;
2456 	wmi_handle->max_msg_len = response.MaxMsgLength;
2457 
2458 	return EOK;
2459 }
2460 
2461 /**
2462  * wmi_get_host_credits() -  WMI API to get updated host_credits
2463  *
2464  * @wmi_handle: handle to WMI.
2465  *
2466  * @Return: updated host_credits.
2467  */
2468 int wmi_get_host_credits(wmi_unified_t wmi_handle)
2469 {
2470 	int host_credits = 0;
2471 
2472 	htc_get_control_endpoint_tx_host_credits(wmi_handle->htc_handle,
2473 						 &host_credits);
2474 	return host_credits;
2475 }
2476 
2477 /**
2478  * wmi_get_pending_cmds() - WMI API to get WMI Pending Commands in the HTC
2479  *                          queue
2480  *
2481  * @wmi_handle: handle to WMI.
2482  *
2483  * @Return: Pending Commands in the HTC queue.
2484  */
2485 int wmi_get_pending_cmds(wmi_unified_t wmi_handle)
2486 {
2487 	return qdf_atomic_read(&wmi_handle->pending_cmds);
2488 }
2489 
2490 /**
2491  * wmi_set_target_suspend() -  WMI API to set target suspend state
2492  *
2493  * @wmi_handle: handle to WMI.
2494  * @val: suspend state boolean.
2495  *
2496  * @Return: none.
2497  */
2498 void wmi_set_target_suspend(wmi_unified_t wmi_handle, A_BOOL val)
2499 {
2500 	qdf_atomic_set(&wmi_handle->is_target_suspended, val);
2501 }
2502 
2503 #ifndef CONFIG_MCL
2504 /**
2505  * API to flush all the previous packets  associated with the wmi endpoint
2506  *
2507  * @param wmi_handle      : handle to WMI.
2508  */
2509 void
2510 wmi_flush_endpoint(wmi_unified_t wmi_handle)
2511 {
2512 	htc_flush_endpoint(wmi_handle->htc_handle,
2513 		wmi_handle->wmi_endpoint_id, 0);
2514 }
2515 
2516 /**
2517  * generic function to block unified WMI command
2518  * @param wmi_handle      : handle to WMI.
2519  * @return 0  on success and -ve on failure.
2520  */
2521 int
2522 wmi_stop(wmi_unified_t wmi_handle)
2523 {
2524 	QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO,
2525 			"WMI Stop\n");
2526 	wmi_handle->wmi_stopinprogress = 1;
2527 	return 0;
2528 }
2529 #endif
2530