1 /* 2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 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 */ 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 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 */ 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 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 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 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 IPA struct 200 * @ipa_ctx: IPA context 201 * 202 * Dump entries in struct ipa_ctx 203 * 204 * Return: none 205 */ 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 IPA SYS Pipe struct 352 * @ipa_ctx: IPA IPA struct 353 * 354 * Dump entire struct wlan_ipa_sys_pipe 355 * 356 * Return: none 357 */ 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 /** 410 * wlan_ipa_dump_iface_context() - dump IPA IPA Interface Context struct 411 * @ipa_ctx: IPA IPA struct 412 * 413 * Dump entire struct wlan_ipa_iface_context 414 * 415 * Return: none 416 */ 417 static void wlan_ipa_dump_iface_context(struct wlan_ipa_priv *ipa_ctx) 418 { 419 int i; 420 421 /* IPA Interface Contexts */ 422 ipa_info("\n==== IPA Interface Contexts ====\n"); 423 424 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) { 425 struct wlan_ipa_iface_context *iface_context; 426 427 iface_context = &ipa_ctx->iface_context[i]; 428 429 ipa_info("\niface_context[%d]----\n" 430 "\tipa_ctx: %pK\n" 431 "\tsession_id: %d\n" 432 "\tcons_client: %d\n" 433 "\tprod_client: %d\n" 434 "\tiface_id: %d\n" 435 "\tinterface_lock: %pK\n" 436 "\tifa_address: 0x%x\n", 437 i, 438 iface_context->ipa_ctx, 439 iface_context->session_id, 440 iface_context->cons_client, 441 iface_context->prod_client, 442 iface_context->iface_id, 443 &iface_context->interface_lock, 444 iface_context->ifa_address); 445 } 446 } 447 448 void wlan_ipa_dump_info(struct wlan_ipa_priv *ipa_ctx) 449 { 450 wlan_ipa_dump_ipa_ctx(ipa_ctx); 451 wlan_ipa_dump_sys_pipe(ipa_ctx); 452 wlan_ipa_dump_iface_context(ipa_ctx); 453 } 454 455 void wlan_ipa_uc_stat_query(struct wlan_ipa_priv *ipa_ctx, 456 uint32_t *ipa_tx_diff, uint32_t *ipa_rx_diff) 457 { 458 *ipa_tx_diff = 0; 459 *ipa_rx_diff = 0; 460 461 qdf_mutex_acquire(&ipa_ctx->ipa_lock); 462 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx) && 463 (false == ipa_ctx->resource_loading)) { 464 *ipa_tx_diff = ipa_ctx->ipa_tx_packets_diff; 465 *ipa_rx_diff = ipa_ctx->ipa_rx_packets_diff; 466 } 467 qdf_mutex_release(&ipa_ctx->ipa_lock); 468 } 469 470 void wlan_ipa_uc_stat_request(struct wlan_ipa_priv *ipa_ctx, uint8_t reason) 471 { 472 qdf_mutex_acquire(&ipa_ctx->ipa_lock); 473 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx) && 474 (false == ipa_ctx->resource_loading)) { 475 ipa_ctx->stat_req_reason = reason; 476 cdp_ipa_get_stat(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id); 477 qdf_mutex_release(&ipa_ctx->ipa_lock); 478 } else { 479 qdf_mutex_release(&ipa_ctx->ipa_lock); 480 } 481 } 482 483 /** 484 * wlan_ipa_print_session_info - Print IPA session info 485 * @ipa_ctx: IPA context 486 * 487 * Return: None 488 */ 489 static void wlan_ipa_print_session_info(struct wlan_ipa_priv *ipa_ctx) 490 { 491 struct wlan_ipa_uc_pending_event *event = NULL, *next = NULL; 492 struct wlan_ipa_iface_context *iface_context = NULL; 493 int i; 494 495 ipa_info("\n==== IPA SESSION INFO ====\n" 496 "NUM IFACE: %d\n" 497 "RM STATE: %d\n" 498 "ACTIVATED FW PIPE: %d\n" 499 "SAP NUM STAs: %d\n" 500 "STA CONNECTED: %d\n" 501 "CONCURRENT MODE: %s\n" 502 "RSC LOADING: %d\n" 503 "RSC UNLOADING: %d\n" 504 "PENDING CONS REQ: %d\n" 505 "IPA PIPES DOWN: %d\n" 506 "IPA UC LOADED: %d\n" 507 "IPA WDI ENABLED: %d\n" 508 "NUM SEND MSG: %d\n" 509 "NUM FREE MSG: %d\n", 510 ipa_ctx->num_iface, 511 ipa_ctx->rm_state, 512 ipa_ctx->activated_fw_pipe, 513 ipa_ctx->sap_num_connected_sta, 514 ipa_ctx->sta_connected, 515 (ipa_ctx->mcc_mode ? "MCC" : "SCC"), 516 ipa_ctx->resource_loading, 517 ipa_ctx->resource_unloading, 518 ipa_ctx->pending_cons_req, 519 ipa_ctx->ipa_pipes_down, 520 ipa_ctx->uc_loaded, 521 ipa_ctx->wdi_enabled, 522 (unsigned int)ipa_ctx->stats.num_send_msg, 523 (unsigned int)ipa_ctx->stats.num_free_msg); 524 525 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) { 526 iface_context = &ipa_ctx->iface_context[i]; 527 528 if (iface_context->session_id == WLAN_IPA_MAX_SESSION) 529 continue; 530 531 ipa_info("\nIFACE[%d]: mode:%d, offload:%d", 532 i, iface_context->device_mode, 533 ipa_ctx->vdev_offload_enabled[iface_context-> 534 session_id]); 535 } 536 537 for (i = 0; i < QDF_IPA_WLAN_EVENT_MAX; i++) 538 ipa_info("\nEVENT[%d]=%d", 539 i, ipa_ctx->stats.event[i]); 540 541 i = 0; 542 qdf_list_peek_front(&ipa_ctx->pending_event, 543 (qdf_list_node_t **)&event); 544 while (event) { 545 ipa_info("PENDING EVENT[%d]: EVT:%s, MAC:"QDF_MAC_ADDR_FMT, 546 i, wlan_ipa_wlan_event_to_str(event->type), 547 QDF_MAC_ADDR_REF(event->mac_addr)); 548 549 qdf_list_peek_next(&ipa_ctx->pending_event, 550 (qdf_list_node_t *)event, 551 (qdf_list_node_t **)&next); 552 event = next; 553 next = NULL; 554 i++; 555 } 556 } 557 558 /** 559 * wlan_ipa_print_txrx_stats - Print IPA IPA TX/RX stats 560 * @ipa_ctx: IPA context 561 * 562 * Return: None 563 */ 564 static void wlan_ipa_print_txrx_stats(struct wlan_ipa_priv *ipa_ctx) 565 { 566 int i; 567 struct wlan_ipa_iface_context *iface_context = NULL; 568 569 ipa_info("\n==== IPA IPA TX/RX STATS ====\n" 570 "NUM RM GRANT: %llu\n" 571 "NUM RM RELEASE: %llu\n" 572 "NUM RM GRANT IMM: %llu\n" 573 "NUM CONS PERF REQ: %llu\n" 574 "NUM PROD PERF REQ: %llu\n" 575 "NUM RX DROP: %llu\n" 576 "NUM EXCP PKT: %llu\n" 577 "NUM TX FWD OK: %llu\n" 578 "NUM TX FWD ERR: %llu\n" 579 "NUM TX DESC Q CNT: %llu\n" 580 "NUM TX DESC ERROR: %llu\n" 581 "NUM TX COMP CNT: %llu\n" 582 "NUM TX QUEUED: %llu\n" 583 "NUM TX DEQUEUED: %llu\n" 584 "NUM MAX PM QUEUE: %llu\n" 585 "TX REF CNT: %d\n" 586 "SUSPENDED: %d\n" 587 "PEND DESC HEAD: %pK\n" 588 "TX DESC LIST: %pK\n", 589 ipa_ctx->stats.num_rm_grant, 590 ipa_ctx->stats.num_rm_release, 591 ipa_ctx->stats.num_rm_grant_imm, 592 ipa_ctx->stats.num_cons_perf_req, 593 ipa_ctx->stats.num_prod_perf_req, 594 ipa_ctx->stats.num_rx_drop, 595 ipa_ctx->stats.num_rx_excep, 596 ipa_ctx->stats.num_tx_fwd_ok, 597 ipa_ctx->stats.num_tx_fwd_err, 598 ipa_ctx->stats.num_tx_desc_q_cnt, 599 ipa_ctx->stats.num_tx_desc_error, 600 ipa_ctx->stats.num_tx_comp_cnt, 601 ipa_ctx->stats.num_tx_queued, 602 ipa_ctx->stats.num_tx_dequeued, 603 ipa_ctx->stats.num_max_pm_queue, 604 ipa_ctx->tx_ref_cnt.counter, 605 ipa_ctx->suspended, 606 &ipa_ctx->pend_desc_head, 607 &ipa_ctx->tx_desc_free_list); 608 609 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) { 610 611 iface_context = &ipa_ctx->iface_context[i]; 612 if (iface_context->session_id == WLAN_IPA_MAX_SESSION) 613 continue; 614 615 ipa_info("IFACE[%d]: TX:%llu, TX DROP:%llu, TX ERR:%llu," 616 " TX CAC DROP:%llu, RX IPA EXCEP:%llu", 617 i, iface_context->stats.num_tx, 618 iface_context->stats.num_tx_drop, 619 iface_context->stats.num_tx_err, 620 iface_context->stats.num_tx_cac_drop, 621 iface_context->stats.num_rx_ipa_excep); 622 } 623 } 624 625 void wlan_ipa_print_fw_wdi_stats(struct wlan_ipa_priv *ipa_ctx, 626 struct ipa_uc_fw_stats *uc_fw_stat) 627 { 628 ipa_info("\n==== WLAN FW WDI TX STATS ====\n" 629 "COMP RING SIZE: %d\n" 630 "COMP RING DBELL IND VAL : %d\n" 631 "COMP RING DBELL CACHED VAL : %d\n" 632 "PKTS ENQ : %d\n" 633 "PKTS COMP : %d\n" 634 "IS SUSPEND : %d\n", 635 uc_fw_stat->tx_comp_ring_size, 636 uc_fw_stat->tx_comp_ring_dbell_ind_val, 637 uc_fw_stat->tx_comp_ring_dbell_cached_val, 638 uc_fw_stat->tx_pkts_enqueued, 639 uc_fw_stat->tx_pkts_completed, 640 uc_fw_stat->tx_is_suspend); 641 642 ipa_info("\n==== WLAN FW WDI RX STATS ====\n" 643 "IND RING SIZE: %d\n" 644 "IND RING DBELL IND VAL : %d\n" 645 "IND RING DBELL CACHED VAL : %d\n" 646 "RDY IND CACHE VAL : %d\n" 647 "RFIL IND : %d\n" 648 "NUM PKT INDICAT : %d\n" 649 "BUF REFIL : %d\n" 650 "NUM DROP NO SPC : %d\n" 651 "NUM DROP NO BUF : %d\n" 652 "IS SUSPND : %d\n", 653 uc_fw_stat->rx_ind_ring_size, 654 uc_fw_stat->rx_ind_ring_dbell_ind_val, 655 uc_fw_stat->rx_ind_ring_dbell_ind_cached_val, 656 uc_fw_stat->rx_ind_ring_rd_idx_cached_val, 657 uc_fw_stat->rx_refill_idx, 658 uc_fw_stat->rx_num_pkts_indicated, 659 uc_fw_stat->rx_buf_refilled, 660 uc_fw_stat->rx_num_ind_drop_no_space, 661 uc_fw_stat->rx_num_ind_drop_no_buf, 662 uc_fw_stat->rx_is_suspend); 663 } 664 665 /** 666 * wlan_ipa_print_ipa_wdi_stats - Print IPA WDI stats 667 * @ipa_ctx: IPA context 668 * 669 * Return: None 670 */ 671 static void wlan_ipa_print_ipa_wdi_stats(struct wlan_ipa_priv *ipa_ctx) 672 { 673 qdf_ipa_hw_stats_wdi_info_data_t ipa_stat; 674 675 qdf_ipa_get_wdi_stats(&ipa_stat); 676 677 ipa_info("\n==== IPA WDI TX STATS ====\n" 678 "NUM PROCD : %d\n" 679 "CE DBELL : 0x%x\n" 680 "NUM DBELL FIRED : %d\n" 681 "COMP RNG FULL : %d\n" 682 "COMP RNG EMPT : %d\n" 683 "COMP RNG USE HGH : %d\n" 684 "COMP RNG USE LOW : %d\n" 685 "BAM FIFO FULL : %d\n" 686 "BAM FIFO EMPT : %d\n" 687 "BAM FIFO USE HGH : %d\n" 688 "BAM FIFO USE LOW : %d\n" 689 "NUM DBELL : %d\n" 690 "NUM UNEXP DBELL : %d\n" 691 "NUM BAM INT HDL : 0x%x\n" 692 "NUM QMB INT HDL : 0x%x\n", 693 ipa_stat.tx_ch_stats.num_pkts_processed, 694 ipa_stat.tx_ch_stats.copy_engine_doorbell_value, 695 ipa_stat.tx_ch_stats.num_db_fired, 696 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringFull, 697 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringEmpty, 698 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageHigh, 699 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageLow, 700 ipa_stat.tx_ch_stats.bam_stats.bamFifoFull, 701 ipa_stat.tx_ch_stats.bam_stats.bamFifoEmpty, 702 ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageHigh, 703 ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageLow, 704 ipa_stat.tx_ch_stats.num_db, 705 ipa_stat.tx_ch_stats.num_unexpected_db, 706 ipa_stat.tx_ch_stats.num_bam_int_handled, 707 ipa_stat.tx_ch_stats.num_qmb_int_handled); 708 709 ipa_info("\n==== IPA WDI RX STATS ====\n" 710 "MAX OST PKT : %d\n" 711 "NUM PKT PRCSD : %d\n" 712 "RNG RP : 0x%x\n" 713 "IND RNG FULL : %d\n" 714 "IND RNG EMPT : %d\n" 715 "IND RNG USE HGH : %d\n" 716 "IND RNG USE LOW : %d\n" 717 "BAM FIFO FULL : %d\n" 718 "BAM FIFO EMPT : %d\n" 719 "BAM FIFO USE HGH : %d\n" 720 "BAM FIFO USE LOW : %d\n" 721 "NUM DB : %d\n" 722 "NUM UNEXP DB : %d\n" 723 "NUM BAM INT HNDL : 0x%x\n", 724 ipa_stat.rx_ch_stats.max_outstanding_pkts, 725 ipa_stat.rx_ch_stats.num_pkts_processed, 726 ipa_stat.rx_ch_stats.rx_ring_rp_value, 727 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringFull, 728 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringEmpty, 729 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageHigh, 730 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageLow, 731 ipa_stat.rx_ch_stats.bam_stats.bamFifoFull, 732 ipa_stat.rx_ch_stats.bam_stats.bamFifoEmpty, 733 ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageHigh, 734 ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageLow, 735 ipa_stat.rx_ch_stats.num_db, 736 ipa_stat.rx_ch_stats.num_unexpected_db, 737 ipa_stat.rx_ch_stats.num_bam_int_handled); 738 } 739 740 void wlan_ipa_uc_info(struct wlan_ipa_priv *ipa_ctx) 741 { 742 wlan_ipa_print_session_info(ipa_ctx); 743 } 744 745 void wlan_ipa_uc_stat(struct wlan_ipa_priv *ipa_ctx) 746 { 747 /* IPA IPA TX/RX stats */ 748 wlan_ipa_print_txrx_stats(ipa_ctx); 749 /* IPA WDI stats */ 750 wlan_ipa_print_ipa_wdi_stats(ipa_ctx); 751 /* WLAN FW WDI stats */ 752 wlan_ipa_uc_stat_request(ipa_ctx, WLAN_IPA_UC_STAT_REASON_DEBUG); 753 } 754 755 #ifdef FEATURE_METERING 756 757 #ifdef WDI3_STATS_UPDATE 758 #ifdef WDI3_STATS_BW_MONITOR 759 /** 760 * __wlan_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler. 761 * IPA calls to get WLAN stats or set quota limit. 762 * @priv: pointer to private data registered with IPA (we register a 763 * pointer to the IPA context) 764 * @evt: the IPA event which triggered the callback 765 * @data: data associated with the event 766 * 767 * Return: None 768 */ 769 static void __wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt, 770 void *data) 771 { 772 struct wlan_ipa_priv *ipa_ctx = wlan_ipa_get_obj_context(); 773 struct qdf_ipa_inform_wlan_bw *bw_info; 774 uint8_t bw_level_index; 775 uint64_t throughput; 776 777 if (evt != IPA_INFORM_WLAN_BW) 778 return; 779 780 bw_info = data; 781 bw_level_index = QDF_IPA_INFORM_WLAN_BW_INDEX(bw_info); 782 throughput = QDF_IPA_INFORM_WLAN_BW_THROUGHPUT(bw_info); 783 ipa_debug("bw_info idx:%d tp:%llu", bw_level_index, throughput); 784 785 if (bw_level_index == ipa_ctx->curr_bw_level) 786 return; 787 788 if (bw_level_index == WLAN_IPA_BW_LEVEL_LOW) { 789 cdp_ipa_set_perf_level(ipa_ctx->dp_soc, 790 QDF_IPA_CLIENT_WLAN2_CONS, 791 ipa_ctx->config->ipa_bw_low); 792 ipa_ctx->curr_bw_level = WLAN_IPA_BW_LEVEL_LOW; 793 } else if (bw_level_index == WLAN_IPA_BW_LEVEL_MEDIUM) { 794 cdp_ipa_set_perf_level(ipa_ctx->dp_soc, 795 QDF_IPA_CLIENT_WLAN2_CONS, 796 ipa_ctx->config->ipa_bw_medium); 797 ipa_ctx->curr_bw_level = WLAN_IPA_BW_LEVEL_MEDIUM; 798 } else if (bw_level_index == WLAN_IPA_BW_LEVEL_HIGH) { 799 cdp_ipa_set_perf_level(ipa_ctx->dp_soc, 800 QDF_IPA_CLIENT_WLAN2_CONS, 801 ipa_ctx->config->ipa_bw_high); 802 ipa_ctx->curr_bw_level = WLAN_IPA_BW_LEVEL_HIGH; 803 } 804 805 ipa_debug("Requested BW level: %d", ipa_ctx->curr_bw_level); 806 } 807 808 #else 809 static void __wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt, 810 void *data) 811 { 812 } 813 #endif 814 815 void wlan_ipa_update_tx_stats(struct wlan_ipa_priv *ipa_ctx, uint64_t sta_tx, 816 uint64_t ap_tx) 817 { 818 qdf_ipa_wdi_tx_info_t tx_stats; 819 820 if (!qdf_atomic_read(&ipa_ctx->stats_quota)) 821 return; 822 823 QDF_IPA_WDI_TX_INFO_STA_TX_BYTES(&tx_stats) = sta_tx; 824 QDF_IPA_WDI_TX_INFO_SAP_TX_BYTES(&tx_stats) = ap_tx; 825 826 qdf_ipa_wdi_wlan_stats(&tx_stats); 827 } 828 829 #else 830 831 /** 832 * wlan_ipa_uc_sharing_stats_request() - Get IPA stats from IPA. 833 * @ipa_ctx: IPA context 834 * @reset_stats: reset stat countis after response 835 * 836 * Return: None 837 */ 838 static void wlan_ipa_uc_sharing_stats_request(struct wlan_ipa_priv *ipa_ctx, 839 uint8_t reset_stats) 840 { 841 qdf_mutex_acquire(&ipa_ctx->ipa_lock); 842 if (false == ipa_ctx->resource_loading) { 843 qdf_mutex_release(&ipa_ctx->ipa_lock); 844 cdp_ipa_uc_get_share_stats(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id, 845 reset_stats); 846 } else { 847 qdf_mutex_release(&ipa_ctx->ipa_lock); 848 } 849 } 850 851 /** 852 * wlan_ipa_uc_set_quota() - Set quota limit bytes from IPA. 853 * @ipa_ctx: IPA context 854 * @set_quota: when 1, FW starts quota monitoring 855 * @quota_bytes: quota limit in bytes 856 * 857 * Return: None 858 */ 859 static void wlan_ipa_uc_set_quota(struct wlan_ipa_priv *ipa_ctx, 860 uint8_t set_quota, 861 uint64_t quota_bytes) 862 { 863 ipa_info("SET_QUOTA: set_quota=%d, quota_bytes=%llu", 864 set_quota, quota_bytes); 865 866 qdf_mutex_acquire(&ipa_ctx->ipa_lock); 867 if (false == ipa_ctx->resource_loading) { 868 qdf_mutex_release(&ipa_ctx->ipa_lock); 869 cdp_ipa_uc_set_quota(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id, 870 quota_bytes); 871 } else { 872 qdf_mutex_release(&ipa_ctx->ipa_lock); 873 } 874 } 875 876 /** 877 * __wlan_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler. 878 * IPA calls to get WLAN stats or set quota limit. 879 * @priv: pointer to private data registered with IPA (we register a 880 * pointer to the IPA context) 881 * @evt: the IPA event which triggered the callback 882 * @data: data associated with the event 883 * 884 * Return: None 885 */ 886 static void __wlan_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt, 887 void *data) 888 { 889 struct wlan_ipa_priv *ipa_ctx = wlan_ipa_get_obj_context(); 890 struct wlan_ipa_iface_context *iface_ctx; 891 qdf_ipa_get_wdi_sap_stats_t *wdi_sap_stats; 892 qdf_ipa_set_wifi_quota_t *ipa_set_quota; 893 QDF_STATUS status; 894 895 ipa_debug("event=%d", evt); 896 897 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE); 898 if (!iface_ctx) { 899 ipa_err_rl("IPA uC share stats failed - no iface"); 900 return; 901 } 902 903 switch (evt) { 904 case IPA_GET_WDI_SAP_STATS: 905 /* fill-up ipa_get_wdi_sap_stats structure after getting 906 * ipa_uc_fw_stats from FW 907 */ 908 wdi_sap_stats = data; 909 910 qdf_event_reset(&ipa_ctx->ipa_uc_sharing_stats_comp); 911 wlan_ipa_uc_sharing_stats_request(ipa_ctx, 912 QDF_IPA_GET_WDI_SAP_STATS_RESET_STATS(wdi_sap_stats)); 913 status = qdf_wait_for_event_completion( 914 &ipa_ctx->ipa_uc_sharing_stats_comp, 915 IPA_UC_SHARING_STATES_WAIT_TIME); 916 if (!QDF_IS_STATUS_SUCCESS(status)) { 917 ipa_err("IPA uC share stats request timed out"); 918 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats) 919 = 0; 920 } else { 921 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats) 922 = 1; 923 924 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(wdi_sap_stats) 925 = ipa_ctx->ipa_sharing_stats.ipv4_rx_packets; 926 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(wdi_sap_stats) 927 = ipa_ctx->ipa_sharing_stats.ipv4_rx_bytes; 928 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(wdi_sap_stats) 929 = ipa_ctx->ipa_sharing_stats.ipv6_rx_packets; 930 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(wdi_sap_stats) 931 = ipa_ctx->ipa_sharing_stats.ipv6_rx_bytes; 932 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(wdi_sap_stats) 933 = ipa_ctx->ipa_sharing_stats.ipv4_tx_packets; 934 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(wdi_sap_stats) 935 = ipa_ctx->ipa_sharing_stats.ipv4_tx_bytes; 936 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(wdi_sap_stats) 937 = ipa_ctx->ipa_sharing_stats.ipv6_tx_packets; 938 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(wdi_sap_stats) 939 = ipa_ctx->ipa_sharing_stats.ipv6_tx_bytes; 940 } 941 break; 942 943 case IPA_SET_WIFI_QUOTA: 944 /* get ipa_set_wifi_quota structure from IPA and pass to FW 945 * through quota_exceeded field in ipa_uc_fw_stats 946 */ 947 ipa_set_quota = data; 948 949 qdf_event_reset(&ipa_ctx->ipa_uc_set_quota_comp); 950 wlan_ipa_uc_set_quota(ipa_ctx, ipa_set_quota->set_quota, 951 ipa_set_quota->quota_bytes); 952 953 status = qdf_wait_for_event_completion( 954 &ipa_ctx->ipa_uc_set_quota_comp, 955 IPA_UC_SET_QUOTA_WAIT_TIME); 956 if (!QDF_IS_STATUS_SUCCESS(status)) { 957 ipa_err("IPA uC set quota request timed out"); 958 QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota) = 0; 959 } else { 960 QDF_IPA_SET_WIFI_QUOTA_BYTES(ipa_set_quota) = 961 ((uint64_t)(ipa_ctx->ipa_quota_rsp.quota_hi) 962 <<32)|ipa_ctx->ipa_quota_rsp.quota_lo; 963 QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota) = 964 ipa_ctx->ipa_quota_rsp.success; 965 } 966 break; 967 968 default: 969 break; 970 } 971 } 972 973 QDF_STATUS wlan_ipa_uc_op_metering(struct wlan_ipa_priv *ipa_ctx, 974 struct op_msg_type *op_msg) 975 { 976 struct op_msg_type *msg = op_msg; 977 struct ipa_uc_sharing_stats *uc_sharing_stats; 978 struct ipa_uc_quota_rsp *uc_quota_rsp; 979 struct ipa_uc_quota_ind *uc_quota_ind; 980 struct wlan_ipa_iface_context *iface_ctx; 981 uint64_t quota_bytes; 982 983 if (msg->op_code == WLAN_IPA_UC_OPCODE_SHARING_STATS) { 984 /* fill-up ipa_uc_sharing_stats structure from FW */ 985 uc_sharing_stats = (struct ipa_uc_sharing_stats *) 986 ((uint8_t *)op_msg + sizeof(struct op_msg_type)); 987 988 memcpy(&ipa_ctx->ipa_sharing_stats, uc_sharing_stats, 989 sizeof(struct ipa_uc_sharing_stats)); 990 991 qdf_event_set(&ipa_ctx->ipa_uc_sharing_stats_comp); 992 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_QUOTA_RSP) { 993 /* received set quota response */ 994 uc_quota_rsp = (struct ipa_uc_quota_rsp *) 995 ((uint8_t *)op_msg + sizeof(struct op_msg_type)); 996 997 memcpy(&ipa_ctx->ipa_quota_rsp, uc_quota_rsp, 998 sizeof(struct ipa_uc_quota_rsp)); 999 1000 qdf_event_set(&ipa_ctx->ipa_uc_set_quota_comp); 1001 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_QUOTA_IND) { 1002 /* hit quota limit */ 1003 uc_quota_ind = (struct ipa_uc_quota_ind *) 1004 ((uint8_t *)op_msg + sizeof(struct op_msg_type)); 1005 1006 ipa_ctx->ipa_quota_ind.quota_bytes = 1007 uc_quota_ind->quota_bytes; 1008 1009 /* send quota exceeded indication to IPA */ 1010 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE); 1011 quota_bytes = uc_quota_ind->quota_bytes; 1012 if (iface_ctx) 1013 qdf_ipa_broadcast_wdi_quota_reach_ind( 1014 iface_ctx->dev->ifindex, 1015 quota_bytes); 1016 else 1017 ipa_err("Failed quota_reach_ind: NULL interface"); 1018 } else { 1019 return QDF_STATUS_E_INVAL; 1020 } 1021 1022 return QDF_STATUS_SUCCESS; 1023 } 1024 #endif /* WDI3_STATS_UPDATE */ 1025 1026 /** 1027 * wlan_ipa_wdi_meter_notifier_cb() - SSR wrapper for 1028 * __wlan_ipa_wdi_meter_notifier_cb 1029 * @priv: pointer to private data registered with IPA (we register a 1030 * pointer to the IPA context) 1031 * @evt: the IPA event which triggered the callback 1032 * @data: data associated with the event 1033 * 1034 * Return: None 1035 */ 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