1 /*
2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024 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 /**
21 * DOC: target_if_cp_stats.c
22 *
23 * This file provide definition for APIs registered through lmac Tx Ops
24 */
25
26 #include <qdf_mem.h>
27 #include <qdf_status.h>
28 #include <target_if_cp_stats.h>
29 #include <wmi_unified_priv.h>
30 #include <wmi_unified_param.h>
31 #include <target_if.h>
32 #include <wlan_tgt_def_config.h>
33 #include <wmi_unified_api.h>
34 #include <wlan_osif_priv.h>
35 #include <wlan_cp_stats_utils_api.h>
36 #include <wlan_cp_stats_mc_tgt_api.h>
37 #include "../../../umac/cmn_services/utils/inc/wlan_utility.h"
38 #include <cdp_txrx_cmn_struct.h>
39 #include <cdp_txrx_ops.h>
40 #include <cdp_txrx_stats_struct.h>
41 #include <cdp_txrx_host_stats.h>
42 #include <cdp_txrx_ctrl.h>
43 #include <cds_api.h>
44 #ifdef WLAN_FEATURE_SON
45 #include "son_api.h"
46 #endif
47
48 #if defined(WLAN_SUPPORT_TWT) && defined(WLAN_TWT_CONV_SUPPORTED)
49 static QDF_STATUS
target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc * psoc)50 target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc *psoc)
51 {
52 return QDF_STATUS_SUCCESS;
53 }
54
55 static QDF_STATUS
target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc * psoc)56 target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc *psoc)
57 {
58 return QDF_STATUS_SUCCESS;
59 }
60 #elif defined(WLAN_SUPPORT_TWT) && !defined(WLAN_TWT_CONV_SUPPORTED)
61
62 #include <wmi.h>
63 #include <wlan_cp_stats_mc_ucfg_api.h>
64
65 /**
66 * target_if_twt_fill_peer_twt_session_params() - Fills peer twt session
67 * parameter obtained from firmware into mc_cp_stats of peer
68 * @mc_cp_stats: Pointer to Peer mc_cp stats
69 * @twt_params: twt session parameters to be copied
70 *
71 * Return: None
72 */
target_if_twt_fill_peer_twt_session_params(struct peer_mc_cp_stats * mc_cp_stats,struct wmi_host_twt_session_stats_info * twt_params)73 static void target_if_twt_fill_peer_twt_session_params
74 (
75 struct peer_mc_cp_stats *mc_cp_stats,
76 struct wmi_host_twt_session_stats_info *twt_params
77 )
78 {
79 uint32_t event_type;
80 int i = 0;
81
82 if (!mc_cp_stats || !twt_params)
83 return;
84
85 if ((twt_params->event_type == HOST_TWT_SESSION_UPDATE) ||
86 (twt_params->event_type == HOST_TWT_SESSION_TEARDOWN)) {
87 /* Update for a existing session, find by dialog_id */
88 for (i = 0; i < TWT_PEER_MAX_SESSIONS; i++) {
89 if (mc_cp_stats->twt_param[i].dialog_id !=
90 twt_params->dialog_id)
91 continue;
92 qdf_mem_copy(&mc_cp_stats->twt_param[i], twt_params,
93 sizeof(*twt_params));
94 return;
95 }
96 } else if (twt_params->event_type == HOST_TWT_SESSION_SETUP) {
97 /* New session, fill in any existing invalid session */
98 for (i = 0; i < TWT_PEER_MAX_SESSIONS; i++) {
99 event_type = mc_cp_stats->twt_param[i].event_type;
100 if ((event_type != HOST_TWT_SESSION_SETUP) &&
101 (event_type != HOST_TWT_SESSION_UPDATE)) {
102 qdf_mem_copy(&mc_cp_stats->twt_param[i],
103 twt_params,
104 sizeof(*twt_params));
105 return;
106 }
107 }
108 }
109
110 target_if_err("Unable to save twt session params with dialog id %d",
111 twt_params->dialog_id);
112 }
113
114 /**
115 * target_if_obtain_mc_cp_stat_obj() - Retrieves peer mc cp stats object
116 * @peer_obj: peer object
117 *
118 * Return: mc cp stats object on success or NULL
119 */
120 static struct peer_mc_cp_stats *
target_if_obtain_mc_cp_stat_obj(struct wlan_objmgr_peer * peer_obj)121 target_if_obtain_mc_cp_stat_obj(struct wlan_objmgr_peer *peer_obj)
122 {
123 struct peer_cp_stats *cp_stats_peer_obj;
124 struct peer_mc_cp_stats *mc_cp_stats;
125
126 cp_stats_peer_obj = wlan_objmgr_peer_get_comp_private_obj
127 (peer_obj, WLAN_UMAC_COMP_CP_STATS);
128 if (!cp_stats_peer_obj) {
129 target_if_err("cp peer stats obj err");
130 return NULL;
131 }
132
133 mc_cp_stats = cp_stats_peer_obj->peer_stats;
134 if (!mc_cp_stats) {
135 target_if_err("mc stats obj err");
136 return NULL;
137 }
138 return mc_cp_stats;
139 }
140
141 /**
142 * target_if_twt_session_params_event_handler() - Handles twt session stats
143 * event from firmware and store the per peer twt session parameters in
144 * mc_cp_stats
145 * @scn: scn handle
146 * @evt_buf: data buffer for event
147 * @evt_data_len: data length of event
148 *
149 * Return: 0 on success, else error values
150 */
target_if_twt_session_params_event_handler(ol_scn_t scn,uint8_t * evt_buf,uint32_t evt_data_len)151 static int target_if_twt_session_params_event_handler(ol_scn_t scn,
152 uint8_t *evt_buf,
153 uint32_t evt_data_len)
154 {
155 struct wlan_objmgr_psoc *psoc_obj;
156 struct wlan_objmgr_peer *peer_obj;
157 struct wmi_unified *wmi_hdl;
158 struct wmi_host_twt_session_stats_info twt_params;
159 struct wmi_twt_session_stats_event_param params = {0};
160 struct peer_mc_cp_stats *mc_cp_stats;
161 struct peer_cp_stats *peer_cp_stats_priv;
162 uint32_t expected_len;
163 int i;
164 QDF_STATUS status;
165
166 if (!scn || !evt_buf) {
167 target_if_err("scn: 0x%pK, evt_buf: 0x%pK", scn, evt_buf);
168 return -EINVAL;
169 }
170
171 psoc_obj = target_if_get_psoc_from_scn_hdl(scn);
172 if (!psoc_obj) {
173 target_if_err("psoc object is null!");
174 return -EINVAL;
175 }
176
177 wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc_obj);
178 if (!wmi_hdl) {
179 target_if_err("wmi_handle is null!");
180 return -EINVAL;
181 }
182
183 status = wmi_extract_twt_session_stats_event(wmi_hdl, evt_buf, ¶ms);
184 if (QDF_IS_STATUS_ERROR(status)) {
185 target_if_err("Could not extract twt session stats event");
186 return qdf_status_to_os_return(status);
187 }
188
189 if (params.num_sessions > TWT_PEER_MAX_SESSIONS) {
190 target_if_err("no of twt sessions exceeded the max supported");
191 return -EINVAL;
192 }
193
194 expected_len = (sizeof(wmi_pdev_twt_session_stats_event_fixed_param) +
195 WMI_TLV_HDR_SIZE + (params.num_sessions *
196 sizeof(wmi_twt_session_stats_info)));
197
198 if (evt_data_len < expected_len) {
199 target_if_err("Got invalid len of data from FW %d expected %d",
200 evt_data_len, expected_len);
201 return -EINVAL;
202 }
203
204 for (i = 0; i < params.num_sessions; i++) {
205 status = wmi_extract_twt_session_stats_data(wmi_hdl, evt_buf,
206 ¶ms,
207 &twt_params, i);
208 if (QDF_IS_STATUS_ERROR(status)) {
209 target_if_err("Unable to extract twt params for idx %d",
210 i);
211 return -EINVAL;
212 }
213
214 peer_obj = wlan_objmgr_get_peer_by_mac(psoc_obj,
215 twt_params.peer_mac,
216 WLAN_CP_STATS_ID);
217 if (!peer_obj) {
218 target_if_err("peer obj not found for "
219 QDF_MAC_ADDR_FMT,
220 QDF_MAC_ADDR_REF(twt_params.peer_mac));
221 continue;
222 }
223
224 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer_obj);
225 if (!peer_cp_stats_priv) {
226 target_if_err("peer_cp_stats_priv is null");
227 continue;
228 }
229
230 mc_cp_stats = target_if_obtain_mc_cp_stat_obj(peer_obj);
231 if (!mc_cp_stats) {
232 target_if_err("Unable to retrieve mc cp stats obj for "
233 QDF_MAC_ADDR_FMT,
234 QDF_MAC_ADDR_REF(twt_params.peer_mac));
235 wlan_objmgr_peer_release_ref(peer_obj,
236 WLAN_CP_STATS_ID);
237 continue;
238 }
239
240 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
241 target_if_twt_fill_peer_twt_session_params(mc_cp_stats,
242 &twt_params);
243 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
244
245 wlan_objmgr_peer_release_ref(peer_obj, WLAN_CP_STATS_ID);
246 }
247 return 0;
248 }
249
250 /**
251 * target_if_twt_session_params_unregister_evt_hdlr() - Unregister the
252 * event handler registered for wmi event wmi_twt_session_stats_event_id
253 * @psoc: psoc object
254 *
255 * Return: QDF_STATUS_SUCCESS on success or QDF error values on failure
256 */
257 static QDF_STATUS
target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc * psoc)258 target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc *psoc)
259 {
260 struct wmi_unified *wmi_handle;
261
262 if (!psoc) {
263 target_if_err("psoc obj in null!");
264 return QDF_STATUS_E_NULL_VALUE;
265 }
266
267 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
268 if (!wmi_handle) {
269 target_if_err("wmi_handle is null!");
270 return QDF_STATUS_E_INVAL;
271 }
272
273 wmi_unified_unregister_event_handler(wmi_handle,
274 wmi_twt_session_stats_event_id);
275
276 return QDF_STATUS_SUCCESS;
277 }
278
279 /**
280 * target_if_twt_session_params_register_evt_hdlr() - Register a event
281 * handler with wmi layer for wmi event wmi_twt_session_stats_event_id
282 * @psoc: psoc object
283 *
284 * Return: QDF_STATUS_SUCCESS on success or QDF error values on failure
285 */
286 static QDF_STATUS
target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc * psoc)287 target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc *psoc)
288 {
289 QDF_STATUS ret_val;
290 struct wmi_unified *wmi_handle;
291
292 if (!psoc) {
293 target_if_err("psoc obj in null!");
294 return QDF_STATUS_E_NULL_VALUE;
295 }
296
297 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
298 if (!wmi_handle) {
299 target_if_err("wmi_handle is null!");
300 return QDF_STATUS_E_INVAL;
301 }
302
303 ret_val = wmi_unified_register_event_handler(
304 wmi_handle,
305 wmi_twt_session_stats_event_id,
306 target_if_twt_session_params_event_handler,
307 WMI_RX_WORK_CTX);
308
309 if (QDF_IS_STATUS_ERROR(ret_val))
310 target_if_err("Failed to register twt session stats event cb");
311
312 return ret_val;
313 }
314 #else
315 static QDF_STATUS
target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc * psoc)316 target_if_twt_session_params_register_evt_hdlr(struct wlan_objmgr_psoc *psoc)
317 {
318 return QDF_STATUS_SUCCESS;
319 }
320
321 static QDF_STATUS
target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc * psoc)322 target_if_twt_session_params_unregister_evt_hdlr(struct wlan_objmgr_psoc *psoc)
323 {
324 return QDF_STATUS_SUCCESS;
325 }
326 #endif /* WLAN_SUPPORT_TWT */
327
328 #ifdef WLAN_FEATURE_MIB_STATS
target_if_cp_stats_free_mib_stats(struct stats_event * ev)329 static void target_if_cp_stats_free_mib_stats(struct stats_event *ev)
330 {
331 qdf_mem_free(ev->mib_stats);
332 ev->mib_stats = NULL;
333 }
334 #else
target_if_cp_stats_free_mib_stats(struct stats_event * ev)335 static void target_if_cp_stats_free_mib_stats(struct stats_event *ev)
336 {
337 }
338 #endif
339
340 /**
341 * target_if_cp_stats_free_peer_stats_info_ext() - API to free peer stats
342 * info ext structure
343 * @ev: structure from where peer stats info ext needs to be freed
344 *
345 * Return: none
346 */
target_if_cp_stats_free_peer_stats_info_ext(struct stats_event * ev)347 static void target_if_cp_stats_free_peer_stats_info_ext(struct stats_event *ev)
348 {
349 struct peer_stats_info_ext_event *peer_stats_info =
350 ev->peer_stats_info_ext;
351 uint16_t i;
352
353 for (i = 0; i < ev->num_peer_stats_info_ext; i++) {
354 qdf_mem_free(peer_stats_info->tx_pkt_per_mcs);
355 peer_stats_info->tx_pkt_per_mcs = NULL;
356 qdf_mem_free(peer_stats_info->rx_pkt_per_mcs);
357 peer_stats_info->rx_pkt_per_mcs = NULL;
358 peer_stats_info++;
359 }
360
361 qdf_mem_free(ev->peer_stats_info_ext);
362 ev->peer_stats_info_ext = NULL;
363 ev->num_peer_stats_info_ext = 0;
364 }
365
target_if_cp_stats_free_stats_event(struct stats_event * ev)366 static void target_if_cp_stats_free_stats_event(struct stats_event *ev)
367 {
368 qdf_mem_free(ev->pdev_stats);
369 ev->pdev_stats = NULL;
370 qdf_mem_free(ev->pdev_extd_stats);
371 ev->pdev_extd_stats = NULL;
372 qdf_mem_free(ev->peer_stats);
373 ev->peer_stats = NULL;
374 qdf_mem_free(ev->peer_adv_stats);
375 ev->peer_adv_stats = NULL;
376 qdf_mem_free(ev->peer_extended_stats);
377 ev->peer_extended_stats = NULL;
378 qdf_mem_free(ev->cca_stats);
379 ev->cca_stats = NULL;
380 qdf_mem_free(ev->vdev_summary_stats);
381 ev->vdev_summary_stats = NULL;
382 qdf_mem_free(ev->vdev_chain_rssi);
383 ev->vdev_chain_rssi = NULL;
384 target_if_cp_stats_free_mib_stats(ev);
385 target_if_cp_stats_free_peer_stats_info_ext(ev);
386 qdf_mem_free(ev->vdev_extd_stats);
387 ev->vdev_extd_stats = NULL;
388 }
389
target_if_cp_stats_extract_pdev_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)390 static QDF_STATUS target_if_cp_stats_extract_pdev_stats(
391 struct wmi_unified *wmi_hdl,
392 wmi_host_stats_event *stats_param,
393 struct stats_event *ev,
394 uint8_t *data)
395 {
396 uint32_t i;
397 QDF_STATUS status;
398 wmi_host_pdev_stats *pdev_stats;
399 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
400 cdp_config_param_type val;
401
402 ev->num_pdev_stats = stats_param->num_pdev_stats;
403 if (!ev->num_pdev_stats)
404 return QDF_STATUS_SUCCESS;
405
406 /*
407 * num_pdev_stats is validated within function wmi_extract_stats_param
408 * which is called to populated wmi_host_stats_event stats_param
409 */
410 ev->pdev_stats = qdf_mem_malloc(sizeof(*ev->pdev_stats) *
411 ev->num_pdev_stats);
412 if (!ev->pdev_stats)
413 return QDF_STATUS_E_NOMEM;
414
415 pdev_stats = qdf_mem_malloc(sizeof(*pdev_stats));
416
417 if (!pdev_stats) {
418 cp_stats_err("malloc failed for pdev_stats");
419 return QDF_STATUS_E_NOMEM;
420 }
421
422 for (i = 0; i < ev->num_pdev_stats; i++) {
423 status = wmi_extract_pdev_stats(wmi_hdl, data, i, pdev_stats);
424 if (QDF_IS_STATUS_ERROR(status)) {
425 cp_stats_err("wmi_extract_pdev_stats failed");
426 qdf_mem_free(pdev_stats);
427 return status;
428 }
429
430 /*
431 * It's 0.5 db unit from halphy. so correct the value here
432 */
433 ev->pdev_stats[i].max_pwr = pdev_stats->chan_tx_pwr >> 1;
434
435 ev->pdev_stats[i].pdev_id = pdev_stats->pdev_id;
436 ev->pdev_stats[i].rx_clear_count = pdev_stats->rx_clear_count;
437 ev->pdev_stats[i].tx_frame_count = pdev_stats->tx_frame_count;
438 ev->pdev_stats[i].cycle_count = pdev_stats->cycle_count;
439
440 val.cdp_pdev_param_chn_noise_flr = pdev_stats->chan_nf;
441 cdp_txrx_set_pdev_param(soc, 0, CDP_CHAN_NOISE_FLOOR, val);
442 }
443 qdf_mem_free(pdev_stats);
444
445 return QDF_STATUS_SUCCESS;
446 }
447
target_if_cp_stats_extract_pmf_bcn_protect_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)448 static QDF_STATUS target_if_cp_stats_extract_pmf_bcn_protect_stats(
449 struct wmi_unified *wmi_hdl,
450 wmi_host_stats_event *stats_param,
451 struct stats_event *ev, uint8_t *data)
452 {
453 QDF_STATUS status;
454 wmi_host_pmf_bcn_protect_stats pmf_bcn_stats = {0};
455
456 if (!(stats_param->stats_id & WMI_HOST_REQUEST_PMF_BCN_PROTECT_STAT))
457 return QDF_STATUS_SUCCESS;
458
459 qdf_mem_zero(&ev->bcn_protect_stats, sizeof(ev->bcn_protect_stats));
460 status = wmi_extract_pmf_bcn_protect_stats(wmi_hdl, data,
461 &pmf_bcn_stats);
462 if (QDF_IS_STATUS_ERROR(status)) {
463 cp_stats_err("wmi_extract_pmf_bcn_protect_stats failed");
464 return status;
465 }
466
467 ev->bcn_protect_stats.pmf_bcn_stats_valid = true;
468 ev->bcn_protect_stats.igtk_mic_fail_cnt =
469 pmf_bcn_stats.igtk_mic_fail_cnt;
470 ev->bcn_protect_stats.igtk_replay_cnt =
471 pmf_bcn_stats.igtk_replay_cnt;
472 ev->bcn_protect_stats.bcn_mic_fail_cnt =
473 pmf_bcn_stats.bcn_mic_fail_cnt;
474 ev->bcn_protect_stats.bcn_replay_cnt =
475 pmf_bcn_stats.bcn_replay_cnt;
476
477 return QDF_STATUS_SUCCESS;
478 }
479
480 static QDF_STATUS
target_if_cp_stats_extract_pdev_extd_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)481 target_if_cp_stats_extract_pdev_extd_stats(struct wmi_unified *wmi_hdl,
482 wmi_host_stats_event *stats_param,
483 struct stats_event *ev,
484 uint8_t *data)
485 {
486 uint32_t i;
487 QDF_STATUS status;
488 wmi_host_pdev_ext_stats *pdev_extd_stats;
489
490 if (!(stats_param->stats_id & WMI_REQUEST_PDEV_EXTD_STAT))
491 return QDF_STATUS_SUCCESS;
492
493 ev->pdev_extd_stats = qdf_mem_malloc(sizeof(*ev->pdev_extd_stats) *
494 WLAN_UMAC_MAX_RP_PID);
495 if (!ev->pdev_extd_stats)
496 return QDF_STATUS_E_NOMEM;
497
498 pdev_extd_stats = qdf_mem_malloc(sizeof(*pdev_extd_stats));
499 if (!pdev_extd_stats)
500 return QDF_STATUS_E_NOMEM;
501
502 ev->num_pdev_extd_stats = 0;
503 for (i = 0; i < stats_param->num_pdev_ext_stats; i++) {
504 qdf_mem_set(pdev_extd_stats, sizeof(*pdev_extd_stats), 0);
505
506 status = wmi_extract_pdev_ext_stats(wmi_hdl, data, i,
507 pdev_extd_stats);
508 if (QDF_IS_STATUS_ERROR(status)) {
509 qdf_mem_free(pdev_extd_stats);
510 cp_stats_err("wmi_extract_pdev_ext_stats failed");
511 return status;
512 }
513
514 ev->num_pdev_extd_stats++;
515 ev->pdev_extd_stats[i].pdev_id =
516 pdev_extd_stats->pdev_id;
517 ev->pdev_extd_stats[i].my_rx_count =
518 pdev_extd_stats->my_rx_count;
519 ev->pdev_extd_stats[i].rx_matched_11ax_msdu_cnt =
520 pdev_extd_stats->rx_matched_11ax_msdu_cnt;
521 ev->pdev_extd_stats[i].rx_other_11ax_msdu_cnt =
522 pdev_extd_stats->rx_other_11ax_msdu_cnt;
523 }
524
525 qdf_mem_free(pdev_extd_stats);
526 return QDF_STATUS_SUCCESS;
527 }
528
target_if_cp_stats_extract_peer_extd_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)529 static void target_if_cp_stats_extract_peer_extd_stats(
530 struct wmi_unified *wmi_hdl,
531 wmi_host_stats_event *stats_param,
532 struct stats_event *ev,
533 uint8_t *data)
534
535 {
536 QDF_STATUS status;
537 uint32_t i;
538 wmi_host_peer_extd_stats peer_extd_stats;
539 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
540 struct cdp_peer_stats *peer_stats;
541
542 if (!stats_param->num_peer_extd_stats)
543 return;
544
545 ev->peer_extended_stats =
546 qdf_mem_malloc(sizeof(*ev->peer_extended_stats) *
547 stats_param->num_peer_extd_stats);
548 if (!ev->peer_extended_stats)
549 return;
550
551 ev->num_peer_extd_stats = stats_param->num_peer_extd_stats;
552
553 for (i = 0; i < ev->num_peer_extd_stats; i++) {
554 status = wmi_extract_peer_extd_stats(wmi_hdl, data, i,
555 &peer_extd_stats);
556 if (QDF_IS_STATUS_ERROR(status)) {
557 cp_stats_err("wmi_extract_peer_extd_stats failed");
558 continue;
559 }
560 WMI_MAC_ADDR_TO_CHAR_ARRAY(
561 &peer_extd_stats.peer_macaddr,
562 ev->peer_extended_stats[i].peer_macaddr);
563 ev->peer_extended_stats[i].rx_mc_bc_cnt =
564 peer_extd_stats.rx_mc_bc_cnt;
565
566 peer_stats = qdf_mem_malloc(sizeof(*peer_stats));
567 if (!peer_stats)
568 continue;
569
570 status = cdp_host_get_peer_stats(soc, VDEV_ALL,
571 ev->peer_extended_stats[i].peer_macaddr,
572 peer_stats);
573 if (status == QDF_STATUS_SUCCESS)
574 ev->peer_extended_stats[i].rx_mc_bc_cnt =
575 peer_stats->rx.multicast.num +
576 peer_stats->rx.bcast.num;
577
578 qdf_mem_free(peer_stats);
579 }
580 }
581
target_if_cp_stats_extract_peer_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)582 static QDF_STATUS target_if_cp_stats_extract_peer_stats(
583 struct wmi_unified *wmi_hdl,
584 wmi_host_stats_event *stats_param,
585 struct stats_event *ev,
586 uint8_t *data)
587 {
588 uint32_t i;
589 QDF_STATUS status;
590 wmi_host_peer_stats peer_stats;
591 bool db2dbm_enabled;
592 struct wmi_host_peer_adv_stats *peer_adv_stats;
593
594 /* Extract peer_stats */
595 if (!stats_param->num_peer_stats)
596 goto adv_stats;
597
598 ev->peer_stats = qdf_mem_malloc(sizeof(*ev->peer_stats) *
599 stats_param->num_peer_stats);
600 if (!ev->peer_stats)
601 return QDF_STATUS_E_NOMEM;
602 ev->num_peer_stats = stats_param->num_peer_stats;
603
604 db2dbm_enabled = wmi_service_enabled(wmi_hdl,
605 wmi_service_hw_db2dbm_support);
606 for (i = 0; i < ev->num_peer_stats; i++) {
607 status = wmi_extract_peer_stats(wmi_hdl, data, i, &peer_stats);
608 if (QDF_IS_STATUS_ERROR(status)) {
609 cp_stats_err("wmi_extract_peer_stats failed");
610 continue;
611 }
612 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats.peer_macaddr,
613 ev->peer_stats[i].peer_macaddr);
614 ev->peer_stats[i].tx_rate = peer_stats.peer_tx_rate;
615 ev->peer_stats[i].rx_rate = peer_stats.peer_rx_rate;
616 if (db2dbm_enabled)
617 ev->peer_stats[i].peer_rssi = peer_stats.peer_rssi;
618 else
619 ev->peer_stats[i].peer_rssi = peer_stats.peer_rssi +
620 TGT_NOISE_FLOOR_DBM;
621 }
622
623 adv_stats:
624 target_if_cp_stats_extract_peer_extd_stats(wmi_hdl, stats_param, ev,
625 data);
626
627 /* Extract peer_adv_stats */
628 ev->num_peer_adv_stats = stats_param->num_peer_adv_stats;
629 if (!ev->num_peer_adv_stats)
630 return QDF_STATUS_SUCCESS;
631
632 ev->peer_adv_stats = qdf_mem_malloc(sizeof(*ev->peer_adv_stats) *
633 ev->num_peer_adv_stats);
634 if (!ev->peer_adv_stats)
635 return QDF_STATUS_E_NOMEM;
636
637 peer_adv_stats = qdf_mem_malloc(sizeof(*peer_adv_stats) *
638 ev->num_peer_adv_stats);
639 if (!peer_adv_stats) {
640 qdf_mem_free(ev->peer_adv_stats);
641 return QDF_STATUS_E_NOMEM;
642 }
643
644 status = wmi_extract_peer_adv_stats(wmi_hdl, data, peer_adv_stats);
645 if (QDF_IS_STATUS_ERROR(status)) {
646 cp_stats_err("wmi_extract_peer_stats failed");
647 qdf_mem_free(peer_adv_stats);
648 qdf_mem_free(ev->peer_adv_stats);
649 ev->peer_adv_stats = NULL;
650 return QDF_STATUS_SUCCESS;
651 }
652
653 for (i = 0; i < ev->num_peer_adv_stats; i++) {
654 qdf_mem_copy(&ev->peer_adv_stats[i].peer_macaddr,
655 &peer_adv_stats[i].peer_macaddr,
656 QDF_MAC_ADDR_SIZE);
657 ev->peer_adv_stats[i].fcs_count = peer_adv_stats[i].fcs_count;
658 ev->peer_adv_stats[i].rx_bytes = peer_adv_stats[i].rx_bytes;
659 ev->peer_adv_stats[i].rx_count = peer_adv_stats[i].rx_count;
660 }
661 qdf_mem_free(peer_adv_stats);
662 return QDF_STATUS_SUCCESS;
663 }
664
target_if_cp_stats_extract_cca_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)665 static QDF_STATUS target_if_cp_stats_extract_cca_stats(
666 struct wmi_unified *wmi_hdl,
667 wmi_host_stats_event *stats_param,
668 struct stats_event *ev, uint8_t *data)
669 {
670 QDF_STATUS status;
671 struct wmi_host_congestion_stats stats = {0};
672
673 status = wmi_extract_cca_stats(wmi_hdl, data, &stats);
674 if (QDF_IS_STATUS_ERROR(status))
675 return QDF_STATUS_SUCCESS;
676
677 ev->cca_stats = qdf_mem_malloc(sizeof(*ev->cca_stats));
678 if (!ev->cca_stats)
679 return QDF_STATUS_E_NOMEM;
680
681 ev->cca_stats->vdev_id = stats.vdev_id;
682 ev->cca_stats->congestion = stats.congestion;
683
684 return QDF_STATUS_SUCCESS;
685 }
686
687 #ifdef WLAN_FEATURE_MIB_STATS
target_if_cp_stats_extract_mib_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)688 static QDF_STATUS target_if_cp_stats_extract_mib_stats(
689 struct wmi_unified *wmi_hdl,
690 wmi_host_stats_event *stats_param,
691 struct stats_event *ev, uint8_t *data)
692 {
693 QDF_STATUS status;
694
695 if (!stats_param->num_mib_stats)
696 return QDF_STATUS_SUCCESS;
697
698 if (stats_param->num_mib_stats != MAX_MIB_STATS ||
699 (stats_param->num_mib_extd_stats &&
700 stats_param->num_mib_extd_stats != MAX_MIB_STATS)) {
701 cp_stats_err("number of mib stats wrong, num_mib_stats %d, num_mib_extd_stats %d",
702 stats_param->num_mib_stats,
703 stats_param->num_mib_extd_stats);
704 return QDF_STATUS_E_INVAL;
705 }
706
707 ev->num_mib_stats = stats_param->num_mib_stats;
708
709 ev->mib_stats = qdf_mem_malloc(sizeof(*ev->mib_stats));
710 if (!ev->mib_stats)
711 return QDF_STATUS_E_NOMEM;
712
713 status = wmi_extract_mib_stats(wmi_hdl, data, ev->mib_stats);
714 if (QDF_IS_STATUS_ERROR(status)) {
715 cp_stats_err("wmi_extract_mib_stats failed");
716 return status;
717 }
718
719 return QDF_STATUS_SUCCESS;
720 }
721 #else
target_if_cp_stats_extract_mib_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)722 static QDF_STATUS target_if_cp_stats_extract_mib_stats(
723 struct wmi_unified *wmi_hdl,
724 wmi_host_stats_event *stats_param,
725 struct stats_event *ev, uint8_t *data)
726 {
727 return QDF_STATUS_SUCCESS;
728 }
729 #endif
730
target_if_cp_stats_extract_vdev_summary_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)731 static QDF_STATUS target_if_cp_stats_extract_vdev_summary_stats(
732 struct wmi_unified *wmi_hdl,
733 wmi_host_stats_event *stats_param,
734 struct stats_event *ev, uint8_t *data)
735 {
736 uint32_t i, j;
737 QDF_STATUS status;
738 int32_t bcn_snr, dat_snr;
739 wmi_host_vdev_stats *vdev_stats;
740 bool db2dbm_enabled;
741
742 ev->num_summary_stats = stats_param->num_vdev_stats;
743 if (!ev->num_summary_stats)
744 return QDF_STATUS_SUCCESS;
745
746 ev->vdev_summary_stats = qdf_mem_malloc(sizeof(*ev->vdev_summary_stats)
747 * ev->num_summary_stats);
748
749 if (!ev->vdev_summary_stats)
750 return QDF_STATUS_E_NOMEM;
751
752 db2dbm_enabled = wmi_service_enabled(wmi_hdl,
753 wmi_service_hw_db2dbm_support);
754
755 vdev_stats = qdf_mem_malloc(sizeof(*vdev_stats));
756 if (!vdev_stats) {
757 cp_stats_err("malloc failed for vdev stats");
758 return QDF_STATUS_E_NOMEM;
759 }
760
761 for (i = 0; i < ev->num_summary_stats; i++) {
762 status = wmi_extract_vdev_stats(wmi_hdl, data, i, vdev_stats);
763 if (QDF_IS_STATUS_ERROR(status))
764 continue;
765
766 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
767 dat_snr = vdev_stats->vdev_snr.dat_snr;
768 ev->vdev_summary_stats[i].vdev_id = vdev_stats->vdev_id;
769 /*bcn_snr parameter can come as RSSi/SNR from the FW depending
770 on whether FW supports the RSSI reporting or not */
771 if (!db2dbm_enabled) {
772 cp_stats_debug("vdev %d SNR bcn: %d data: %d",
773 ev->vdev_summary_stats[i].vdev_id,
774 bcn_snr, dat_snr);
775 } else {
776 cp_stats_debug("vdev %d RSSI bcn: %d data: %d",
777 ev->vdev_summary_stats[i].vdev_id,
778 bcn_snr, dat_snr);
779 }
780 for (j = 0; j < 4; j++) {
781 ev->vdev_summary_stats[i].stats.tx_frm_cnt[j] =
782 vdev_stats->tx_frm_cnt[j];
783 ev->vdev_summary_stats[i].stats.fail_cnt[j] =
784 vdev_stats->fail_cnt[j];
785 ev->vdev_summary_stats[i].stats.multiple_retry_cnt[j] =
786 vdev_stats->multiple_retry_cnt[j];
787 }
788
789 ev->vdev_summary_stats[i].stats.rx_frm_cnt =
790 vdev_stats->rx_frm_cnt;
791 ev->vdev_summary_stats[i].stats.rx_error_cnt =
792 vdev_stats->rx_err_cnt;
793 ev->vdev_summary_stats[i].stats.rx_discard_cnt =
794 vdev_stats->rx_discard_cnt;
795 ev->vdev_summary_stats[i].stats.ack_fail_cnt =
796 vdev_stats->ack_fail_cnt;
797 ev->vdev_summary_stats[i].stats.rts_succ_cnt =
798 vdev_stats->rts_succ_cnt;
799 ev->vdev_summary_stats[i].stats.rts_fail_cnt =
800 vdev_stats->rts_fail_cnt;
801 /* Update SNR and RSSI in SummaryStats */
802 wlan_util_stats_get_rssi(db2dbm_enabled, bcn_snr, dat_snr,
803 &ev->vdev_summary_stats[i].stats.rssi);
804 ev->vdev_summary_stats[i].stats.snr =
805 ev->vdev_summary_stats[i].stats.rssi -
806 TGT_NOISE_FLOOR_DBM;
807 }
808 qdf_mem_free(vdev_stats);
809
810 return QDF_STATUS_SUCCESS;
811 }
812
813
target_if_cp_stats_extract_vdev_chain_rssi_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)814 static QDF_STATUS target_if_cp_stats_extract_vdev_chain_rssi_stats(
815 struct wmi_unified *wmi_hdl,
816 wmi_host_stats_event *stats_param,
817 struct stats_event *ev, uint8_t *data)
818 {
819 uint32_t i, j;
820 QDF_STATUS status;
821 int32_t bcn_snr, dat_snr;
822 struct wmi_host_per_chain_rssi_stats rssi_stats;
823 bool db2dbm_enabled;
824
825 ev->num_chain_rssi_stats = stats_param->num_rssi_stats;
826 if (!ev->num_chain_rssi_stats)
827 return QDF_STATUS_SUCCESS;
828
829 ev->vdev_chain_rssi = qdf_mem_malloc(sizeof(*ev->vdev_chain_rssi) *
830 ev->num_chain_rssi_stats);
831 if (!ev->vdev_chain_rssi)
832 return QDF_STATUS_E_NOMEM;
833
834 db2dbm_enabled = wmi_service_enabled(wmi_hdl,
835 wmi_service_hw_db2dbm_support);
836 for (i = 0; i < ev->num_chain_rssi_stats; i++) {
837 status = wmi_extract_per_chain_rssi_stats(wmi_hdl, data, i,
838 &rssi_stats);
839 if (QDF_IS_STATUS_ERROR(status))
840 continue;
841 ev->vdev_chain_rssi[i].vdev_id = rssi_stats.vdev_id;
842
843 for (j = 0; j < MAX_NUM_CHAINS; j++) {
844 dat_snr = rssi_stats.rssi_avg_data[j];
845 bcn_snr = rssi_stats.rssi_avg_beacon[j];
846 cp_stats_nofl_debug("Chain %d SNR bcn: %d data: %d", j,
847 bcn_snr, dat_snr);
848 /*
849 * Get the absolute rssi value from the current rssi
850 * value the snr value is hardcoded into 0 in the
851 * qcacld-new/CORE stack
852 */
853 wlan_util_stats_get_rssi(db2dbm_enabled, bcn_snr,
854 dat_snr,
855 &ev->vdev_chain_rssi[i].
856 chain_rssi[j]);
857 }
858 }
859
860 return QDF_STATUS_SUCCESS;
861 }
862
863 static QDF_STATUS
target_if_cp_stats_extract_vdev_extd_stats(struct wmi_unified * wmi_hdl,wmi_host_stats_event * stats_param,struct stats_event * ev,uint8_t * data)864 target_if_cp_stats_extract_vdev_extd_stats(struct wmi_unified *wmi_hdl,
865 wmi_host_stats_event *stats_param,
866 struct stats_event *ev,
867 uint8_t *data)
868 {
869 uint8_t i;
870 QDF_STATUS status;
871 struct wmi_host_vdev_prb_fils_stats *stats;
872
873 ev->num_vdev_extd_stats = stats_param->num_vdev_extd_stats;
874 if (!ev->num_vdev_extd_stats)
875 return QDF_STATUS_SUCCESS;
876
877 if (ev->num_vdev_extd_stats > WLAN_MAX_VDEVS) {
878 cp_stats_err("num_vdev_extd_stats is invalid: %u",
879 ev->num_vdev_extd_stats);
880 return QDF_STATUS_E_INVAL;
881 }
882
883 ev->vdev_extd_stats = qdf_mem_malloc(sizeof(*ev->vdev_extd_stats) *
884 ev->num_vdev_extd_stats);
885 if (!ev->vdev_extd_stats)
886 return QDF_STATUS_E_NOMEM;
887
888 stats = qdf_mem_malloc(sizeof(*stats) * ev->num_vdev_extd_stats);
889
890 if (!stats) {
891 cp_stats_err("malloc failed for vdev extended stats");
892 status = QDF_STATUS_E_NOMEM;
893 goto end;
894 }
895
896 for (i = 0 ; i < ev->num_vdev_extd_stats; i++) {
897 status = wmi_extract_vdev_prb_fils_stats(wmi_hdl, data,
898 i, stats);
899 if (QDF_IS_STATUS_ERROR(status)) {
900 cp_stats_err("wmi_extract_vdev_extd_stats failed");
901 qdf_mem_free(stats);
902 goto end;
903 }
904 ev->vdev_extd_stats[i].vdev_id = stats[0].vdev_id;
905 ev->vdev_extd_stats[i].is_mlo_vdev_active =
906 stats[0].is_mlo_vdev_active;
907 ev->vdev_extd_stats[i].vdev_tx_power = stats[i].vdev_tx_power;
908 }
909
910 qdf_mem_free(stats);
911 return status;
912
913 end:
914 qdf_mem_free(ev->vdev_extd_stats);
915 ev->vdev_extd_stats = NULL;
916 return status;
917 }
918
target_if_cp_stats_extract_event(struct wmi_unified * wmi_hdl,struct stats_event * ev,uint8_t * data)919 static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
920 struct stats_event *ev,
921 uint8_t *data)
922 {
923 QDF_STATUS status;
924 static uint8_t mac_seq = 0;
925 wmi_host_stats_event stats_param = {0};
926
927 status = wmi_extract_stats_param(wmi_hdl, data, &stats_param);
928 if (QDF_IS_STATUS_ERROR(status)) {
929 cp_stats_err("stats param extract failed: %d", status);
930 return status;
931 }
932 cp_stats_nofl_debug("num: pdev: %d, pdev_extd: %d, vdev: %d, vdev_extd: %d, "
933 "peer: %d, peer_extd: %d rssi: %d, mib %d, mib_extd %d, "
934 "bcnflt: %d, channel: %d, bcn: %d, peer_extd2: %d, "
935 "last_event: %x, stats id: %d",
936 stats_param.num_pdev_stats,
937 stats_param.num_pdev_ext_stats,
938 stats_param.num_vdev_stats,
939 stats_param.num_vdev_extd_stats,
940 stats_param.num_peer_stats,
941 stats_param.num_peer_extd_stats,
942 stats_param.num_rssi_stats,
943 stats_param.num_mib_stats,
944 stats_param.num_mib_extd_stats,
945 stats_param.num_bcnflt_stats,
946 stats_param.num_chan_stats,
947 stats_param.num_bcn_stats,
948 stats_param.num_peer_adv_stats,
949 stats_param.last_event,
950 stats_param.stats_id);
951
952 ev->last_event = stats_param.last_event;
953 ev->mac_seq_num = mac_seq;
954 if (IS_MSB_SET(ev->last_event) && IS_LSB_SET(ev->last_event))
955 mac_seq = 0;
956 else
957 mac_seq++;
958
959 status = target_if_cp_stats_extract_pdev_stats(wmi_hdl, &stats_param,
960 ev, data);
961 if (QDF_IS_STATUS_ERROR(status))
962 return status;
963
964 status = target_if_cp_stats_extract_peer_stats(wmi_hdl, &stats_param,
965 ev, data);
966 if (QDF_IS_STATUS_ERROR(status))
967 return status;
968
969 status = target_if_cp_stats_extract_cca_stats(wmi_hdl, &stats_param,
970 ev, data);
971 if (QDF_IS_STATUS_ERROR(status))
972 return status;
973
974 status = target_if_cp_stats_extract_vdev_summary_stats(wmi_hdl,
975 &stats_param,
976 ev, data);
977 if (QDF_IS_STATUS_ERROR(status))
978 return status;
979
980 status = target_if_cp_stats_extract_vdev_chain_rssi_stats(wmi_hdl,
981 &stats_param,
982 ev, data);
983 if (QDF_IS_STATUS_ERROR(status))
984 return status;
985
986 status = target_if_cp_stats_extract_mib_stats(wmi_hdl,
987 &stats_param,
988 ev, data);
989 if (QDF_IS_STATUS_ERROR(status))
990 return status;
991
992 status = target_if_cp_stats_extract_pmf_bcn_protect_stats(wmi_hdl,
993 &stats_param,
994 ev, data);
995 if (QDF_IS_STATUS_ERROR(status))
996 return status;
997
998 status = target_if_cp_stats_extract_pdev_extd_stats(wmi_hdl,
999 &stats_param,
1000 ev, data);
1001 if (QDF_IS_STATUS_ERROR(status))
1002 return status;
1003
1004 status = target_if_cp_stats_extract_vdev_extd_stats(wmi_hdl,
1005 &stats_param,
1006 ev, data);
1007 return status;
1008 }
1009
target_if_mc_cp_get_mac_id(struct vdev_mlme_obj * vdev_mlme)1010 uint8_t target_if_mc_cp_get_mac_id(struct vdev_mlme_obj *vdev_mlme)
1011 {
1012 uint8_t mac_id = 0;
1013
1014 if (wlan_reg_is_24ghz_ch_freq(vdev_mlme->vdev->vdev_mlme.des_chan->ch_freq))
1015 mac_id = TGT_MAC_ID_24G;
1016 else
1017 mac_id = TGT_MAC_ID_5G;
1018
1019 return mac_id;
1020 }
1021
1022 /**
1023 * target_if_mc_cp_stats_stats_event_handler() - function to handle stats event
1024 * from firmware.
1025 * @scn: scn handle
1026 * @data: data buffer for event
1027 * @datalen: data length
1028 *
1029 * Return: status of operation.
1030 */
target_if_mc_cp_stats_stats_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)1031 static int target_if_mc_cp_stats_stats_event_handler(ol_scn_t scn,
1032 uint8_t *data,
1033 uint32_t datalen)
1034 {
1035 QDF_STATUS status;
1036 struct stats_event *ev;
1037 struct wlan_objmgr_psoc *psoc;
1038 struct wmi_unified *wmi_handle;
1039 struct wlan_lmac_if_cp_stats_rx_ops *rx_ops;
1040
1041 if (!scn || !data) {
1042 cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
1043 return -EINVAL;
1044 }
1045 psoc = target_if_get_psoc_from_scn_hdl(scn);
1046 if (!psoc) {
1047 cp_stats_err("null psoc");
1048 return -EINVAL;
1049 }
1050
1051 rx_ops = target_if_cp_stats_get_rx_ops(psoc);
1052 if (!rx_ops || !rx_ops->process_stats_event) {
1053 cp_stats_err("callback not registered");
1054 return -EINVAL;
1055 }
1056
1057 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1058 if (!wmi_handle) {
1059 cp_stats_err("wmi_handle is null");
1060 return -EINVAL;
1061 }
1062
1063 ev = qdf_mem_malloc(sizeof(*ev));
1064 if (!ev) {
1065 cp_stats_err("");
1066 return -EINVAL;
1067 }
1068
1069 status = target_if_cp_stats_extract_event(wmi_handle, ev, data);
1070 if (QDF_IS_STATUS_ERROR(status)) {
1071 cp_stats_err("extract event failed");
1072 goto end;
1073 }
1074
1075 status = rx_ops->process_stats_event(psoc, ev);
1076
1077 end:
1078 target_if_cp_stats_free_stats_event(ev);
1079 qdf_mem_free(ev);
1080
1081 return qdf_status_to_os_return(status);
1082 }
1083
1084 #ifdef WLAN_FEATURE_BIG_DATA_STATS
target_if_mc_cp_stats_big_data_stats_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)1085 static int target_if_mc_cp_stats_big_data_stats_event_handler(ol_scn_t scn,
1086 uint8_t *data,
1087 uint32_t datalen)
1088 {
1089 QDF_STATUS status;
1090 struct big_data_stats_event ev = {0};
1091 struct wlan_objmgr_psoc *psoc;
1092 struct wmi_unified *wmi_handle;
1093 struct wlan_lmac_if_cp_stats_rx_ops *rx_ops;
1094
1095 if (!scn || !data) {
1096 cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
1097 return -EINVAL;
1098 }
1099 psoc = target_if_get_psoc_from_scn_hdl(scn);
1100 if (!psoc) {
1101 cp_stats_err("null psoc");
1102 return -EINVAL;
1103 }
1104
1105 rx_ops = target_if_cp_stats_get_rx_ops(psoc);
1106 if (!rx_ops || !rx_ops->process_big_data_stats_event) {
1107 cp_stats_err("callback not registered");
1108 return -EINVAL;
1109 }
1110
1111 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1112 if (!wmi_handle) {
1113 cp_stats_err("wmi_handle is null");
1114 return -EINVAL;
1115 }
1116
1117 status = wmi_extract_big_data_stats_param(wmi_handle, data, &ev);
1118 if (QDF_IS_STATUS_ERROR(status)) {
1119 cp_stats_err("extract event failed");
1120 goto end;
1121 }
1122
1123 status = rx_ops->process_big_data_stats_event(psoc, &ev);
1124
1125 end:
1126 return qdf_status_to_os_return(status);
1127 }
1128
1129 /**
1130 * target_if_cp_stats_send_big_data_stats_req() - API to send request to wmi
1131 * @psoc: pointer to psoc object
1132 * @req: pointer to object containing stats request parameters
1133 *
1134 * Return: status of operation.
1135 */
target_if_cp_stats_send_big_data_stats_req(struct wlan_objmgr_psoc * psoc,struct request_info * req)1136 static QDF_STATUS target_if_cp_stats_send_big_data_stats_req(
1137 struct wlan_objmgr_psoc *psoc,
1138 struct request_info *req)
1139
1140 {
1141 struct wmi_unified *wmi_handle;
1142 struct stats_request_params param = {0};
1143
1144 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1145 if (!wmi_handle) {
1146 cp_stats_err("wmi_handle is null.");
1147 return QDF_STATUS_E_NULL_VALUE;
1148 }
1149 param.vdev_id = req->vdev_id;
1150
1151 return wmi_unified_big_data_stats_request_send(wmi_handle,
1152 ¶m);
1153 }
1154 #endif
1155
1156 static QDF_STATUS
target_if_cp_stats_extract_peer_stats_event(struct wmi_unified * wmi_hdl,struct stats_event * ev,uint8_t * data)1157 target_if_cp_stats_extract_peer_stats_event(struct wmi_unified *wmi_hdl,
1158 struct stats_event *ev,
1159 uint8_t *data)
1160 {
1161 QDF_STATUS status;
1162 wmi_host_stats_event stats_param = {0};
1163 struct peer_stats_info_ext_event *peer_stats_info;
1164 wmi_host_peer_stats_info stats_info;
1165 uint32_t peer_stats_info_size;
1166 int i, j;
1167 uint32_t tx_rate_count_idx = 0, rx_rate_count_idx = 0;
1168
1169 status = wmi_extract_peer_stats_param(wmi_hdl, data, &stats_param);
1170 if (QDF_IS_STATUS_ERROR(status)) {
1171 cp_stats_err("peer stats param extract failed: %d", status);
1172 return status;
1173 }
1174
1175 if (stats_param.num_peer_stats_info_ext == 0) {
1176 cp_stats_err("num_peer_stats_info_ext is 0");
1177 return status;
1178 }
1179
1180 ev->num_peer_stats_info_ext = stats_param.num_peer_stats_info_ext;
1181 peer_stats_info_size = sizeof(*ev->peer_stats_info_ext) *
1182 ev->num_peer_stats_info_ext;
1183 ev->peer_stats_info_ext = qdf_mem_malloc(peer_stats_info_size);
1184 if (!ev->peer_stats_info_ext) {
1185 ev->num_peer_stats_info_ext = 0;
1186 return QDF_STATUS_E_NOMEM;
1187 }
1188
1189 peer_stats_info = ev->peer_stats_info_ext;
1190 for (i = 0; i < ev->num_peer_stats_info_ext; i++) {
1191 status = wmi_extract_peer_stats_info(wmi_hdl, data,
1192 i, &stats_info);
1193 if (QDF_IS_STATUS_ERROR(status)) {
1194 cp_stats_err("peer stats info extract failed: %d",
1195 status);
1196 target_if_cp_stats_free_peer_stats_info_ext(ev);
1197 return status;
1198 }
1199 qdf_mem_copy(&peer_stats_info->peer_macaddr,
1200 &stats_info.peer_macaddr,
1201 sizeof(peer_stats_info->peer_macaddr));
1202 peer_stats_info->tx_packets = stats_info.tx_packets;
1203 peer_stats_info->tx_bytes = stats_info.tx_bytes;
1204 peer_stats_info->rx_packets = stats_info.rx_packets;
1205 peer_stats_info->rx_bytes = stats_info.rx_bytes;
1206 peer_stats_info->tx_retries = stats_info.tx_retries;
1207 peer_stats_info->tx_failed = stats_info.tx_failed;
1208 peer_stats_info->tx_succeed = stats_info.tx_succeed;
1209 peer_stats_info->rssi = stats_info.peer_rssi;
1210 peer_stats_info->tx_rate = stats_info.last_tx_bitrate_kbps;
1211 peer_stats_info->tx_rate_code = stats_info.last_tx_rate_code;
1212 peer_stats_info->rx_rate = stats_info.last_rx_bitrate_kbps;
1213 peer_stats_info->rx_rate_code = stats_info.last_rx_rate_code;
1214 for (j = 0; j < WMI_MAX_CHAINS; j++)
1215 peer_stats_info->peer_rssi_per_chain[j] =
1216 stats_info.peer_rssi_per_chain[j];
1217
1218 if (stats_info.num_tx_rate_counts) {
1219 peer_stats_info->num_tx_rate_counts =
1220 stats_info.num_tx_rate_counts;
1221 status = wmi_extract_peer_tx_pkt_per_mcs(
1222 wmi_hdl, data,
1223 tx_rate_count_idx,
1224 &stats_info);
1225 if (QDF_IS_STATUS_ERROR(status)) {
1226 wmi_err("tx rate count extract failed");
1227 target_if_cp_stats_free_peer_stats_info_ext(ev);
1228 return status;
1229 }
1230 tx_rate_count_idx +=
1231 peer_stats_info->num_tx_rate_counts;
1232
1233 peer_stats_info->tx_pkt_per_mcs =
1234 stats_info.tx_pkt_per_mcs;
1235 stats_info.tx_pkt_per_mcs = NULL;
1236 }
1237 if (stats_info.num_rx_rate_counts) {
1238 peer_stats_info->num_rx_rate_counts =
1239 stats_info.num_rx_rate_counts;
1240 status = wmi_extract_peer_rx_pkt_per_mcs(
1241 wmi_hdl, data,
1242 rx_rate_count_idx,
1243 &stats_info);
1244 if (QDF_IS_STATUS_ERROR(status)) {
1245 wmi_err("rx rate count extract failed");
1246 target_if_cp_stats_free_peer_stats_info_ext(ev);
1247 return status;
1248 }
1249 rx_rate_count_idx +=
1250 peer_stats_info->num_rx_rate_counts;
1251
1252 peer_stats_info->rx_pkt_per_mcs =
1253 stats_info.rx_pkt_per_mcs;
1254 stats_info.rx_pkt_per_mcs = NULL;
1255 }
1256 peer_stats_info++;
1257 }
1258
1259 return QDF_STATUS_SUCCESS;
1260 }
1261
1262 /**
1263 * target_if_mc_cp_stats_peer_stats_info_event_handler() - function to handle
1264 * peer stats info event from firmware.
1265 * @scn: scn handle
1266 * @data: data buffer for event
1267 * @datalen: data length
1268 *
1269 * Return: status of operation.
1270 */
target_if_mc_cp_stats_peer_stats_info_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)1271 static int target_if_mc_cp_stats_peer_stats_info_event_handler(ol_scn_t scn,
1272 uint8_t *data,
1273 uint32_t datalen)
1274 {
1275 QDF_STATUS status;
1276 struct stats_event ev = {0};
1277 struct wlan_objmgr_psoc *psoc;
1278 struct wmi_unified *wmi_handle;
1279 struct wlan_lmac_if_cp_stats_rx_ops *rx_ops;
1280
1281 if (!scn || !data) {
1282 cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
1283 return -EINVAL;
1284 }
1285 psoc = target_if_get_psoc_from_scn_hdl(scn);
1286 if (!psoc) {
1287 cp_stats_err("null psoc");
1288 return -EINVAL;
1289 }
1290
1291 rx_ops = target_if_cp_stats_get_rx_ops(psoc);
1292 if (!rx_ops || !rx_ops->process_stats_event) {
1293 cp_stats_err("callback not registered");
1294 return -EINVAL;
1295 }
1296
1297 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1298 if (!wmi_handle) {
1299 cp_stats_err("wmi_handle is null");
1300 return -EINVAL;
1301 }
1302
1303 status = target_if_cp_stats_extract_peer_stats_event(wmi_handle,
1304 &ev, data);
1305 if (QDF_IS_STATUS_ERROR(status)) {
1306 cp_stats_err("extract event failed");
1307 goto end;
1308 }
1309
1310 status = rx_ops->process_stats_event(psoc, &ev);
1311
1312 end:
1313 target_if_cp_stats_free_stats_event(&ev);
1314
1315 return qdf_status_to_os_return(status);
1316 }
1317
target_if_cp_stats_inc_wake_lock_stats(uint32_t reason,struct wake_lock_stats * stats,uint32_t * unspecified_wake_count)1318 static void target_if_cp_stats_inc_wake_lock_stats(uint32_t reason,
1319 struct wake_lock_stats *stats,
1320 uint32_t *unspecified_wake_count)
1321 {
1322 switch (reason) {
1323 case WOW_REASON_UNSPECIFIED:
1324 (*unspecified_wake_count)++;
1325 break;
1326
1327 case WOW_REASON_ASSOC_REQ_RECV:
1328 stats->mgmt_assoc++;
1329 break;
1330
1331 case WOW_REASON_DISASSOC_RECVD:
1332 stats->mgmt_disassoc++;
1333 break;
1334
1335 case WOW_REASON_ASSOC_RES_RECV:
1336 stats->mgmt_assoc_resp++;
1337 break;
1338
1339 case WOW_REASON_REASSOC_REQ_RECV:
1340 stats->mgmt_reassoc++;
1341 break;
1342
1343 case WOW_REASON_REASSOC_RES_RECV:
1344 stats->mgmt_reassoc_resp++;
1345 break;
1346
1347 case WOW_REASON_AUTH_REQ_RECV:
1348 stats->mgmt_auth++;
1349 break;
1350
1351 case WOW_REASON_DEAUTH_RECVD:
1352 stats->mgmt_deauth++;
1353 break;
1354
1355 case WOW_REASON_ACTION_FRAME_RECV:
1356 stats->mgmt_action++;
1357 break;
1358
1359 case WOW_REASON_NLOD:
1360 stats->pno_match_wake_up_count++;
1361 break;
1362
1363 case WOW_REASON_NLO_SCAN_COMPLETE:
1364 stats->pno_complete_wake_up_count++;
1365 break;
1366
1367 case WOW_REASON_LOW_RSSI:
1368 stats->low_rssi_wake_up_count++;
1369 break;
1370
1371 case WOW_REASON_EXTSCAN:
1372 stats->gscan_wake_up_count++;
1373 break;
1374
1375 case WOW_REASON_RSSI_BREACH_EVENT:
1376 stats->rssi_breach_wake_up_count++;
1377 break;
1378
1379 case WOW_REASON_OEM_RESPONSE_EVENT:
1380 stats->oem_response_wake_up_count++;
1381 break;
1382
1383 case WOW_REASON_11D_SCAN:
1384 stats->scan_11d++;
1385 break;
1386
1387 case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
1388 stats->pwr_save_fail_detected++;
1389 break;
1390
1391 case WOW_REASON_LOCAL_DATA_UC_DROP:
1392 stats->uc_drop_wake_up_count++;
1393 break;
1394
1395 case WOW_REASON_FATAL_EVENT_WAKE:
1396 stats->fatal_event_wake_up_count++;
1397 break;
1398
1399 default:
1400 break;
1401 }
1402 }
1403
1404 #ifdef WLAN_FEATURE_BIG_DATA_STATS
1405 static QDF_STATUS
target_if_register_big_data_event_handler(struct wmi_unified * wmi_handle)1406 target_if_register_big_data_event_handler(struct wmi_unified *wmi_handle)
1407 {
1408 return wmi_unified_register_event_handler(
1409 wmi_handle, wmi_vdev_send_big_data_p2_eventid,
1410 target_if_mc_cp_stats_big_data_stats_event_handler,
1411 WMI_RX_WORK_CTX);
1412 }
1413
1414 static void
target_if_unregister_big_data_event_handler(struct wmi_unified * wmi_handle)1415 target_if_unregister_big_data_event_handler(struct wmi_unified *wmi_handle)
1416 {
1417 wmi_unified_unregister_event_handler(wmi_handle,
1418 wmi_vdev_send_big_data_p2_eventid);
1419 }
1420
1421 static QDF_STATUS
target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops * cp_stats_tx_ops)1422 target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops
1423 *cp_stats_tx_ops)
1424 {
1425 cp_stats_tx_ops->send_req_big_data_stats =
1426 target_if_cp_stats_send_big_data_stats_req;
1427 return QDF_STATUS_SUCCESS;
1428 }
1429
1430 static void
target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops * cp_stats_tx_ops)1431 target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops
1432 *cp_stats_tx_ops)
1433 {
1434 cp_stats_tx_ops->send_req_big_data_stats = NULL;
1435 }
1436 #else
1437 static QDF_STATUS
target_if_register_big_data_event_handler(struct wmi_unified * wmi_handle)1438 target_if_register_big_data_event_handler(struct wmi_unified *wmi_handle)
1439 {
1440 return QDF_STATUS_SUCCESS;
1441 }
1442
1443 static void
target_if_unregister_big_data_event_handler(struct wmi_unified * wmi_handle)1444 target_if_unregister_big_data_event_handler(struct wmi_unified *wmi_handle)
1445 {}
1446
1447 static QDF_STATUS
target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops * cp_stats_tx_ops)1448 target_if_big_data_stats_register_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops
1449 *cp_stats_tx_ops)
1450 {
1451 return QDF_STATUS_SUCCESS;
1452 }
1453
1454 static void
target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops * cp_stats_tx_ops)1455 target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops
1456 *cp_stats_tx_ops)
1457 {}
1458 #endif
1459
1460 #ifdef WLAN_FEATURE_SON
1461 static int
target_if_mc_cp_stats_inst_rssi_stats_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)1462 target_if_mc_cp_stats_inst_rssi_stats_event_handler(ol_scn_t scn,
1463 uint8_t *data,
1464 uint32_t datalen)
1465 {
1466 QDF_STATUS status;
1467 struct wlan_objmgr_peer *peer;
1468 struct wlan_objmgr_psoc *psoc;
1469 struct wmi_unified *wmi_handle;
1470 struct wmi_host_inst_rssi_stats_resp ev = {0};
1471
1472 if (!scn || !data) {
1473 cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
1474 return -EINVAL;
1475 }
1476
1477 psoc = target_if_get_psoc_from_scn_hdl(scn);
1478 if (!psoc) {
1479 cp_stats_err("null psoc");
1480 return -EINVAL;
1481 }
1482
1483 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1484 if (!wmi_handle) {
1485 cp_stats_err("wmi_handle is null");
1486 return -EINVAL;
1487 }
1488
1489 status = wmi_extract_inst_rssi_stats_resp(wmi_handle, data, &ev);
1490 if (QDF_IS_STATUS_ERROR(status)) {
1491 cp_stats_err("extract event failed");
1492 return qdf_status_to_os_return(status);
1493 }
1494
1495 peer = wlan_objmgr_get_peer_by_mac(psoc, ev.peer_macaddr.bytes,
1496 WLAN_CP_STATS_ID);
1497 if (!peer) {
1498 cp_stats_err("null peer");
1499 return -EINVAL;
1500 }
1501
1502 wlan_son_deliver_inst_rssi(wlan_peer_get_vdev(peer),
1503 peer,
1504 ev.inst_rssi);
1505
1506 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
1507
1508 return 0;
1509 }
1510
1511 static QDF_STATUS
target_if_register_inst_rssi_event_handler(struct wmi_unified * wmi_handle)1512 target_if_register_inst_rssi_event_handler(struct wmi_unified *wmi_handle)
1513 {
1514 return wmi_unified_register_event_handler(wmi_handle,
1515 wmi_inst_rssi_stats_event_id,
1516 target_if_mc_cp_stats_inst_rssi_stats_event_handler,
1517 WMI_RX_SERIALIZER_CTX);
1518 }
1519
1520 static void
target_if_unregister_inst_rssi_event_handler(struct wmi_unified * wmi_handle)1521 target_if_unregister_inst_rssi_event_handler(struct wmi_unified *wmi_handle)
1522 {
1523 wmi_unified_unregister_event_handler(wmi_handle,
1524 wmi_inst_rssi_stats_event_id);
1525 }
1526 #else
1527 static QDF_STATUS
target_if_register_inst_rssi_event_handler(struct wmi_unified * wmi_handle)1528 target_if_register_inst_rssi_event_handler(struct wmi_unified *wmi_handle)
1529 {
1530 return QDF_STATUS_SUCCESS;
1531 }
1532
1533 static void
target_if_unregister_inst_rssi_event_handler(struct wmi_unified * wmi_handle)1534 target_if_unregister_inst_rssi_event_handler(struct wmi_unified *wmi_handle)
1535 {
1536 }
1537 #endif
1538
1539 static QDF_STATUS
target_if_mc_cp_stats_register_event_handler(struct wlan_objmgr_psoc * psoc)1540 target_if_mc_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc)
1541 {
1542 QDF_STATUS ret_val;
1543 struct wmi_unified *wmi_handle;
1544
1545 if (!psoc) {
1546 cp_stats_err("PSOC is NULL!");
1547 return QDF_STATUS_E_NULL_VALUE;
1548 }
1549
1550 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1551 if (!wmi_handle) {
1552 cp_stats_err("wmi_handle is null");
1553 return QDF_STATUS_E_INVAL;
1554 }
1555
1556 ret_val = wmi_unified_register_event_handler(
1557 wmi_handle,
1558 wmi_update_stats_event_id,
1559 target_if_mc_cp_stats_stats_event_handler,
1560 WMI_RX_WORK_CTX);
1561 if (QDF_IS_STATUS_ERROR(ret_val))
1562 cp_stats_err("Failed to register stats event cb");
1563
1564 ret_val = wmi_unified_register_event_handler(wmi_handle,
1565 wmi_peer_stats_info_event_id,
1566 target_if_mc_cp_stats_peer_stats_info_event_handler,
1567 WMI_RX_WORK_CTX);
1568 if (QDF_IS_STATUS_ERROR(ret_val))
1569 cp_stats_err("Failed to register peer stats info event cb");
1570
1571 ret_val = target_if_register_big_data_event_handler(wmi_handle);
1572 if (QDF_IS_STATUS_ERROR(ret_val))
1573 cp_stats_err("Failed to register big data stats info event cb");
1574
1575 ret_val = target_if_register_inst_rssi_event_handler(wmi_handle);
1576 if (QDF_IS_STATUS_ERROR(ret_val))
1577 cp_stats_err("Failed to register inst rssi stats event cb");
1578
1579 return ret_val;
1580 }
1581
1582 static QDF_STATUS
target_if_mc_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc * psoc)1583 target_if_mc_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
1584 {
1585 struct wmi_unified *wmi_handle;
1586
1587 if (!psoc) {
1588 cp_stats_err("PSOC is NULL!");
1589 return QDF_STATUS_E_INVAL;
1590 }
1591
1592 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1593 if (!wmi_handle) {
1594 cp_stats_err("wmi_handle is null");
1595 return QDF_STATUS_E_INVAL;
1596 }
1597
1598 target_if_unregister_inst_rssi_event_handler(wmi_handle);
1599 target_if_unregister_big_data_event_handler(wmi_handle);
1600
1601 wmi_unified_unregister_event_handler(wmi_handle,
1602 wmi_peer_stats_info_event_id);
1603 wmi_unified_unregister_event_handler(wmi_handle,
1604 wmi_update_stats_event_id);
1605
1606 return QDF_STATUS_SUCCESS;
1607 }
1608
get_stats_id(enum stats_req_type type)1609 static uint32_t get_stats_id(enum stats_req_type type)
1610 {
1611 switch (type) {
1612 default:
1613 break;
1614 case TYPE_CONNECTION_TX_POWER:
1615 return WMI_REQUEST_PDEV_STAT | WMI_REQUEST_VDEV_EXTD_STAT;
1616 case TYPE_CONGESTION_STATS:
1617 return WMI_REQUEST_PDEV_STAT | WMI_REQUEST_PDEV_EXTD_STAT;
1618 case TYPE_PEER_STATS:
1619 return WMI_REQUEST_PEER_STAT | WMI_REQUEST_PEER_EXTD_STAT;
1620 case TYPE_STATION_STATS:
1621 return (WMI_REQUEST_AP_STAT |
1622 WMI_REQUEST_PEER_STAT |
1623 WMI_REQUEST_VDEV_STAT |
1624 WMI_REQUEST_VDEV_EXTD_STAT |
1625 WMI_REQUEST_PDEV_STAT |
1626 WMI_REQUEST_PEER_EXTD2_STAT |
1627 WMI_REQUEST_RSSI_PER_CHAIN_STAT |
1628 WMI_REQUEST_PMF_BCN_PROTECT_STAT);
1629 case TYPE_MIB_STATS:
1630 return (WMI_REQUEST_MIB_STAT | WMI_REQUEST_MIB_EXTD_STAT);
1631 }
1632
1633 return 0;
1634 }
1635
1636 /**
1637 * target_if_cp_stats_send_stats_req() - API to send stats request to wmi
1638 * @psoc: pointer to psoc object
1639 * @type: Type of stats requested
1640 * @req: pointer to object containing stats request parameters
1641 *
1642 * Return: status of operation.
1643 */
target_if_cp_stats_send_stats_req(struct wlan_objmgr_psoc * psoc,enum stats_req_type type,struct request_info * req)1644 static QDF_STATUS target_if_cp_stats_send_stats_req(
1645 struct wlan_objmgr_psoc *psoc,
1646 enum stats_req_type type,
1647 struct request_info *req)
1648
1649 {
1650 struct wmi_unified *wmi_handle;
1651 struct stats_request_params param = {0};
1652
1653 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1654 if (!wmi_handle) {
1655 cp_stats_err("wmi_handle is null.");
1656 return QDF_STATUS_E_NULL_VALUE;
1657 }
1658
1659 /* refer (WMI_REQUEST_STATS_CMDID) */
1660 param.stats_id = get_stats_id(type);
1661 param.vdev_id = req->vdev_id;
1662 param.pdev_id = req->pdev_id;
1663
1664 /* only very frequent periodic stats needs to go over QMI.
1665 * for that, wlan_hdd_qmi_get_sync_resume/wlan_hdd_qmi_put_suspend
1666 * needs to be called to cover the period between qmi send and
1667 * qmi response.
1668 */
1669 if (TYPE_STATION_STATS == type)
1670 param.is_qmi_send_support = true;
1671
1672 return wmi_unified_stats_request_send(wmi_handle, req->peer_mac_addr,
1673 ¶m);
1674 }
1675
1676 /**
1677 * target_if_set_pdev_stats_update_period(): API to set pdev stats update
1678 * period to FW
1679 * @psoc: pointer to psoc object
1680 * @pdev_id: pdev id
1681 * @val: pdev stats update period, 0: disabled periodical stats report.
1682 *
1683 * Return: status of operation
1684 */
1685 static QDF_STATUS
target_if_set_pdev_stats_update_period(struct wlan_objmgr_psoc * psoc,uint8_t pdev_id,uint32_t val)1686 target_if_set_pdev_stats_update_period(struct wlan_objmgr_psoc *psoc,
1687 uint8_t pdev_id, uint32_t val)
1688 {
1689 struct wmi_unified *wmi_handle;
1690 struct pdev_params pdev_param = {0};
1691
1692 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1693
1694 if (!wmi_handle) {
1695 cp_stats_err("wmi_handle is null");
1696 return QDF_STATUS_E_INVAL;
1697 }
1698
1699 pdev_param.param_id = wmi_pdev_param_pdev_stats_update_period;
1700 pdev_param.param_value = val;
1701 return wmi_unified_pdev_param_send(wmi_handle,
1702 &pdev_param,
1703 pdev_id);
1704 }
1705
1706 /**
1707 * target_if_mc_cp_stats_unregister_handlers() - Unregisters wmi event handlers
1708 * of control plane stats & twt session stats info
1709 * @psoc: PSOC object
1710 *
1711 * Return: QDF_STATUS_SUCCESS on success or QDF error values on failure
1712 */
1713 static QDF_STATUS
target_if_mc_cp_stats_unregister_handlers(struct wlan_objmgr_psoc * psoc)1714 target_if_mc_cp_stats_unregister_handlers(struct wlan_objmgr_psoc *psoc)
1715 {
1716 QDF_STATUS qdf_status;
1717
1718 qdf_status = target_if_twt_session_params_unregister_evt_hdlr(psoc);
1719 if (qdf_status == QDF_STATUS_SUCCESS)
1720 qdf_status =
1721 target_if_mc_cp_stats_unregister_event_handler(psoc);
1722
1723 return qdf_status;
1724 }
1725
1726 /**
1727 * target_if_mc_cp_stats_register_handlers() - Registers wmi event handlers for
1728 * control plane stats & twt session stats info
1729 * @psoc: PSOC object
1730 *
1731 * Return: QDF_STATUS_SUCCESS on success or QDF error values on failure
1732 */
1733 static QDF_STATUS
target_if_mc_cp_stats_register_handlers(struct wlan_objmgr_psoc * psoc)1734 target_if_mc_cp_stats_register_handlers(struct wlan_objmgr_psoc *psoc)
1735 {
1736 QDF_STATUS qdf_status;
1737
1738 qdf_status = target_if_mc_cp_stats_register_event_handler(psoc);
1739 if (qdf_status != QDF_STATUS_SUCCESS)
1740 return qdf_status;
1741
1742 qdf_status = target_if_twt_session_params_register_evt_hdlr(psoc);
1743 if (qdf_status != QDF_STATUS_SUCCESS)
1744 target_if_mc_cp_stats_unregister_event_handler(psoc);
1745
1746 return qdf_status;
1747 }
1748
1749 /**
1750 * target_if_cp_stats_send_peer_stats_req() - API to send peer stats request
1751 * to wmi
1752 * @psoc: pointer to psoc object
1753 * @req: pointer to object containing peer stats request parameters
1754 *
1755 * Return: status of operation.
1756 */
1757 static QDF_STATUS
target_if_cp_stats_send_peer_stats_req(struct wlan_objmgr_psoc * psoc,struct request_info * req)1758 target_if_cp_stats_send_peer_stats_req(struct wlan_objmgr_psoc *psoc,
1759 struct request_info *req)
1760
1761 {
1762 struct wmi_unified *wmi_handle;
1763 struct peer_stats_request_params param = {0};
1764
1765 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
1766 if (!wmi_handle) {
1767 cp_stats_err("wmi_handle is null.");
1768 return QDF_STATUS_E_NULL_VALUE;
1769 }
1770 param.request_type = WMI_REQUEST_ONE_PEER_STATS_INFO;
1771 param.vdev_id = req->vdev_id;
1772 qdf_mem_copy(param.peer_mac_addr, req->peer_mac_addr,
1773 QDF_MAC_ADDR_SIZE);
1774 param.reset_after_request = 0;
1775
1776 return wmi_unified_peer_stats_request_send(wmi_handle, ¶m);
1777 }
1778
1779 static QDF_STATUS
target_if_mc_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)1780 target_if_mc_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
1781 {
1782 struct wlan_lmac_if_cp_stats_tx_ops *cp_stats_tx_ops;
1783
1784 if (!tx_ops) {
1785 cp_stats_err("lmac tx ops is NULL!");
1786 return QDF_STATUS_E_INVAL;
1787 }
1788
1789 cp_stats_tx_ops = &tx_ops->cp_stats_tx_ops;
1790 if (!cp_stats_tx_ops) {
1791 cp_stats_err("lmac tx ops is NULL!");
1792 return QDF_STATUS_E_FAILURE;
1793 }
1794
1795 cp_stats_tx_ops->inc_wake_lock_stats =
1796 target_if_cp_stats_inc_wake_lock_stats;
1797 cp_stats_tx_ops->send_req_stats = target_if_cp_stats_send_stats_req;
1798 cp_stats_tx_ops->set_pdev_stats_update_period =
1799 target_if_set_pdev_stats_update_period;
1800 cp_stats_tx_ops->send_req_peer_stats =
1801 target_if_cp_stats_send_peer_stats_req;
1802
1803 target_if_big_data_stats_register_tx_ops(cp_stats_tx_ops);
1804
1805 return QDF_STATUS_SUCCESS;
1806 }
1807
1808 static QDF_STATUS
target_if_mc_cp_stats_unregister_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)1809 target_if_mc_cp_stats_unregister_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
1810 {
1811 struct wlan_lmac_if_cp_stats_tx_ops *cp_stats_tx_ops;
1812
1813 if (!tx_ops) {
1814 cp_stats_err("lmac tx ops is NULL!");
1815 return QDF_STATUS_E_INVAL;
1816 }
1817
1818 cp_stats_tx_ops = &tx_ops->cp_stats_tx_ops;
1819 if (!cp_stats_tx_ops) {
1820 cp_stats_err("lmac tx ops is NULL!");
1821 return QDF_STATUS_E_FAILURE;
1822 }
1823
1824 target_if_big_data_stats_unregister_tx_ops(cp_stats_tx_ops);
1825 cp_stats_tx_ops->inc_wake_lock_stats = NULL;
1826 cp_stats_tx_ops->send_req_stats = NULL;
1827 cp_stats_tx_ops->set_pdev_stats_update_period = NULL;
1828 cp_stats_tx_ops->send_req_peer_stats = NULL;
1829
1830 return QDF_STATUS_SUCCESS;
1831 }
1832
1833 #ifdef WLAN_SUPPORT_LEGACY_CP_STATS_HANDLERS
1834 QDF_STATUS
target_if_cp_stats_register_legacy_event_handler(struct wlan_objmgr_psoc * psoc)1835 target_if_cp_stats_register_legacy_event_handler(struct wlan_objmgr_psoc *psoc)
1836 {
1837 QDF_STATUS status;
1838 struct wlan_lmac_if_tx_ops *tx_ops;
1839
1840 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
1841 if (!tx_ops) {
1842 cp_stats_err("lmac tx ops is NULL!");
1843 return QDF_STATUS_E_FAILURE;
1844 }
1845
1846 status = target_if_mc_cp_stats_register_tx_ops(tx_ops);
1847 if (QDF_IS_STATUS_ERROR(status))
1848 return status;
1849
1850 return target_if_mc_cp_stats_register_handlers(psoc);
1851 }
1852
1853 QDF_STATUS
target_if_cp_stats_unregister_legacy_event_handler(struct wlan_objmgr_psoc * psoc)1854 target_if_cp_stats_unregister_legacy_event_handler(
1855 struct wlan_objmgr_psoc *psoc)
1856 {
1857 QDF_STATUS status;
1858 struct wlan_lmac_if_tx_ops *tx_ops;
1859
1860 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
1861 if (!tx_ops) {
1862 cp_stats_err("lmac tx ops is NULL!");
1863 return QDF_STATUS_E_FAILURE;
1864 }
1865
1866 status = target_if_mc_cp_stats_unregister_tx_ops(tx_ops);
1867 if (QDF_IS_STATUS_ERROR(status))
1868 return status;
1869
1870 return target_if_mc_cp_stats_unregister_handlers(psoc);
1871 }
1872 #endif
1873