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