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