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