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