xref: /wlan-dirver/qca-wifi-host-cmn/ipa/core/src/wlan_ipa_stats.c (revision c7eaf5ac989ac229214b8317faa3e981d261e7db)
1 /*
2  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 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 /* Include Files */
21 #include "wlan_ipa_main.h"
22 #include "wlan_ipa_core.h"
23 #include "cdp_txrx_ipa.h"
24 #include "qdf_platform.h"
25 
26 #ifdef IPA_OFFLOAD
27 /**
28  * wlan_ipa_uc_rt_debug_host_fill - fill rt debug buffer
29  * @ctext: pointer to ipa context.
30  *
31  * If rt debug enabled, periodically called, and fill debug buffer
32  *
33  * Return: none
34  */
35 static void wlan_ipa_uc_rt_debug_host_fill(void *ctext)
36 {
37 	struct wlan_ipa_priv *ipa_ctx = ctext;
38 	struct uc_rt_debug_info *dump_info = NULL;
39 
40 	if (!ipa_ctx)
41 		return;
42 
43 	qdf_mutex_acquire(&ipa_ctx->rt_debug_lock);
44 	dump_info = &ipa_ctx->rt_bug_buffer[
45 		ipa_ctx->rt_buf_fill_index % WLAN_IPA_UC_RT_DEBUG_BUF_COUNT];
46 
47 	dump_info->time = (uint64_t)qdf_mc_timer_get_system_time();
48 	dump_info->ipa_excep_count = ipa_ctx->stats.num_rx_excep;
49 	dump_info->rx_drop_count = ipa_ctx->ipa_rx_internal_drop_count;
50 	dump_info->net_sent_count = ipa_ctx->ipa_rx_net_send_count;
51 	dump_info->tx_fwd_count = ipa_ctx->ipa_tx_forward;
52 	dump_info->tx_fwd_ok_count = ipa_ctx->stats.num_tx_fwd_ok;
53 	dump_info->rx_discard_count = ipa_ctx->ipa_rx_discard;
54 	dump_info->rx_destructor_call = ipa_ctx->ipa_rx_destructor_count;
55 	ipa_ctx->rt_buf_fill_index++;
56 	qdf_mutex_release(&ipa_ctx->rt_debug_lock);
57 
58 	qdf_mc_timer_start(&ipa_ctx->rt_debug_fill_timer,
59 		WLAN_IPA_UC_RT_DEBUG_FILL_INTERVAL);
60 }
61 
62 void wlan_ipa_uc_rt_debug_host_dump(struct wlan_ipa_priv *ipa_ctx)
63 {
64 	unsigned int dump_count;
65 	unsigned int dump_index;
66 	struct uc_rt_debug_info *dump_info = NULL;
67 
68 	if (!wlan_ipa_is_rt_debugging_enabled(ipa_ctx->config)) {
69 		ipa_debug("IPA RT debug is not enabled");
70 		return;
71 	}
72 
73 	ipa_info("========= WLAN-IPA DEBUG BUF DUMP ==========\n");
74 	ipa_info("     TM     :   EXEP   :   DROP   :   NETS   :   FWOK"
75 		 ":   TXFD   :   DSTR   :   DSCD\n");
76 
77 	qdf_mutex_acquire(&ipa_ctx->rt_debug_lock);
78 	for (dump_count = 0;
79 		dump_count < WLAN_IPA_UC_RT_DEBUG_BUF_COUNT;
80 		dump_count++) {
81 		dump_index = (ipa_ctx->rt_buf_fill_index + dump_count) %
82 			WLAN_IPA_UC_RT_DEBUG_BUF_COUNT;
83 		dump_info = &ipa_ctx->rt_bug_buffer[dump_index];
84 		ipa_info("%12llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu\n",
85 			dump_info->time, dump_info->ipa_excep_count,
86 			dump_info->rx_drop_count, dump_info->net_sent_count,
87 			dump_info->tx_fwd_ok_count, dump_info->tx_fwd_count,
88 			dump_info->rx_destructor_call,
89 			dump_info->rx_discard_count);
90 	}
91 	qdf_mutex_release(&ipa_ctx->rt_debug_lock);
92 }
93 
94 /**
95  * wlan_ipa_uc_rt_debug_handler - periodic memory health monitor handler
96  * @ctext: pointer to ipa context.
97  *
98  * periodically called by timer expire
99  * will try to alloc dummy memory and detect out of memory condition
100  * if out of memory detected, dump wlan-ipa stats
101  *
102  * Return: none
103  */
104 static void wlan_ipa_uc_rt_debug_handler(void *ctext)
105 {
106 	struct wlan_ipa_priv *ipa_ctx = ctext;
107 	void *dummy_ptr = NULL;
108 
109 	if (!wlan_ipa_is_rt_debugging_enabled(ipa_ctx->config)) {
110 		ipa_debug("IPA RT debug is not enabled");
111 		return;
112 	}
113 
114 	/* Allocate dummy buffer periodically and free immediately. this will
115 	 * proactively detect OOM and if allocation fails dump ipa stats
116 	 */
117 	dummy_ptr = qdf_mem_malloc(WLAN_IPA_UC_DEBUG_DUMMY_MEM_SIZE);
118 	if (!dummy_ptr) {
119 		wlan_ipa_uc_rt_debug_host_dump(ipa_ctx);
120 		wlan_ipa_uc_stat_request(ipa_ctx,
121 					 WLAN_IPA_UC_STAT_REASON_DEBUG);
122 	} else {
123 		qdf_mem_free(dummy_ptr);
124 	}
125 
126 	qdf_mc_timer_start(&ipa_ctx->rt_debug_timer,
127 		WLAN_IPA_UC_RT_DEBUG_PERIOD);
128 }
129 
130 void wlan_ipa_uc_rt_debug_destructor(qdf_nbuf_t nbuff)
131 {
132 	/* Make change to get the ipa_ctx on per pdev basis
133 	 * Currently storing the debug count only in global ipa_ctx
134 	 * or to the last enumerated radio ipa_ctx
135 	 */
136 	struct wlan_ipa_priv *ipa_ctx = wlan_ipa_get_obj_context();
137 
138 	if (!ipa_ctx) {
139 		ipa_err("invalid ipa context");
140 		return;
141 	}
142 
143 	ipa_ctx->ipa_rx_destructor_count++;
144 }
145 
146 void wlan_ipa_uc_rt_debug_deinit(struct wlan_ipa_priv *ipa_ctx)
147 {
148 	qdf_mutex_destroy(&ipa_ctx->rt_debug_lock);
149 
150 	if (!wlan_ipa_is_rt_debugging_enabled(ipa_ctx->config)) {
151 		ipa_debug("IPA RT debug is not enabled");
152 		return;
153 	}
154 
155 	if (QDF_TIMER_STATE_STOPPED !=
156 		qdf_mc_timer_get_current_state(&ipa_ctx->rt_debug_fill_timer)) {
157 		qdf_mc_timer_stop(&ipa_ctx->rt_debug_fill_timer);
158 	}
159 	qdf_mc_timer_destroy(&ipa_ctx->rt_debug_fill_timer);
160 
161 	if (QDF_TIMER_STATE_STOPPED !=
162 		qdf_mc_timer_get_current_state(&ipa_ctx->rt_debug_timer)) {
163 		qdf_mc_timer_stop(&ipa_ctx->rt_debug_timer);
164 	}
165 	qdf_mc_timer_destroy(&ipa_ctx->rt_debug_timer);
166 }
167 
168 void wlan_ipa_uc_rt_debug_init(struct wlan_ipa_priv *ipa_ctx)
169 {
170 	qdf_mutex_create(&ipa_ctx->rt_debug_lock);
171 	ipa_ctx->rt_buf_fill_index = 0;
172 	qdf_mem_zero(ipa_ctx->rt_bug_buffer,
173 		sizeof(struct uc_rt_debug_info) *
174 		WLAN_IPA_UC_RT_DEBUG_BUF_COUNT);
175 	ipa_ctx->ipa_tx_forward = 0;
176 	ipa_ctx->ipa_rx_discard = 0;
177 	ipa_ctx->ipa_rx_net_send_count = 0;
178 	ipa_ctx->ipa_rx_internal_drop_count = 0;
179 	ipa_ctx->ipa_rx_destructor_count = 0;
180 
181 	/* Realtime debug enable on feature enable */
182 	if (!wlan_ipa_is_rt_debugging_enabled(ipa_ctx->config)) {
183 		ipa_debug("IPA RT debug is not enabled");
184 		return;
185 	}
186 
187 	qdf_mc_timer_init(&ipa_ctx->rt_debug_fill_timer, QDF_TIMER_TYPE_SW,
188 		wlan_ipa_uc_rt_debug_host_fill, (void *)ipa_ctx);
189 	qdf_mc_timer_start(&ipa_ctx->rt_debug_fill_timer,
190 		WLAN_IPA_UC_RT_DEBUG_FILL_INTERVAL);
191 
192 	qdf_mc_timer_init(&ipa_ctx->rt_debug_timer, QDF_TIMER_TYPE_SW,
193 		wlan_ipa_uc_rt_debug_handler, (void *)ipa_ctx);
194 	qdf_mc_timer_start(&ipa_ctx->rt_debug_timer,
195 		WLAN_IPA_UC_RT_DEBUG_PERIOD);
196 
197 }
198 
199 /**
200  * wlan_ipa_dump_ipa_ctx() - dump entries in IPA IPA struct
201  * @ipa_ctx: IPA context
202  *
203  * Dump entries in struct ipa_ctx
204  *
205  * Return: none
206  */
207 static void wlan_ipa_dump_ipa_ctx(struct wlan_ipa_priv *ipa_ctx)
208 {
209 	int i;
210 
211 	/* IPA IPA */
212 	ipa_info("\n==== IPA IPA ====\n"
213 		"num_iface: %d\n"
214 		"rm_state: %d\n"
215 		"rm_lock: %pK\n"
216 		"uc_rm_work: %pK\n"
217 		"uc_op_work: %pK\n"
218 		"wake_lock: %pK\n"
219 		"wake_lock_work: %pK\n"
220 		"wake_lock_released: %d\n"
221 		"tx_ref_cnt: %d\n"
222 		"pm_queue_head----\n"
223 		"\thead: %pK\n"
224 		"\ttail: %pK\n"
225 		"\tqlen: %d\n"
226 		"pm_work: %pK\n"
227 		"pm_lock: %pK\n"
228 		"suspended: %d\n",
229 		ipa_ctx->num_iface,
230 		ipa_ctx->rm_state,
231 		&ipa_ctx->rm_lock,
232 		&ipa_ctx->uc_rm_work,
233 		&ipa_ctx->uc_op_work,
234 		&ipa_ctx->wake_lock,
235 		&ipa_ctx->wake_lock_work,
236 		ipa_ctx->wake_lock_released,
237 		ipa_ctx->tx_ref_cnt.counter,
238 		ipa_ctx->pm_queue_head.head,
239 		ipa_ctx->pm_queue_head.tail,
240 		ipa_ctx->pm_queue_head.qlen,
241 		&ipa_ctx->pm_work,
242 		&ipa_ctx->pm_lock,
243 		ipa_ctx->suspended);
244 
245 	ipa_info("\nq_lock: %pK\n"
246 		"pend_desc_head----\n"
247 		"\tnext: %pK\n"
248 		"\tprev: %pK\n"
249 		"stats: %pK\n"
250 		"curr_prod_bw: %d\n"
251 		"curr_cons_bw: %d\n"
252 		"activated_fw_pipe: %d\n"
253 		"sap_num_connected_sta: %d\n"
254 		"sta_connected: %d\n",
255 		&ipa_ctx->q_lock,
256 		ipa_ctx->pend_desc_head.next,
257 		ipa_ctx->pend_desc_head.prev,
258 		&ipa_ctx->stats,
259 		ipa_ctx->curr_prod_bw,
260 		ipa_ctx->curr_cons_bw,
261 		ipa_ctx->activated_fw_pipe,
262 		ipa_ctx->sap_num_connected_sta,
263 		(unsigned int)ipa_ctx->sta_connected);
264 
265 	ipa_info("\ntx_pipe_handle: 0x%x\n"
266 		"rx_pipe_handle: 0x%x\n"
267 		"resource_loading: %d\n"
268 		"resource_unloading: %d\n"
269 		"pending_cons_req: %d\n"
270 		"pending_event----\n"
271 		"\tanchor.next: %pK\n"
272 		"\tanchor.prev: %pK\n"
273 		"\tcount: %d\n"
274 		"\tmax_size: %d\n"
275 		"event_lock: %pK\n"
276 		"ipa_tx_packets_diff: %d\n"
277 		"ipa_rx_packets_diff: %d\n"
278 		"ipa_p_tx_packets: %d\n"
279 		"ipa_p_rx_packets: %d\n"
280 		"stat_req_reason: %d\n",
281 		ipa_ctx->tx_pipe_handle,
282 		ipa_ctx->rx_pipe_handle,
283 		ipa_ctx->resource_loading,
284 		ipa_ctx->resource_unloading,
285 		ipa_ctx->pending_cons_req,
286 		ipa_ctx->pending_event.anchor.next,
287 		ipa_ctx->pending_event.anchor.prev,
288 		ipa_ctx->pending_event.count,
289 		ipa_ctx->pending_event.max_size,
290 		&ipa_ctx->event_lock,
291 		ipa_ctx->ipa_tx_packets_diff,
292 		ipa_ctx->ipa_rx_packets_diff,
293 		ipa_ctx->ipa_p_tx_packets,
294 		ipa_ctx->ipa_p_rx_packets,
295 		ipa_ctx->stat_req_reason);
296 
297 	ipa_info("\ncons_pipe_in----\n"
298 		"\tsys: %pK\n"
299 		"\tdl.comp_ring_base_pa: 0x%x\n"
300 		"\tdl.comp_ring_size: %d\n"
301 		"\tdl.ce_ring_base_pa: 0x%x\n"
302 		"\tdl.ce_door_bell_pa: 0x%x\n"
303 		"\tdl.ce_ring_size: %d\n"
304 		"\tdl.num_tx_buffers: %d\n"
305 		"prod_pipe_in----\n"
306 		"\tsys: %pK\n"
307 		"\tul.rdy_ring_base_pa: 0x%x\n"
308 		"\tul.rdy_ring_size: %d\n"
309 		"\tul.rdy_ring_rp_pa: 0x%x\n"
310 		"uc_loaded: %d\n"
311 		"wdi_enabled: %d\n"
312 		"rt_debug_fill_timer: %pK\n"
313 		"rt_debug_lock: %pK\n"
314 		"ipa_lock: %pK\n",
315 		&ipa_ctx->cons_pipe_in.sys,
316 		(unsigned int)ipa_ctx->cons_pipe_in.u.dl.comp_ring_base_pa,
317 		ipa_ctx->cons_pipe_in.u.dl.comp_ring_size,
318 		(unsigned int)ipa_ctx->cons_pipe_in.u.dl.ce_ring_base_pa,
319 		(unsigned int)ipa_ctx->cons_pipe_in.u.dl.ce_door_bell_pa,
320 		ipa_ctx->cons_pipe_in.u.dl.ce_ring_size,
321 		ipa_ctx->cons_pipe_in.u.dl.num_tx_buffers,
322 		&ipa_ctx->prod_pipe_in.sys,
323 		(unsigned int)ipa_ctx->prod_pipe_in.u.ul.rdy_ring_base_pa,
324 		ipa_ctx->prod_pipe_in.u.ul.rdy_ring_size,
325 		(unsigned int)ipa_ctx->prod_pipe_in.u.ul.rdy_ring_rp_pa,
326 		ipa_ctx->uc_loaded,
327 		ipa_ctx->wdi_enabled,
328 		&ipa_ctx->rt_debug_fill_timer,
329 		&ipa_ctx->rt_debug_lock,
330 		&ipa_ctx->ipa_lock);
331 
332 	ipa_info("\nvdev_to_iface----");
333 	for (i = 0; i < WLAN_IPA_MAX_SESSION; i++)
334 		ipa_info("\n\t[%d]=%d", i, ipa_ctx->vdev_to_iface[i]);
335 
336 	QDF_TRACE(QDF_MODULE_ID_IPA, QDF_TRACE_LEVEL_INFO,
337 		"\nvdev_offload_enabled----");
338 	for (i = 0; i < WLAN_IPA_MAX_SESSION; i++)
339 		ipa_info("\n\t[%d]=%d", i, ipa_ctx->vdev_offload_enabled[i]);
340 
341 	QDF_TRACE(QDF_MODULE_ID_IPA, QDF_TRACE_LEVEL_INFO,
342 		"\nassoc_stas_map ----");
343 	for (i = 0; i < WLAN_IPA_MAX_STA_COUNT; i++) {
344 		ipa_info("\n\t[%d]: is_reserved=%d mac: " QDF_MAC_ADDR_FMT, i,
345 			 ipa_ctx->assoc_stas_map[i].is_reserved,
346 			 QDF_MAC_ADDR_REF(
347 				ipa_ctx->assoc_stas_map[i].mac_addr.bytes));
348 	}
349 }
350 
351 /**
352  * wlan_ipa_dump_sys_pipe() - dump IPA IPA SYS Pipe struct
353  * @ipa_ctx: IPA IPA struct
354  *
355  * Dump entire struct wlan_ipa_sys_pipe
356  *
357  * Return: none
358  */
359 static void wlan_ipa_dump_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
360 {
361 	int i;
362 
363 	/* IPA SYS Pipes */
364 	ipa_info("==== IPA SYS Pipes ====");
365 
366 	for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
367 		struct wlan_ipa_sys_pipe *sys_pipe;
368 		qdf_ipa_sys_connect_params_t *ipa_sys_params;
369 
370 		sys_pipe = &ipa_ctx->sys_pipe[i];
371 		ipa_sys_params = &sys_pipe->ipa_sys_params;
372 
373 		ipa_info("\nsys_pipe[%d]----\n"
374 			"\tconn_hdl: 0x%x\n"
375 			"\tconn_hdl_valid: %d\n"
376 			"\tnat_en: %d\n"
377 			"\thdr_len %d\n"
378 			"\thdr_additional_const_len: %d\n"
379 			"\thdr_ofst_pkt_size_valid: %d\n"
380 			"\thdr_ofst_pkt_size: %d\n"
381 			"\thdr_little_endian: %d\n"
382 			"\tmode: %d\n"
383 			"\tclient: %d\n"
384 			"\tdesc_fifo_sz: %d\n"
385 			"\tpriv: %pK\n"
386 			"\tnotify: %pK\n"
387 			"\tskip_ep_cfg: %d\n"
388 			"\tkeep_ipa_awake: %d\n",
389 			i,
390 			sys_pipe->conn_hdl,
391 			sys_pipe->conn_hdl_valid,
392 			QDF_IPA_SYS_PARAMS_NAT_EN(ipa_sys_params),
393 			QDF_IPA_SYS_PARAMS_HDR_LEN(ipa_sys_params),
394 			QDF_IPA_SYS_PARAMS_HDR_ADDITIONAL_CONST_LEN(
395 				ipa_sys_params),
396 			QDF_IPA_SYS_PARAMS_HDR_OFST_PKT_SIZE_VALID(
397 				ipa_sys_params),
398 			QDF_IPA_SYS_PARAMS_HDR_OFST_PKT_SIZE(ipa_sys_params),
399 			QDF_IPA_SYS_PARAMS_HDR_LITTLE_ENDIAN(ipa_sys_params),
400 			QDF_IPA_SYS_PARAMS_MODE(ipa_sys_params),
401 			QDF_IPA_SYS_PARAMS_CLIENT(ipa_sys_params),
402 			QDF_IPA_SYS_PARAMS_DESC_FIFO_SZ(ipa_sys_params),
403 			QDF_IPA_SYS_PARAMS_PRIV(ipa_sys_params),
404 			QDF_IPA_SYS_PARAMS_NOTIFY(ipa_sys_params),
405 			QDF_IPA_SYS_PARAMS_SKIP_EP_CFG(ipa_sys_params),
406 			QDF_IPA_SYS_PARAMS_KEEP_IPA_AWAKE(ipa_sys_params));
407 	}
408 }
409 
410 /**
411  * wlan_ipa_dump_iface_context() - dump IPA IPA Interface Context struct
412  * @ipa_ctx: IPA IPA struct
413  *
414  * Dump entire struct wlan_ipa_iface_context
415  *
416  * Return: none
417  */
418 static void wlan_ipa_dump_iface_context(struct wlan_ipa_priv *ipa_ctx)
419 {
420 	int i;
421 
422 	/* IPA Interface Contexts */
423 	ipa_info("\n==== IPA Interface Contexts ====\n");
424 
425 	for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
426 		struct wlan_ipa_iface_context *iface_context;
427 
428 		iface_context = &ipa_ctx->iface_context[i];
429 
430 		ipa_info("\niface_context[%d]----\n"
431 			"\tipa_ctx: %pK\n"
432 			"\tsession_id: %d\n"
433 			"\tcons_client: %d\n"
434 			"\tprod_client: %d\n"
435 			"\tiface_id: %d\n"
436 			"\tinterface_lock: %pK\n"
437 			"\tifa_address: 0x%x\n",
438 			i,
439 			iface_context->ipa_ctx,
440 			iface_context->session_id,
441 			iface_context->cons_client,
442 			iface_context->prod_client,
443 			iface_context->iface_id,
444 			&iface_context->interface_lock,
445 			iface_context->ifa_address);
446 	}
447 }
448 
449 void wlan_ipa_dump_info(struct wlan_ipa_priv *ipa_ctx)
450 {
451 	wlan_ipa_dump_ipa_ctx(ipa_ctx);
452 	wlan_ipa_dump_sys_pipe(ipa_ctx);
453 	wlan_ipa_dump_iface_context(ipa_ctx);
454 }
455 
456 void wlan_ipa_uc_stat_query(struct wlan_ipa_priv *ipa_ctx,
457 			    uint32_t *ipa_tx_diff, uint32_t *ipa_rx_diff)
458 {
459 	*ipa_tx_diff = 0;
460 	*ipa_rx_diff = 0;
461 
462 	qdf_mutex_acquire(&ipa_ctx->ipa_lock);
463 	if (wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
464 	    (false == ipa_ctx->resource_loading)) {
465 		*ipa_tx_diff = ipa_ctx->ipa_tx_packets_diff;
466 		*ipa_rx_diff = ipa_ctx->ipa_rx_packets_diff;
467 	}
468 	qdf_mutex_release(&ipa_ctx->ipa_lock);
469 }
470 
471 void wlan_ipa_uc_stat_request(struct wlan_ipa_priv *ipa_ctx, uint8_t reason)
472 {
473 	qdf_mutex_acquire(&ipa_ctx->ipa_lock);
474 	if (wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
475 	    (false == ipa_ctx->resource_loading)) {
476 		ipa_ctx->stat_req_reason = reason;
477 		cdp_ipa_get_stat(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id);
478 		qdf_mutex_release(&ipa_ctx->ipa_lock);
479 	} else {
480 		qdf_mutex_release(&ipa_ctx->ipa_lock);
481 	}
482 }
483 
484 /**
485  * wlan_ipa_print_session_info - Print IPA session info
486  * @ipa_ctx: IPA context
487  *
488  * Return: None
489  */
490 static void wlan_ipa_print_session_info(struct wlan_ipa_priv *ipa_ctx)
491 {
492 	struct wlan_ipa_uc_pending_event *event = NULL, *next = NULL;
493 	struct wlan_ipa_iface_context *iface_context = NULL;
494 	int i;
495 
496 	ipa_info("\n==== IPA SESSION INFO ====\n"
497 		"NUM IFACE: %d\n"
498 		"RM STATE: %d\n"
499 		"ACTIVATED FW PIPE: %d\n"
500 		"SAP NUM STAs: %d\n"
501 		"STA CONNECTED: %d\n"
502 		"CONCURRENT MODE: %s\n"
503 		"RSC LOADING: %d\n"
504 		"RSC UNLOADING: %d\n"
505 		"PENDING CONS REQ: %d\n"
506 		"IPA PIPES DOWN: %d\n"
507 		"IPA UC LOADED: %d\n"
508 		"IPA WDI ENABLED: %d\n"
509 		"NUM SEND MSG: %d\n"
510 		"NUM FREE MSG: %d\n",
511 		ipa_ctx->num_iface,
512 		ipa_ctx->rm_state,
513 		ipa_ctx->activated_fw_pipe,
514 		ipa_ctx->sap_num_connected_sta,
515 		ipa_ctx->sta_connected,
516 		(ipa_ctx->mcc_mode ? "MCC" : "SCC"),
517 		ipa_ctx->resource_loading,
518 		ipa_ctx->resource_unloading,
519 		ipa_ctx->pending_cons_req,
520 		ipa_ctx->ipa_pipes_down,
521 		ipa_ctx->uc_loaded,
522 		ipa_ctx->wdi_enabled,
523 		(unsigned int)ipa_ctx->stats.num_send_msg,
524 		(unsigned int)ipa_ctx->stats.num_free_msg);
525 
526 	for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
527 		iface_context = &ipa_ctx->iface_context[i];
528 
529 		if (iface_context->session_id == WLAN_IPA_MAX_SESSION)
530 			continue;
531 
532 		ipa_info("\nIFACE[%d]: mode:%d, offload:%d",
533 			 i, iface_context->device_mode,
534 			 ipa_ctx->vdev_offload_enabled[iface_context->
535 						       session_id]);
536 	}
537 
538 	for (i = 0; i < QDF_IPA_WLAN_EVENT_MAX; i++)
539 		ipa_info("\nEVENT[%d]=%d",
540 			 i, ipa_ctx->stats.event[i]);
541 
542 	i = 0;
543 	qdf_list_peek_front(&ipa_ctx->pending_event,
544 			(qdf_list_node_t **)&event);
545 	while (event) {
546 		ipa_info("PENDING EVENT[%d]: EVT:%s, MAC:"QDF_MAC_ADDR_FMT,
547 			 i, wlan_ipa_wlan_event_to_str(event->type),
548 			 QDF_MAC_ADDR_REF(event->mac_addr));
549 
550 		qdf_list_peek_next(&ipa_ctx->pending_event,
551 				   (qdf_list_node_t *)event,
552 				   (qdf_list_node_t **)&next);
553 		event = next;
554 		next = NULL;
555 		i++;
556 	}
557 }
558 
559 /**
560  * wlan_ipa_print_txrx_stats - Print IPA IPA TX/RX stats
561  * @ipa_ctx: IPA context
562  *
563  * Return: None
564  */
565 static void wlan_ipa_print_txrx_stats(struct wlan_ipa_priv *ipa_ctx)
566 {
567 	int i;
568 	struct wlan_ipa_iface_context *iface_context = NULL;
569 
570 	ipa_info("\n==== IPA IPA TX/RX STATS ====\n"
571 		"NUM RM GRANT: %llu\n"
572 		"NUM RM RELEASE: %llu\n"
573 		"NUM RM GRANT IMM: %llu\n"
574 		"NUM CONS PERF REQ: %llu\n"
575 		"NUM PROD PERF REQ: %llu\n"
576 		"NUM RX DROP: %llu\n"
577 		"NUM EXCP PKT: %llu\n"
578 		"NUM TX FWD OK: %llu\n"
579 		"NUM TX FWD ERR: %llu\n"
580 		"NUM TX DESC Q CNT: %llu\n"
581 		"NUM TX DESC ERROR: %llu\n"
582 		"NUM TX COMP CNT: %llu\n"
583 		"NUM TX QUEUED: %llu\n"
584 		"NUM TX DEQUEUED: %llu\n"
585 		"NUM MAX PM QUEUE: %llu\n"
586 		"TX REF CNT: %d\n"
587 		"SUSPENDED: %d\n"
588 		"PEND DESC HEAD: %pK\n"
589 		"TX DESC LIST: %pK\n",
590 		ipa_ctx->stats.num_rm_grant,
591 		ipa_ctx->stats.num_rm_release,
592 		ipa_ctx->stats.num_rm_grant_imm,
593 		ipa_ctx->stats.num_cons_perf_req,
594 		ipa_ctx->stats.num_prod_perf_req,
595 		ipa_ctx->stats.num_rx_drop,
596 		ipa_ctx->stats.num_rx_excep,
597 		ipa_ctx->stats.num_tx_fwd_ok,
598 		ipa_ctx->stats.num_tx_fwd_err,
599 		ipa_ctx->stats.num_tx_desc_q_cnt,
600 		ipa_ctx->stats.num_tx_desc_error,
601 		ipa_ctx->stats.num_tx_comp_cnt,
602 		ipa_ctx->stats.num_tx_queued,
603 		ipa_ctx->stats.num_tx_dequeued,
604 		ipa_ctx->stats.num_max_pm_queue,
605 		ipa_ctx->tx_ref_cnt.counter,
606 		ipa_ctx->suspended,
607 		&ipa_ctx->pend_desc_head,
608 		&ipa_ctx->tx_desc_free_list);
609 
610 	for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
611 
612 		iface_context = &ipa_ctx->iface_context[i];
613 		if (iface_context->session_id == WLAN_IPA_MAX_SESSION)
614 			continue;
615 
616 		ipa_info("IFACE[%d]: TX:%llu, TX DROP:%llu, TX ERR:%llu,"
617 			 " TX CAC DROP:%llu, RX IPA EXCEP:%llu",
618 			 i, iface_context->stats.num_tx,
619 			 iface_context->stats.num_tx_drop,
620 			 iface_context->stats.num_tx_err,
621 			 iface_context->stats.num_tx_cac_drop,
622 			 iface_context->stats.num_rx_ipa_excep);
623 	}
624 }
625 
626 void wlan_ipa_print_fw_wdi_stats(struct wlan_ipa_priv *ipa_ctx,
627 				 struct ipa_uc_fw_stats *uc_fw_stat)
628 {
629 	ipa_info("\n==== WLAN FW WDI TX STATS ====\n"
630 		"COMP RING SIZE: %d\n"
631 		"COMP RING DBELL IND VAL : %d\n"
632 		"COMP RING DBELL CACHED VAL : %d\n"
633 		"PKTS ENQ : %d\n"
634 		"PKTS COMP : %d\n"
635 		"IS SUSPEND : %d\n",
636 		uc_fw_stat->tx_comp_ring_size,
637 		uc_fw_stat->tx_comp_ring_dbell_ind_val,
638 		uc_fw_stat->tx_comp_ring_dbell_cached_val,
639 		uc_fw_stat->tx_pkts_enqueued,
640 		uc_fw_stat->tx_pkts_completed,
641 		uc_fw_stat->tx_is_suspend);
642 
643 	ipa_info("\n==== WLAN FW WDI RX STATS ====\n"
644 		"IND RING SIZE: %d\n"
645 		"IND RING DBELL IND VAL : %d\n"
646 		"IND RING DBELL CACHED VAL : %d\n"
647 		"RDY IND CACHE VAL : %d\n"
648 		"RFIL IND : %d\n"
649 		"NUM PKT INDICAT : %d\n"
650 		"BUF REFIL : %d\n"
651 		"NUM DROP NO SPC : %d\n"
652 		"NUM DROP NO BUF : %d\n"
653 		"IS SUSPND : %d\n",
654 		uc_fw_stat->rx_ind_ring_size,
655 		uc_fw_stat->rx_ind_ring_dbell_ind_val,
656 		uc_fw_stat->rx_ind_ring_dbell_ind_cached_val,
657 		uc_fw_stat->rx_ind_ring_rd_idx_cached_val,
658 		uc_fw_stat->rx_refill_idx,
659 		uc_fw_stat->rx_num_pkts_indicated,
660 		uc_fw_stat->rx_buf_refilled,
661 		uc_fw_stat->rx_num_ind_drop_no_space,
662 		uc_fw_stat->rx_num_ind_drop_no_buf,
663 		uc_fw_stat->rx_is_suspend);
664 }
665 
666 /**
667  * wlan_ipa_print_ipa_wdi_stats - Print IPA WDI stats
668  * @ipa_ctx: IPA context
669  *
670  * Return: None
671  */
672 static void wlan_ipa_print_ipa_wdi_stats(struct wlan_ipa_priv *ipa_ctx)
673 {
674 	qdf_ipa_hw_stats_wdi_info_data_t ipa_stat;
675 
676 	qdf_ipa_get_wdi_stats(&ipa_stat);
677 
678 	ipa_info("\n==== IPA WDI TX STATS ====\n"
679 		"NUM PROCD : %d\n"
680 		"CE DBELL : 0x%x\n"
681 		"NUM DBELL FIRED : %d\n"
682 		"COMP RNG FULL : %d\n"
683 		"COMP RNG EMPT : %d\n"
684 		"COMP RNG USE HGH : %d\n"
685 		"COMP RNG USE LOW : %d\n"
686 		"BAM FIFO FULL : %d\n"
687 		"BAM FIFO EMPT : %d\n"
688 		"BAM FIFO USE HGH : %d\n"
689 		"BAM FIFO USE LOW : %d\n"
690 		"NUM DBELL : %d\n"
691 		"NUM UNEXP DBELL : %d\n"
692 		"NUM BAM INT HDL : 0x%x\n"
693 		"NUM QMB INT HDL : 0x%x\n",
694 		ipa_stat.tx_ch_stats.num_pkts_processed,
695 		ipa_stat.tx_ch_stats.copy_engine_doorbell_value,
696 		ipa_stat.tx_ch_stats.num_db_fired,
697 		ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringFull,
698 		ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringEmpty,
699 		ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageHigh,
700 		ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageLow,
701 		ipa_stat.tx_ch_stats.bam_stats.bamFifoFull,
702 		ipa_stat.tx_ch_stats.bam_stats.bamFifoEmpty,
703 		ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageHigh,
704 		ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageLow,
705 		ipa_stat.tx_ch_stats.num_db,
706 		ipa_stat.tx_ch_stats.num_unexpected_db,
707 		ipa_stat.tx_ch_stats.num_bam_int_handled,
708 		ipa_stat.tx_ch_stats.num_qmb_int_handled);
709 
710 	ipa_info("\n==== IPA WDI RX STATS ====\n"
711 		"MAX OST PKT : %d\n"
712 		"NUM PKT PRCSD : %d\n"
713 		"RNG RP : 0x%x\n"
714 		"IND RNG FULL : %d\n"
715 		"IND RNG EMPT : %d\n"
716 		"IND RNG USE HGH : %d\n"
717 		"IND RNG USE LOW : %d\n"
718 		"BAM FIFO FULL : %d\n"
719 		"BAM FIFO EMPT : %d\n"
720 		"BAM FIFO USE HGH : %d\n"
721 		"BAM FIFO USE LOW : %d\n"
722 		"NUM DB : %d\n"
723 		"NUM UNEXP DB : %d\n"
724 		"NUM BAM INT HNDL : 0x%x\n",
725 		ipa_stat.rx_ch_stats.max_outstanding_pkts,
726 		ipa_stat.rx_ch_stats.num_pkts_processed,
727 		ipa_stat.rx_ch_stats.rx_ring_rp_value,
728 		ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringFull,
729 		ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringEmpty,
730 		ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageHigh,
731 		ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageLow,
732 		ipa_stat.rx_ch_stats.bam_stats.bamFifoFull,
733 		ipa_stat.rx_ch_stats.bam_stats.bamFifoEmpty,
734 		ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageHigh,
735 		ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageLow,
736 		ipa_stat.rx_ch_stats.num_db,
737 		ipa_stat.rx_ch_stats.num_unexpected_db,
738 		ipa_stat.rx_ch_stats.num_bam_int_handled);
739 }
740 
741 void wlan_ipa_uc_info(struct wlan_ipa_priv *ipa_ctx)
742 {
743 	wlan_ipa_print_session_info(ipa_ctx);
744 }
745 
746 void wlan_ipa_uc_stat(struct wlan_ipa_priv *ipa_ctx)
747 {
748 	/* IPA IPA TX/RX stats */
749 	wlan_ipa_print_txrx_stats(ipa_ctx);
750 	/* IPA WDI stats */
751 	wlan_ipa_print_ipa_wdi_stats(ipa_ctx);
752 	/* WLAN FW WDI stats */
753 	wlan_ipa_uc_stat_request(ipa_ctx, WLAN_IPA_UC_STAT_REASON_DEBUG);
754 }
755 
756 #ifdef FEATURE_METERING
757 
758 #ifdef WDI3_STATS_UPDATE
759 #ifdef WDI3_STATS_BW_MONITOR
760 /**
761  * __wlan_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
762  * IPA calls to get WLAN stats or set quota limit.
763  * @evt: the IPA event which triggered the callback
764  * @data: data associated with the event
765  *
766  * Return: None
767  */
768 static void __wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
769 					     void *data)
770 {
771 	struct wlan_ipa_priv *ipa_ctx = wlan_ipa_get_obj_context();
772 	struct qdf_ipa_inform_wlan_bw *bw_info;
773 	uint8_t bw_level_index;
774 	uint64_t throughput;
775 
776 	if (evt != IPA_INFORM_WLAN_BW)
777 		return;
778 
779 	bw_info = data;
780 	bw_level_index = QDF_IPA_INFORM_WLAN_BW_INDEX(bw_info);
781 	throughput = QDF_IPA_INFORM_WLAN_BW_THROUGHPUT(bw_info);
782 	ipa_debug("bw_info idx:%d tp:%llu", bw_level_index, throughput);
783 
784 	if (bw_level_index == ipa_ctx->curr_bw_level)
785 		return;
786 
787 	if (bw_level_index == WLAN_IPA_BW_LEVEL_LOW) {
788 		cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
789 				       QDF_IPA_CLIENT_WLAN2_CONS,
790 				       ipa_ctx->config->ipa_bw_low);
791 		ipa_ctx->curr_bw_level = WLAN_IPA_BW_LEVEL_LOW;
792 	} else if (bw_level_index == WLAN_IPA_BW_LEVEL_MEDIUM) {
793 		cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
794 				       QDF_IPA_CLIENT_WLAN2_CONS,
795 				       ipa_ctx->config->ipa_bw_medium);
796 		ipa_ctx->curr_bw_level = WLAN_IPA_BW_LEVEL_MEDIUM;
797 	} else if (bw_level_index == WLAN_IPA_BW_LEVEL_HIGH) {
798 		cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
799 				       QDF_IPA_CLIENT_WLAN2_CONS,
800 				       ipa_ctx->config->ipa_bw_high);
801 		ipa_ctx->curr_bw_level = WLAN_IPA_BW_LEVEL_HIGH;
802 	}
803 
804 	ipa_debug("Requested BW level: %d", ipa_ctx->curr_bw_level);
805 }
806 
807 #else
808 static void __wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
809 					     void *data)
810 {
811 }
812 #endif
813 
814 void wlan_ipa_update_tx_stats(struct wlan_ipa_priv *ipa_ctx, uint64_t sta_tx,
815 			      uint64_t ap_tx)
816 {
817 	qdf_ipa_wdi_tx_info_t tx_stats;
818 
819 	if (!qdf_atomic_read(&ipa_ctx->stats_quota))
820 		return;
821 
822 	QDF_IPA_WDI_TX_INFO_STA_TX_BYTES(&tx_stats) = sta_tx;
823 	QDF_IPA_WDI_TX_INFO_SAP_TX_BYTES(&tx_stats) = ap_tx;
824 
825 	qdf_ipa_wdi_wlan_stats(&tx_stats);
826 }
827 
828 #else
829 
830 /**
831  * wlan_ipa_uc_sharing_stats_request() - Get IPA stats from IPA.
832  * @ipa_ctx: IPA context
833  * @reset_stats: reset stat countis after response
834  *
835  * Return: None
836  */
837 static void wlan_ipa_uc_sharing_stats_request(struct wlan_ipa_priv *ipa_ctx,
838 					      uint8_t reset_stats)
839 {
840 	qdf_mutex_acquire(&ipa_ctx->ipa_lock);
841 	if (false == ipa_ctx->resource_loading) {
842 		qdf_mutex_release(&ipa_ctx->ipa_lock);
843 		cdp_ipa_uc_get_share_stats(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id,
844 					   reset_stats);
845 	} else {
846 		qdf_mutex_release(&ipa_ctx->ipa_lock);
847 	}
848 }
849 
850 /**
851  * wlan_ipa_uc_set_quota() - Set quota limit bytes from IPA.
852  * @ipa_ctx: IPA context
853  * @set_quota: when 1, FW starts quota monitoring
854  * @quota_bytes: quota limit in bytes
855  *
856  * Return: None
857  */
858 static void wlan_ipa_uc_set_quota(struct wlan_ipa_priv *ipa_ctx,
859 				  uint8_t set_quota,
860 				  uint64_t quota_bytes)
861 {
862 	ipa_info("SET_QUOTA: set_quota=%d, quota_bytes=%llu",
863 		 set_quota, quota_bytes);
864 
865 	qdf_mutex_acquire(&ipa_ctx->ipa_lock);
866 	if (false == ipa_ctx->resource_loading) {
867 		qdf_mutex_release(&ipa_ctx->ipa_lock);
868 		cdp_ipa_uc_set_quota(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id,
869 				     quota_bytes);
870 	} else {
871 		qdf_mutex_release(&ipa_ctx->ipa_lock);
872 	}
873 }
874 
875 /**
876  * __wlan_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
877  * IPA calls to get WLAN stats or set quota limit.
878  * @evt: the IPA event which triggered the callback
879  * @data: data associated with the event
880  *
881  * Return: None
882  */
883 static void __wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
884 					     void *data)
885 {
886 	struct wlan_ipa_priv *ipa_ctx = wlan_ipa_get_obj_context();
887 	struct wlan_ipa_iface_context *iface_ctx;
888 	qdf_ipa_get_wdi_sap_stats_t *wdi_sap_stats;
889 	qdf_ipa_set_wifi_quota_t *ipa_set_quota;
890 	QDF_STATUS status;
891 
892 	ipa_debug("event=%d", evt);
893 
894 	iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
895 	if (!iface_ctx) {
896 		ipa_err_rl("IPA uC share stats failed - no iface");
897 		return;
898 	}
899 
900 	switch (evt) {
901 	case IPA_GET_WDI_SAP_STATS:
902 		/* fill-up ipa_get_wdi_sap_stats structure after getting
903 		 * ipa_uc_fw_stats from FW
904 		 */
905 		wdi_sap_stats = data;
906 
907 		qdf_event_reset(&ipa_ctx->ipa_uc_sharing_stats_comp);
908 		wlan_ipa_uc_sharing_stats_request(ipa_ctx,
909 			QDF_IPA_GET_WDI_SAP_STATS_RESET_STATS(wdi_sap_stats));
910 		status = qdf_wait_for_event_completion(
911 			&ipa_ctx->ipa_uc_sharing_stats_comp,
912 			IPA_UC_SHARING_STATES_WAIT_TIME);
913 		if (!QDF_IS_STATUS_SUCCESS(status)) {
914 			ipa_err("IPA uC share stats request timed out");
915 			QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
916 				= 0;
917 		} else {
918 			QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
919 				= 1;
920 
921 			QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(wdi_sap_stats)
922 				= ipa_ctx->ipa_sharing_stats.ipv4_rx_packets;
923 			QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(wdi_sap_stats)
924 				= ipa_ctx->ipa_sharing_stats.ipv4_rx_bytes;
925 			QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(wdi_sap_stats)
926 				= ipa_ctx->ipa_sharing_stats.ipv6_rx_packets;
927 			QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(wdi_sap_stats)
928 				= ipa_ctx->ipa_sharing_stats.ipv6_rx_bytes;
929 			QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(wdi_sap_stats)
930 				= ipa_ctx->ipa_sharing_stats.ipv4_tx_packets;
931 			QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(wdi_sap_stats)
932 				= ipa_ctx->ipa_sharing_stats.ipv4_tx_bytes;
933 			QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(wdi_sap_stats)
934 				= ipa_ctx->ipa_sharing_stats.ipv6_tx_packets;
935 			QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(wdi_sap_stats)
936 				= ipa_ctx->ipa_sharing_stats.ipv6_tx_bytes;
937 		}
938 		break;
939 
940 	case IPA_SET_WIFI_QUOTA:
941 		/* get ipa_set_wifi_quota structure from IPA and pass to FW
942 		 * through quota_exceeded field in ipa_uc_fw_stats
943 		 */
944 		ipa_set_quota = data;
945 
946 		qdf_event_reset(&ipa_ctx->ipa_uc_set_quota_comp);
947 		wlan_ipa_uc_set_quota(ipa_ctx, ipa_set_quota->set_quota,
948 				      ipa_set_quota->quota_bytes);
949 
950 		status = qdf_wait_for_event_completion(
951 				&ipa_ctx->ipa_uc_set_quota_comp,
952 				IPA_UC_SET_QUOTA_WAIT_TIME);
953 		if (!QDF_IS_STATUS_SUCCESS(status)) {
954 			ipa_err("IPA uC set quota request timed out");
955 			QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota)	= 0;
956 		} else {
957 			QDF_IPA_SET_WIFI_QUOTA_BYTES(ipa_set_quota) =
958 				((uint64_t)(ipa_ctx->ipa_quota_rsp.quota_hi)
959 				  <<32)|ipa_ctx->ipa_quota_rsp.quota_lo;
960 			QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota)	=
961 				ipa_ctx->ipa_quota_rsp.success;
962 		}
963 		break;
964 
965 	default:
966 		break;
967 	}
968 }
969 
970 QDF_STATUS wlan_ipa_uc_op_metering(struct wlan_ipa_priv *ipa_ctx,
971 				   struct op_msg_type *op_msg)
972 {
973 	struct op_msg_type *msg = op_msg;
974 	struct ipa_uc_sharing_stats *uc_sharing_stats;
975 	struct ipa_uc_quota_rsp *uc_quota_rsp;
976 	struct ipa_uc_quota_ind *uc_quota_ind;
977 	struct wlan_ipa_iface_context *iface_ctx;
978 	uint64_t quota_bytes;
979 
980 	if (msg->op_code == WLAN_IPA_UC_OPCODE_SHARING_STATS) {
981 		/* fill-up ipa_uc_sharing_stats structure from FW */
982 		uc_sharing_stats = (struct ipa_uc_sharing_stats *)
983 			     ((uint8_t *)op_msg + sizeof(struct op_msg_type));
984 
985 		memcpy(&ipa_ctx->ipa_sharing_stats, uc_sharing_stats,
986 		       sizeof(struct ipa_uc_sharing_stats));
987 
988 		qdf_event_set(&ipa_ctx->ipa_uc_sharing_stats_comp);
989 	} else if (msg->op_code == WLAN_IPA_UC_OPCODE_QUOTA_RSP) {
990 		/* received set quota response */
991 		uc_quota_rsp = (struct ipa_uc_quota_rsp *)
992 			     ((uint8_t *)op_msg + sizeof(struct op_msg_type));
993 
994 		memcpy(&ipa_ctx->ipa_quota_rsp, uc_quota_rsp,
995 		       sizeof(struct ipa_uc_quota_rsp));
996 
997 		qdf_event_set(&ipa_ctx->ipa_uc_set_quota_comp);
998 	} else if (msg->op_code == WLAN_IPA_UC_OPCODE_QUOTA_IND) {
999 		/* hit quota limit */
1000 		uc_quota_ind = (struct ipa_uc_quota_ind *)
1001 			     ((uint8_t *)op_msg + sizeof(struct op_msg_type));
1002 
1003 		ipa_ctx->ipa_quota_ind.quota_bytes =
1004 					uc_quota_ind->quota_bytes;
1005 
1006 		/* send quota exceeded indication to IPA */
1007 		iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1008 		quota_bytes = uc_quota_ind->quota_bytes;
1009 		if (iface_ctx)
1010 			qdf_ipa_broadcast_wdi_quota_reach_ind(
1011 							iface_ctx->dev->ifindex,
1012 							quota_bytes);
1013 		else
1014 			ipa_err("Failed quota_reach_ind: NULL interface");
1015 	} else {
1016 		return QDF_STATUS_E_INVAL;
1017 	}
1018 
1019 	return QDF_STATUS_SUCCESS;
1020 }
1021 #endif /* WDI3_STATS_UPDATE */
1022 
1023 void wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
1024 				    void *data)
1025 {
1026 	struct qdf_op_sync *op_sync;
1027 
1028 	if (qdf_op_protect(&op_sync))
1029 		return;
1030 
1031 	__wlan_ipa_wdi_meter_notifier_cb(evt, data);
1032 
1033 	qdf_op_unprotect(op_sync);
1034 }
1035 #endif /* FEATURE_METERING */
1036 #endif /* IPA_OFFLOAD */
1037