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