1 /*
2 * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include "osdep.h"
19 #include "wmi.h"
20 #include "wmi_unified_priv.h"
21 #include "wmi_unified_param.h"
22 #include "target_if_cp_stats.h"
23 #include <wlan_cp_stats_public_structs.h>
24
25 #if defined(WLAN_SUPPORT_INFRA_CTRL_PATH_STATS) || \
26 defined(WLAN_CONFIG_TELEMETRY_AGENT)
27 /**
28 * get_infra_cp_stats_id() - convert from to wmi_ctrl_path_stats_id
29 * @type: type from enum infra_cp_stats_id
30 *
31 * Return: wmi_ctrl_path_stats_id code for success or -EINVAL
32 * for failure
33 */
get_infra_cp_stats_id(enum infra_cp_stats_id type)34 static uint32_t get_infra_cp_stats_id(enum infra_cp_stats_id type)
35 {
36 switch (type) {
37 case TYPE_REQ_CTRL_PATH_PDEV_TX_STAT:
38 return WMI_REQUEST_CTRL_PATH_PDEV_TX_STAT;
39 case TYPE_REQ_CTRL_PATH_VDEV_EXTD_STAT:
40 return WMI_REQUEST_CTRL_PATH_VDEV_EXTD_STAT;
41 case TYPE_REQ_CTRL_PATH_MEM_STAT:
42 return WMI_REQUEST_CTRL_PATH_MEM_STAT;
43 case TYPE_REQ_CTRL_PATH_TWT_STAT:
44 return WMI_REQUEST_CTRL_PATH_TWT_STAT;
45 case TYPE_REQ_CTRL_PATH_BMISS_STAT:
46 return WMI_REQUEST_CTRL_PATH_BMISS_STAT;
47 case TYPE_REQ_CTRL_PATH_PMLO_STAT:
48 return WMI_REQUEST_CTRL_PATH_PMLO_STAT;
49 case TYPE_REQ_CTRL_PATH_RRM_STA_STAT:
50 return WMI_REQUEST_CTRL_STA_RRM_STAT;
51 default:
52 return -EINVAL;
53 }
54 }
55
56 /**
57 * get_infra_cp_stats_action() - convert action codes from
58 * enum infra_cp_stats_action to wmi_ctrl_path_stats_action
59 * @action: action code from enum infra_cp_stats_action
60 *
61 * Return: wmi_ctrl_path_stats_action code for success or -EINVAL
62 * for failure
63 */
get_infra_cp_stats_action(enum infra_cp_stats_action action)64 static uint32_t get_infra_cp_stats_action(enum infra_cp_stats_action action)
65 {
66 switch (action) {
67 case ACTION_REQ_CTRL_PATH_STAT_GET:
68 return WMI_REQUEST_CTRL_PATH_STAT_GET;
69 case ACTION_REQ_CTRL_PATH_STAT_RESET:
70 return WMI_REQUEST_CTRL_PATH_STAT_RESET;
71 case ACTION_REQ_CTRL_PATH_STAT_START:
72 return WMI_REQUEST_CTRL_PATH_STAT_START;
73 case ACTION_REQ_CTRL_PATH_STAT_STOP:
74 return WMI_REQUEST_CTRL_PATH_STAT_STOP;
75 case ACTION_REQ_CTRL_PATH_STAT_PERIODIC_PUBLISH:
76 return WMI_REQUEST_CTRL_PATH_STAT_PERIODIC_PUBLISH;
77 default:
78 return -EINVAL;
79 }
80 }
81
82 #ifdef WLAN_SUPPORT_TWT
83 static uint32_t
get_stats_req_twt_dialog_id(struct infra_cp_stats_cmd_info * req)84 get_stats_req_twt_dialog_id(struct infra_cp_stats_cmd_info *req)
85 {
86 return req->dialog_id;
87 }
88
89 static enum WMI_HOST_GET_STATS_TWT_STATUS
wmi_get_converted_twt_get_stats_status(WMI_GET_STATS_TWT_STATUS_T tgt_status)90 wmi_get_converted_twt_get_stats_status(WMI_GET_STATS_TWT_STATUS_T tgt_status)
91 {
92 switch (tgt_status) {
93 case WMI_GET_STATS_TWT_STATUS_OK:
94 return WMI_HOST_GET_STATS_TWT_STATUS_OK;
95 case WMI_GET_STATS_TWT_STATUS_DIALOG_ID_NOT_EXIST:
96 return WMI_HOST_GET_STATS_TWT_STATUS_DIALOG_ID_NOT_EXIST;
97 case WMI_GET_STATS_TWT_STATUS_INVALID_PARAM:
98 return WMI_HOST_GET_STATS_TWT_STATUS_INVALID_PARAM;
99 default:
100 return WMI_HOST_GET_STATS_TWT_STATUS_UNKNOWN_ERROR;
101 }
102 }
103
104 static inline
wmi_extract_ctrl_path_twt_stats_tlv(void * tag_buf,struct twt_infra_cp_stats_event * param)105 void wmi_extract_ctrl_path_twt_stats_tlv(void *tag_buf,
106 struct twt_infra_cp_stats_event *param)
107 {
108 wmi_ctrl_path_twt_stats_struct *wmi_stats_buf =
109 (wmi_ctrl_path_twt_stats_struct *)tag_buf;
110
111 param->dialog_id = wmi_stats_buf->dialog_id;
112 param->status = wmi_get_converted_twt_get_stats_status(wmi_stats_buf->status);
113 param->num_sp_cycles = wmi_stats_buf->num_sp_cycles;
114 param->avg_sp_dur_us = wmi_stats_buf->avg_sp_dur_us;
115 param->min_sp_dur_us = wmi_stats_buf->min_sp_dur_us;
116 param->max_sp_dur_us = wmi_stats_buf->max_sp_dur_us;
117 param->tx_mpdu_per_sp = wmi_stats_buf->tx_mpdu_per_sp;
118 param->rx_mpdu_per_sp = wmi_stats_buf->rx_mpdu_per_sp;
119 param->tx_bytes_per_sp = wmi_stats_buf->tx_bytes_per_sp;
120 param->rx_bytes_per_sp = wmi_stats_buf->rx_bytes_per_sp;
121
122 wmi_debug("dialog_id = %u status = %u", wmi_stats_buf->dialog_id,
123 wmi_stats_buf->status);
124 wmi_debug("num_sp_cycles = %u avg_sp_dur_us = 0x%x, \
125 min_sp_dur_us = 0x%x, max_sp_dur_us = 0x%x",
126 wmi_stats_buf->num_sp_cycles, wmi_stats_buf->avg_sp_dur_us,
127 wmi_stats_buf->min_sp_dur_us, wmi_stats_buf->max_sp_dur_us);
128 wmi_debug("tx_mpdu_per_sp 0x%x, rx_mpdu_per_sp = 0x%x, \
129 tx_bytes_per_sp = 0x%x, rx_bytes_per_sp = 0x%x",
130 wmi_stats_buf->tx_mpdu_per_sp, wmi_stats_buf->rx_mpdu_per_sp,
131 wmi_stats_buf->tx_bytes_per_sp,
132 wmi_stats_buf->rx_bytes_per_sp);
133 }
134
wmi_twt_extract_stats_struct(void * tag_buf,struct infra_cp_stats_event * params)135 static void wmi_twt_extract_stats_struct(void *tag_buf,
136 struct infra_cp_stats_event *params)
137 {
138 struct twt_infra_cp_stats_event *twt_params;
139
140 twt_params = params->twt_infra_cp_stats +
141 params->num_twt_infra_cp_stats;
142
143 wmi_debug("TWT stats struct found - num_twt_cp_stats %d",
144 params->num_twt_infra_cp_stats);
145
146 params->num_twt_infra_cp_stats++;
147 wmi_extract_ctrl_path_twt_stats_tlv(tag_buf, twt_params);
148 }
149 #else
150 static inline
get_stats_req_twt_dialog_id(struct infra_cp_stats_cmd_info * req)151 uint32_t get_stats_req_twt_dialog_id(struct infra_cp_stats_cmd_info *req)
152 {
153 return 0;
154 }
155
wmi_twt_extract_stats_struct(void * tag_buf,struct infra_cp_stats_event * params)156 static void wmi_twt_extract_stats_struct(void *tag_buf,
157 struct infra_cp_stats_event *params)
158 {
159 }
160 #endif /* WLAN_SUPPORT_TWT */
161
162 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
163 static void
wmi_extract_ctrl_path_rrm_sta_stats_tlv(void * tag_buf,struct cp_sta_stats * param)164 wmi_extract_ctrl_path_rrm_sta_stats_tlv(void *tag_buf,
165 struct cp_sta_stats *param)
166 {
167 wmi_ctrl_path_sta_rrm_stats_struct *wmi_stats_buf =
168 (wmi_ctrl_path_sta_rrm_stats_struct *)tag_buf;
169 param->group.counter_stats.group_transmitted_frame_count =
170 wmi_stats_buf->dot11GroupTransmittedFrameCount;
171 param->group.counter_stats.group_received_frame_count =
172 wmi_stats_buf->dot11GroupReceivedFrameCount;
173 param->group.counter_stats.transmitted_frame_count =
174 wmi_stats_buf->dot11TransmittedFrameCount;
175 param->group.mac_stats.ack_failure_count =
176 wmi_stats_buf->dot11AckFailureCount;
177 param->group.counter_stats.failed_count =
178 wmi_stats_buf->dot11FailedCount;
179 param->group.counter_stats.fcs_error_count =
180 wmi_stats_buf->dot11FCSErrorCount;
181 param->group.mac_stats.rts_success_count =
182 wmi_stats_buf->dot11RTSSuccessCount;
183 param->group.mac_stats.rts_failure_count =
184 wmi_stats_buf->dot11RTSFailureCount;
185 }
186
187 static void
wmi_rrm_extract_sta_stats_struct(void * tag_buf,struct infra_cp_stats_event * params)188 wmi_rrm_extract_sta_stats_struct(void *tag_buf,
189 struct infra_cp_stats_event *params)
190 {
191 struct cp_sta_stats *rrm_sta_stats;
192
193 rrm_sta_stats = params->sta_stats;
194 wmi_extract_ctrl_path_rrm_sta_stats_tlv(tag_buf, rrm_sta_stats);
195 }
196 #else
197 static inline void
wmi_rrm_extract_sta_stats_struct(void * tag_buf,struct infra_cp_stats_event * params)198 wmi_rrm_extract_sta_stats_struct(void *tag_buf,
199 struct infra_cp_stats_event *params)
200 {}
201 #endif
202
203 #ifdef CONFIG_WLAN_BMISS
204 static void
wmi_extract_ctrl_path_bmiss_stats_tlv(void * tag_buf,struct bmiss_infra_cp_stats_event * param)205 wmi_extract_ctrl_path_bmiss_stats_tlv(void *tag_buf,
206 struct bmiss_infra_cp_stats_event *param)
207 {
208 int idx = 0;
209
210 wmi_ctrl_path_bmiss_stats_struct *wmi_stats_buf =
211 (wmi_ctrl_path_bmiss_stats_struct *)tag_buf;
212 param->num_pre_bmiss = wmi_stats_buf->num_pre_bmiss;
213 for (idx = 0; idx < BMISS_STATS_RSSI_SAMPLES_MAX; idx++) {
214 param->rssi_samples[idx].rssi =
215 wmi_stats_buf->rssi_samples[idx].rssi;
216 param->rssi_samples[idx].sample_time =
217 wmi_stats_buf->rssi_samples[idx].sample_time;
218 }
219 param->rssi_sample_curr_index = wmi_stats_buf->rssi_sample_curr_index;
220 param->num_first_bmiss = wmi_stats_buf->num_first_bmiss;
221 param->num_final_bmiss = wmi_stats_buf->num_final_bmiss;
222 param->num_null_sent_in_first_bmiss =
223 wmi_stats_buf->num_null_sent_in_first_bmiss;
224 param->num_null_failed_in_first_bmiss =
225 wmi_stats_buf->num_null_failed_in_first_bmiss;
226 param->num_null_failed_in_final_bmiss =
227 wmi_stats_buf->num_null_failed_in_final_bmiss;
228 param->cons_bmiss_stats.num_of_bmiss_sequences =
229 wmi_stats_buf->cons_bmiss_stats.num_of_bmiss_sequences;
230 param->cons_bmiss_stats.num_bitmask_wraparound =
231 wmi_stats_buf->cons_bmiss_stats.num_bitmask_wraparound;
232 param->cons_bmiss_stats.num_bcn_hist_lost =
233 wmi_stats_buf->cons_bmiss_stats.num_bcn_hist_lost;
234 wmi_debug("num_pre_bmiss = %u", wmi_stats_buf->num_pre_bmiss);
235 wmi_debug("num_first_bmiss = %u num_final_bmiss = %u, num_null_sent_in_first_bmiss = %u, num_null_failed_in_first_bmiss = %u",
236 wmi_stats_buf->num_first_bmiss,
237 wmi_stats_buf->num_final_bmiss,
238 wmi_stats_buf->num_null_sent_in_first_bmiss,
239 wmi_stats_buf->num_null_failed_in_first_bmiss);
240 wmi_debug("num_null_sent_in_final_bmiss %u null_fail_cnt_final_bmiss = %u rssi_sample_curr_index = %u",
241 wmi_stats_buf->num_null_sent_in_final_bmiss,
242 wmi_stats_buf->num_null_failed_in_final_bmiss,
243 wmi_stats_buf->rssi_sample_curr_index);
244 for (idx = 0; idx < BMISS_STATS_RSSI_SAMPLES_MAX; idx++) {
245 wmi_debug("rssi_sample-%u: rssi=%u", idx,
246 wmi_stats_buf->rssi_samples[idx].rssi);
247 wmi_debug("rssi_sample-%u: sampletime=%u", idx,
248 wmi_stats_buf->rssi_samples[idx].sample_time);
249 }
250 wmi_debug("num_of_bmiss_sequences %u num_bitmask_wraparound = %u num_bcn_hist_lost = %u",
251 wmi_stats_buf->cons_bmiss_stats.num_of_bmiss_sequences,
252 wmi_stats_buf->cons_bmiss_stats.num_bitmask_wraparound,
253 wmi_stats_buf->cons_bmiss_stats.num_bcn_hist_lost);
254 }
255
wmi_bmiss_extract_stats_struct(void * tag_buf,struct infra_cp_stats_event * params)256 static void wmi_bmiss_extract_stats_struct(void *tag_buf,
257 struct infra_cp_stats_event *params)
258 {
259 struct bmiss_infra_cp_stats_event *bmiss_params;
260
261 bmiss_params = params->bmiss_infra_cp_stats;
262 wmi_debug("BMISS stats struct found");
263 wmi_extract_ctrl_path_bmiss_stats_tlv(tag_buf, bmiss_params);
264 }
265
266 #else /* CONFIG_WLAN_BMISS */
267 static inline
wmi_bmiss_extract_stats_struct(void * tag_buf,struct infra_cp_stats_event * params)268 void wmi_bmiss_extract_stats_struct(void *tag_buf,
269 struct infra_cp_stats_event *params)
270
271 {
272 }
273
274 #endif/* CONFIG_WLAN_BMISS */
275
276 #ifdef WLAN_CONFIG_TELEMETRY_AGENT
277 static void
wmi_extract_ctrl_path_pmlo_stats_tlv(wmi_unified_t wmi_handle,void * tag_buf,struct ctrl_path_pmlo_telemetry_stats_struct * param)278 wmi_extract_ctrl_path_pmlo_stats_tlv(wmi_unified_t wmi_handle, void *tag_buf,
279 struct ctrl_path_pmlo_telemetry_stats_struct *param)
280 {
281 int idx = 0;
282 wmi_ctrl_path_pmlo_stats_struct *wmi_stats_buf = tag_buf;
283
284 param->pdev_id =
285 wmi_handle->ops->convert_target_pdev_id_to_host(wmi_handle,
286 wmi_stats_buf->pdev_id);
287 param->dl_inbss_airtime_ac_be =
288 WMI_PMLO_UL_DL_INBSS_AT_GET_BE(wmi_stats_buf->dl_inbss_airtime_per_ac);
289 param->dl_inbss_airtime_ac_bk =
290 WMI_PMLO_UL_DL_INBSS_AT_GET_BK(wmi_stats_buf->dl_inbss_airtime_per_ac);
291 param->dl_inbss_airtime_ac_vi =
292 WMI_PMLO_UL_DL_INBSS_AT_GET_VI(wmi_stats_buf->dl_inbss_airtime_per_ac);
293 param->dl_inbss_airtime_ac_vo =
294 WMI_PMLO_UL_DL_INBSS_AT_GET_VO(wmi_stats_buf->dl_inbss_airtime_per_ac);
295 param->ul_inbss_airtime_ac_be =
296 WMI_PMLO_UL_DL_INBSS_AT_GET_BE(wmi_stats_buf->ul_inbss_airtime_per_ac);
297 param->ul_inbss_airtime_ac_bk =
298 WMI_PMLO_UL_DL_INBSS_AT_GET_BK(wmi_stats_buf->ul_inbss_airtime_per_ac);
299 param->ul_inbss_airtime_ac_vi =
300 WMI_PMLO_UL_DL_INBSS_AT_GET_VI(wmi_stats_buf->ul_inbss_airtime_per_ac);
301 param->ul_inbss_airtime_ac_vo =
302 WMI_PMLO_UL_DL_INBSS_AT_GET_VO(wmi_stats_buf->ul_inbss_airtime_per_ac);
303 param->estimated_air_time_ac_be =
304 WMI_PMLO_UL_DL_INBSS_AT_GET_BE(wmi_stats_buf->estimated_air_time_per_ac);
305 param->estimated_air_time_ac_bk =
306 WMI_PMLO_UL_DL_INBSS_AT_GET_BK(wmi_stats_buf->estimated_air_time_per_ac);
307 param->estimated_air_time_ac_vi =
308 WMI_PMLO_UL_DL_INBSS_AT_GET_VI(wmi_stats_buf->estimated_air_time_per_ac);
309 param->estimated_air_time_ac_vo =
310 WMI_PMLO_UL_DL_INBSS_AT_GET_VO(wmi_stats_buf->estimated_air_time_per_ac);
311 param->link_obss_airtime =
312 WMI_PMLO_LINK_OBSS_AT_GET(wmi_stats_buf->ul_dl_obss_free_aa_word32);
313 param->link_idle_airtime =
314 WMI_PMLO_LINK_AA_GET(wmi_stats_buf->ul_dl_obss_free_aa_word32);
315 param->ul_inbss_airtime_non_ac =
316 WMI_PMLO_UL_AIRTIME_NON_AC_GET(wmi_stats_buf->ul_dl_obss_free_aa_word32);
317 param->dl_inbss_airtime_non_ac =
318 WMI_PMLO_DL_AIRTIME_NON_AC_GET(wmi_stats_buf->ul_dl_obss_free_aa_word32);
319 for (idx = 0; idx < WMI_AC_MAX; idx++) {
320 param->avg_chan_lat_per_ac[idx] =
321 wmi_stats_buf->avg_chan_lat_per_ac[idx];
322 }
323
324 wmi_debug("pdev_id = %u", wmi_stats_buf->pdev_id);
325 wmi_debug("dl_inbss_airtime_per_ac = %u, ul_inbss_airtime_per_ac = %u, estimated_air_time_per_ac = %u, ul_dl_obss_free_aa_word32 = %u",
326 wmi_stats_buf->dl_inbss_airtime_per_ac,
327 wmi_stats_buf->ul_inbss_airtime_per_ac,
328 wmi_stats_buf->estimated_air_time_per_ac,
329 wmi_stats_buf->ul_dl_obss_free_aa_word32);
330
331 for (idx = 0; idx < WMI_AC_MAX; idx++) {
332 wmi_debug("avg_chan_lat_per_ac_sample-%u: avg_chan_lat_per_ac=%u",
333 idx,
334 wmi_stats_buf->avg_chan_lat_per_ac[idx]);
335 }
336 }
337
wmi_pmlo_extract_stats_struct(wmi_unified_t wmi_handle,void * tag_buf,struct infra_cp_stats_event * params)338 static void wmi_pmlo_extract_stats_struct(wmi_unified_t wmi_handle,
339 void *tag_buf,
340 struct infra_cp_stats_event *params)
341 {
342 struct ctrl_path_pmlo_telemetry_stats_struct *pmlo_params;
343
344 pmlo_params = params->telemetry_stats;
345 wmi_debug("PMLO TELEMETRY stats struct found");
346 wmi_extract_ctrl_path_pmlo_stats_tlv(wmi_handle, tag_buf, pmlo_params);
347 }
348 #else
wmi_pmlo_extract_stats_struct(wmi_unified_t wmi_handle,void * tag_buf,struct infra_cp_stats_event * params)349 static void wmi_pmlo_extract_stats_struct(wmi_unified_t wmi_handle,
350 void *tag_buf,
351 struct infra_cp_stats_event *params)
352 { }
353 #endif
354
355 /**
356 * wmi_stats_extract_tag_struct: function to extract tag structs
357 * @wmi_handle: wmi handle
358 * @tag_type: tag type that is to be printed
359 * @tag_buf: pointer to the tag structure
360 * @params: buffer to hold parameters extracted from response event
361 *
362 * Return: None
363 */
wmi_stats_extract_tag_struct(wmi_unified_t wmi_handle,uint32_t tag_type,void * tag_buf,struct infra_cp_stats_event * params)364 static void wmi_stats_extract_tag_struct(wmi_unified_t wmi_handle,
365 uint32_t tag_type, void *tag_buf,
366 struct infra_cp_stats_event *params)
367 {
368 wmi_debug("tag_type %d", tag_type);
369
370 switch (tag_type) {
371 case WMITLV_TAG_STRUC_wmi_ctrl_path_pdev_stats_struct:
372 break;
373
374 case WMITLV_TAG_STRUC_wmi_ctrl_path_mem_stats_struct:
375 break;
376
377 case WMITLV_TAG_STRUC_wmi_ctrl_path_twt_stats_struct:
378 wmi_twt_extract_stats_struct(tag_buf, params);
379 break;
380
381 case WMITLV_TAG_STRUC_wmi_ctrl_path_bmiss_stats_struct:
382 wmi_bmiss_extract_stats_struct(tag_buf, params);
383 break;
384
385 case WMITLV_TAG_STRUC_wmi_ctrl_path_pmlo_stats_struct:
386 wmi_pmlo_extract_stats_struct(wmi_handle, tag_buf, params);
387 break;
388
389 case WMITLV_TAG_STRUC_wmi_ctrl_path_sta_rrm_stats_struct:
390 wmi_rrm_extract_sta_stats_struct(tag_buf, params);
391 break;
392
393 default:
394 break;
395 }
396 }
397
wmi_stats_handler(wmi_unified_t wmi_handle,void * buff,int32_t len,struct infra_cp_stats_event * params)398 QDF_STATUS wmi_stats_handler(wmi_unified_t wmi_handle, void *buff, int32_t len,
399 struct infra_cp_stats_event *params)
400 {
401 WMI_CTRL_PATH_STATS_EVENTID_param_tlvs *param_buf;
402 wmi_ctrl_path_stats_event_fixed_param *ev;
403 uint8_t *buf_ptr = (uint8_t *)buff;
404 uint32_t curr_tlv_tag;
405 uint32_t curr_tlv_len;
406 uint8_t *tag_start_ptr;
407
408 param_buf = (WMI_CTRL_PATH_STATS_EVENTID_param_tlvs *)buff;
409 if (!param_buf) {
410 wmi_err_rl("param_buf is NULL");
411 return QDF_STATUS_E_FAILURE;
412 }
413 ev = (wmi_ctrl_path_stats_event_fixed_param *)param_buf->fixed_param;
414
415 curr_tlv_tag = WMITLV_GET_TLVTAG(ev->tlv_header);
416 curr_tlv_len = WMITLV_GET_TLVLEN(ev->tlv_header);
417 buf_ptr = (uint8_t *)param_buf->fixed_param;
418 wmi_debug("Fixed param more %d req_id %d status %d", ev->more,
419 ev->request_id, ev->status);
420 params->request_id = ev->request_id;
421 params->status = ev->status;
422
423 /* buffer should point to next TLV in event */
424 buf_ptr += (curr_tlv_len + WMI_TLV_HDR_SIZE);
425 len -= (curr_tlv_len + WMI_TLV_HDR_SIZE);
426
427 curr_tlv_tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(buf_ptr));
428 curr_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr));
429
430 wmi_debug("curr_tlv_len %d curr_tlv_tag %d rem_len %d", len,
431 curr_tlv_len, curr_tlv_tag);
432
433 while ((len >= curr_tlv_len) &&
434 (curr_tlv_tag >= WMITLV_TAG_FIRST_ARRAY_ENUM)) {
435 if (curr_tlv_tag == WMITLV_TAG_ARRAY_STRUC) {
436 /* Move to next WMITLV_TAG_ARRAY_STRUC */
437 buf_ptr += WMI_TLV_HDR_SIZE;
438 len -= WMI_TLV_HDR_SIZE;
439 if (len <= 0)
440 break;
441 }
442 curr_tlv_tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(buf_ptr));
443 curr_tlv_len = WMITLV_GET_TLVLEN(WMITLV_GET_HDR(buf_ptr));
444
445 wmi_debug("curr_tlv_len %d curr_tlv_tag %d rem_len %d",
446 len, curr_tlv_len, curr_tlv_tag);
447 if (curr_tlv_len) {
448 /* point to the tag inside WMITLV_TAG_ARRAY_STRUC */
449 tag_start_ptr = buf_ptr + WMI_TLV_HDR_SIZE;
450 curr_tlv_tag = WMITLV_GET_TLVTAG(
451 WMITLV_GET_HDR(tag_start_ptr));
452 wmi_stats_extract_tag_struct(wmi_handle, curr_tlv_tag,
453 (void *)tag_start_ptr,
454 params);
455 /* Move to next tag */
456 buf_ptr += curr_tlv_len + WMI_TLV_HDR_SIZE;
457 len -= (curr_tlv_len + WMI_TLV_HDR_SIZE);
458 }
459 if (len <= 0)
460 break;
461 }
462
463 return QDF_STATUS_SUCCESS;
464 }
465
466 /**
467 * extract_infra_cp_stats_tlv - api to extract stats information from
468 * event buffer
469 * @wmi_handle: wmi handle
470 * @evt_buf: event buffer
471 * @evt_buf_len: length of the event buffer
472 * @params: buffer to populate more flag
473 *
474 * Return: QDF_STATUS_SUCCESS on success, else other qdf error values
475 */
476 QDF_STATUS
extract_infra_cp_stats_tlv(wmi_unified_t wmi_handle,void * evt_buf,uint32_t evt_buf_len,struct infra_cp_stats_event * params)477 extract_infra_cp_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf,
478 uint32_t evt_buf_len,
479 struct infra_cp_stats_event *params)
480 {
481 wmi_stats_handler(wmi_handle, evt_buf, evt_buf_len, params);
482 return QDF_STATUS_SUCCESS;
483 }
484
485 /**
486 * prepare_infra_cp_stats_buf() - Allocate and prepare wmi cmd request buffer
487 * @wmi_handle: wmi handle
488 * @stats_req: Request parameters to be filled in wmi cmd request buffer
489 * @req_buf_len: length of the output wmi cmd buffer allocated
490 *
491 * Return: Valid wmi buffer pointer on success and NULL pointer for failure
492 */
493 static wmi_buf_t
prepare_infra_cp_stats_buf(wmi_unified_t wmi_handle,struct infra_cp_stats_cmd_info * stats_req,uint32_t * req_buf_len)494 prepare_infra_cp_stats_buf(wmi_unified_t wmi_handle,
495 struct infra_cp_stats_cmd_info *stats_req,
496 uint32_t *req_buf_len)
497 {
498 wmi_request_ctrl_path_stats_cmd_fixed_param *cmd_fixed_param;
499 uint32_t index;
500 wmi_buf_t req_buf;
501 uint8_t *buf_ptr;
502 uint32_t *pdev_id_array;
503 uint32_t *vdev_id_array;
504 uint8_t *mac_addr_array;
505 uint32_t *dialog_id_array;
506 uint32_t num_pdev_ids = stats_req->num_pdev_ids;
507 uint32_t num_vdev_ids = stats_req->num_vdev_ids;
508 uint32_t num_mac_addr_list = stats_req->num_mac_addr_list;
509 uint32_t num_dialog_ids = INFRA_CP_STATS_MAX_REQ_TWT_DIALOG_ID;
510
511 /* Calculate total buffer length */
512 *req_buf_len = (sizeof(wmi_request_ctrl_path_stats_cmd_fixed_param) +
513 WMI_TLV_HDR_SIZE + (sizeof(A_UINT32) * (num_pdev_ids)) +
514 WMI_TLV_HDR_SIZE + sizeof(A_UINT32) * (num_vdev_ids) +
515 WMI_TLV_HDR_SIZE +
516 sizeof(wmi_mac_addr) * (num_mac_addr_list) +
517 WMI_TLV_HDR_SIZE +
518 (sizeof(A_UINT32) * (num_dialog_ids)));
519 req_buf = wmi_buf_alloc(wmi_handle, *req_buf_len);
520 if (!req_buf)
521 return NULL;
522
523 cmd_fixed_param = (wmi_request_ctrl_path_stats_cmd_fixed_param *)
524 wmi_buf_data(req_buf);
525
526 /*Set TLV header*/
527 WMITLV_SET_HDR(&cmd_fixed_param->tlv_header,
528 WMITLV_TAG_STRUC_wmi_request_ctrl_path_stats_cmd_fixed_param,
529 WMITLV_GET_STRUCT_TLVLEN(
530 wmi_request_ctrl_path_stats_cmd_fixed_param));
531
532 index = get_infra_cp_stats_id(stats_req->stats_id);
533 cmd_fixed_param->stats_id_mask = (1 << index);
534
535 cmd_fixed_param->request_id = stats_req->request_id;
536 cmd_fixed_param->action = get_infra_cp_stats_action(stats_req->action);
537 cmd_fixed_param->stat_periodicity = stats_req->stat_periodicity;
538
539 buf_ptr = (uint8_t *)cmd_fixed_param;
540 /* Setting tlv header for pdev id arrays*/
541 buf_ptr = buf_ptr + sizeof(*cmd_fixed_param);
542 pdev_id_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
543 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
544 sizeof(A_UINT32) * num_pdev_ids);
545
546 /* Setting tlv header for vdev id arrays*/
547 buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE +
548 (sizeof(A_UINT32) * num_pdev_ids);
549 vdev_id_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
550 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
551 sizeof(A_UINT32) * num_vdev_ids);
552
553 /* Setting tlv header for mac addr arrays*/
554 buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE +
555 (sizeof(A_UINT32) * num_vdev_ids);
556 mac_addr_array = buf_ptr + WMI_TLV_HDR_SIZE;
557 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
558 sizeof(wmi_mac_addr) * num_mac_addr_list);
559
560 /* Setting tlv header for dialog id arrays*/
561 buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE +
562 sizeof(wmi_mac_addr) * num_mac_addr_list;
563 dialog_id_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
564 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
565 sizeof(A_UINT32) * num_dialog_ids);
566
567 for (index = 0; index < num_pdev_ids; index++) {
568 pdev_id_array[index] =
569 wmi_handle->ops->convert_pdev_id_host_to_target(
570 wmi_handle,
571 stats_req->pdev_id[index]);
572 }
573
574 for (index = 0; index < num_vdev_ids; index++)
575 vdev_id_array[index] = stats_req->vdev_id[index];
576
577 for (index = 0; index < num_mac_addr_list; index++) {
578 qdf_mem_copy(mac_addr_array, stats_req->peer_mac_addr[index],
579 QDF_MAC_ADDR_SIZE);
580 mac_addr_array += QDF_MAC_ADDR_SIZE;
581 }
582
583 dialog_id_array[0] = get_stats_req_twt_dialog_id(stats_req);
584
585 wmi_debug("stats_id_mask 0x%x action 0x%x dialog_id %d",
586 cmd_fixed_param->stats_id_mask, cmd_fixed_param->action,
587 dialog_id_array[0]);
588 wmi_debug("num_pdev_ids %d num_vdev_ids %d num_dialog_ids %d \
589 num_mac_addr %d", num_pdev_ids, num_vdev_ids,
590 num_dialog_ids, num_mac_addr_list);
591
592 return req_buf;
593 }
594
595 /**
596 * send_infra_cp_stats_request_cmd_tlv() - Prepare and send infra_cp_stats
597 * wmi cmd to firmware
598 * @wmi_handle: wmi handle
599 * @param: Pointer to request structure
600 *
601 * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes
602 * on failure
603 */
604 static QDF_STATUS
send_infra_cp_stats_request_cmd_tlv(wmi_unified_t wmi_handle,struct infra_cp_stats_cmd_info * param)605 send_infra_cp_stats_request_cmd_tlv(wmi_unified_t wmi_handle,
606 struct infra_cp_stats_cmd_info *param)
607 {
608 uint32_t len;
609 wmi_buf_t buf;
610 QDF_STATUS status;
611
612 buf = prepare_infra_cp_stats_buf(wmi_handle, param, &len);
613 if (!buf)
614 return QDF_STATUS_E_NOMEM;
615
616 wmi_debug("buf_len %d", len);
617
618 wmi_mtrace(WMI_REQUEST_CTRL_PATH_STATS_CMDID, NO_SESSION, 0);
619 status = wmi_unified_cmd_send(wmi_handle, buf,
620 len, WMI_REQUEST_CTRL_PATH_STATS_CMDID);
621
622 if (QDF_IS_STATUS_ERROR(status)) {
623 wmi_buf_free(buf);
624 return QDF_STATUS_E_FAILURE;
625 }
626
627 return QDF_STATUS_SUCCESS;
628 }
629 #else
630 static inline QDF_STATUS
send_infra_cp_stats_request_cmd_tlv(wmi_unified_t wmi_handle,struct infra_cp_stats_cmd_info * param)631 send_infra_cp_stats_request_cmd_tlv(wmi_unified_t wmi_handle,
632 struct infra_cp_stats_cmd_info *param)
633 {
634 return QDF_STATUS_SUCCESS;
635 }
636 #endif
637
638 #ifdef QCA_WIFI_EMULATION
639 /**
640 * send_stats_request_cmd_tlv() - WMI request stats function
641 * @wmi_handle: handle to WMI.
642 * @macaddr: MAC address
643 * @param: pointer to hold stats request parameter
644 *
645 * Return: QDF_STATUS on success, else failure.
646 */
647 static QDF_STATUS
send_stats_request_cmd_tlv(wmi_unified_t wmi_handle,uint8_t macaddr[QDF_MAC_ADDR_SIZE],struct stats_request_params * param)648 send_stats_request_cmd_tlv(wmi_unified_t wmi_handle,
649 uint8_t macaddr[QDF_MAC_ADDR_SIZE],
650 struct stats_request_params *param)
651 {
652 return QDF_STATUS_SUCCESS;
653 }
654 #else
655 static QDF_STATUS
send_stats_request_cmd_tlv(wmi_unified_t wmi_handle,uint8_t macaddr[QDF_MAC_ADDR_SIZE],struct stats_request_params * param)656 send_stats_request_cmd_tlv(wmi_unified_t wmi_handle,
657 uint8_t macaddr[QDF_MAC_ADDR_SIZE],
658 struct stats_request_params *param)
659 {
660 int32_t ret;
661 wmi_request_stats_cmd_fixed_param *cmd;
662 wmi_buf_t buf;
663 uint16_t len = sizeof(wmi_request_stats_cmd_fixed_param);
664 bool is_qmi_send_support;
665
666 buf = wmi_buf_alloc(wmi_handle, len);
667 if (!buf)
668 return QDF_STATUS_E_NOMEM;
669
670 cmd = (wmi_request_stats_cmd_fixed_param *) wmi_buf_data(buf);
671 WMITLV_SET_HDR(&cmd->tlv_header,
672 WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param,
673 WMITLV_GET_STRUCT_TLVLEN
674 (wmi_request_stats_cmd_fixed_param));
675 cmd->stats_id = param->stats_id;
676 cmd->vdev_id = param->vdev_id;
677 cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
678 wmi_handle,
679 param->pdev_id);
680 is_qmi_send_support = param->is_qmi_send_support;
681
682 WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->peer_macaddr);
683
684 wmi_debug("STATS REQ STATS_ID:%d VDEV_ID:%d PDEV_ID:%d, is_qmi_send_support %d",
685 cmd->stats_id, cmd->vdev_id, cmd->pdev_id,
686 is_qmi_send_support);
687
688 wmi_mtrace(WMI_REQUEST_STATS_CMDID, cmd->vdev_id, 0);
689 ret = wmi_unified_cmd_send_pm_chk(wmi_handle, buf, len,
690 WMI_REQUEST_STATS_CMDID,
691 is_qmi_send_support);
692
693 if (ret) {
694 wmi_err("Failed to send stats request to fw =%d", ret);
695 wmi_buf_free(buf);
696 }
697
698 return qdf_status_from_os_return(ret);
699 }
700 #endif
701
702 #ifdef WLAN_FEATURE_BIG_DATA_STATS
703 /**
704 * send_big_data_stats_request_cmd_tlv () - send big data stats cmd
705 * @wmi_handle: wmi handle
706 * @param: pointer to command request param
707 *
708 * Return: QDF_STATUS_SUCCESS for success or error code
709 */
710 static QDF_STATUS
send_big_data_stats_request_cmd_tlv(wmi_unified_t wmi_handle,struct stats_request_params * param)711 send_big_data_stats_request_cmd_tlv(wmi_unified_t wmi_handle,
712 struct stats_request_params *param)
713 {
714 int32_t ret = 0;
715 wmi_vdev_get_big_data_p2_cmd_fixed_param *cmd;
716 wmi_buf_t buf;
717 uint16_t len = sizeof(wmi_vdev_get_big_data_p2_cmd_fixed_param);
718
719 buf = wmi_buf_alloc(wmi_handle, len);
720 if (!buf)
721 return QDF_STATUS_E_NOMEM;
722
723 cmd = (wmi_vdev_get_big_data_p2_cmd_fixed_param *)wmi_buf_data(buf);
724 WMITLV_SET_HDR(
725 &cmd->tlv_header,
726 WMITLV_TAG_STRUC_wmi_vdev_get_big_data_p2_cmd_fixed_param,
727 WMITLV_GET_STRUCT_TLVLEN
728 (wmi_vdev_get_big_data_p2_cmd_fixed_param));
729
730 cmd->vdev_id = param->vdev_id;
731
732 wmi_debug("STATS VDEV_ID:%d -->", cmd->vdev_id);
733
734 wmi_mtrace(WMI_VDEV_GET_BIG_DATA_P2_CMDID, cmd->vdev_id, 0);
735 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
736 WMI_VDEV_GET_BIG_DATA_P2_CMDID);
737
738 if (ret) {
739 wmi_err("Failed to send big data stats request to fw =%d", ret);
740 wmi_buf_free(buf);
741 }
742
743 return qdf_status_from_os_return(ret);
744 }
745 #endif
746
747 /**
748 * extract_all_stats_counts_tlv() - extract all stats count from event
749 * @wmi_handle: wmi handle
750 * @evt_buf: pointer to event buffer
751 * @stats_param: Pointer to hold stats count
752 *
753 * Return: QDF_STATUS_SUCCESS for success or error code
754 */
755 static QDF_STATUS
extract_all_stats_counts_tlv(wmi_unified_t wmi_handle,void * evt_buf,wmi_host_stats_event * stats_param)756 extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, void *evt_buf,
757 wmi_host_stats_event *stats_param)
758 {
759 wmi_stats_event_fixed_param *ev;
760 wmi_per_chain_rssi_stats *rssi_event;
761 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
762 uint64_t min_data_len;
763 uint32_t i;
764
765 qdf_mem_zero(stats_param, sizeof(*stats_param));
766 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
767 ev = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
768 rssi_event = param_buf->chain_stats;
769 if (!ev) {
770 wmi_err("event fixed param NULL");
771 return QDF_STATUS_E_FAILURE;
772 }
773
774 if (param_buf->num_data > WMI_SVC_MSG_MAX_SIZE - sizeof(*ev)) {
775 wmi_err("num_data : %u is invalid", param_buf->num_data);
776 return QDF_STATUS_E_FAULT;
777 }
778
779 for (i = 1; i <= WMI_REQUEST_PDEV_TELEMETRY_STAT; i = i << 1) {
780 switch (ev->stats_id & i) {
781 case WMI_REQUEST_PEER_STAT:
782 stats_param->stats_id |= WMI_HOST_REQUEST_PEER_STAT;
783 break;
784
785 case WMI_REQUEST_AP_STAT:
786 stats_param->stats_id |= WMI_HOST_REQUEST_AP_STAT;
787 break;
788
789 case WMI_REQUEST_PDEV_STAT:
790 stats_param->stats_id |= WMI_HOST_REQUEST_PDEV_STAT;
791 break;
792
793 case WMI_REQUEST_VDEV_STAT:
794 stats_param->stats_id |= WMI_HOST_REQUEST_VDEV_STAT;
795 break;
796
797 case WMI_REQUEST_BCNFLT_STAT:
798 stats_param->stats_id |= WMI_HOST_REQUEST_BCNFLT_STAT;
799 break;
800
801 case WMI_REQUEST_VDEV_RATE_STAT:
802 stats_param->stats_id |=
803 WMI_HOST_REQUEST_VDEV_RATE_STAT;
804 break;
805
806 case WMI_REQUEST_BCN_STAT:
807 stats_param->stats_id |= WMI_HOST_REQUEST_BCN_STAT;
808 break;
809 case WMI_REQUEST_PEER_EXTD_STAT:
810 stats_param->stats_id |= WMI_REQUEST_PEER_EXTD_STAT;
811 break;
812
813 case WMI_REQUEST_PEER_EXTD2_STAT:
814 stats_param->stats_id |=
815 WMI_HOST_REQUEST_PEER_ADV_STATS;
816 break;
817
818 case WMI_REQUEST_PMF_BCN_PROTECT_STAT:
819 stats_param->stats_id |=
820 WMI_HOST_REQUEST_PMF_BCN_PROTECT_STAT;
821 break;
822
823 case WMI_REQUEST_VDEV_EXTD_STAT:
824 stats_param->stats_id |=
825 WMI_HOST_REQUEST_VDEV_PRB_FILS_STAT;
826 break;
827
828 case WMI_REQUEST_PDEV_EXTD_STAT:
829 stats_param->stats_id |=
830 WMI_HOST_REQUEST_PDEV_EXTD_STAT;
831 break;
832
833 case WMI_REQUEST_PDEV_TELEMETRY_STAT:
834 stats_param->stats_id |=
835 WMI_HOST_REQUEST_PDEV_TELEMETRY_STAT;
836 break;
837 }
838 }
839
840 /* ev->num_*_stats may cause uint32_t overflow, so use uint64_t
841 * to save total length calculated
842 */
843 min_data_len =
844 (((uint64_t)ev->num_pdev_stats) * sizeof(wmi_pdev_stats)) +
845 (((uint64_t)ev->num_vdev_stats) * sizeof(wmi_vdev_stats)) +
846 (((uint64_t)ev->num_peer_stats) * sizeof(wmi_peer_stats)) +
847 (((uint64_t)ev->num_bcnflt_stats) *
848 sizeof(wmi_bcnfilter_stats_t)) +
849 (((uint64_t)ev->num_chan_stats) * sizeof(wmi_chan_stats)) +
850 (((uint64_t)ev->num_mib_stats) * sizeof(wmi_mib_stats)) +
851 (((uint64_t)ev->num_bcn_stats) * sizeof(wmi_bcn_stats)) +
852 (((uint64_t)ev->num_peer_extd_stats) *
853 sizeof(wmi_peer_extd_stats)) +
854 (((uint64_t)ev->num_mib_extd_stats) *
855 sizeof(wmi_mib_extd_stats));
856 if (param_buf->num_data != min_data_len) {
857 wmi_err("data len: %u isn't same as calculated: %llu",
858 param_buf->num_data, min_data_len);
859 return QDF_STATUS_E_FAULT;
860 }
861
862 stats_param->last_event = ev->last_event;
863 stats_param->num_pdev_stats = ev->num_pdev_stats;
864 stats_param->num_pdev_ext_stats = param_buf->num_pdev_extd_stats;
865 stats_param->num_vdev_stats = ev->num_vdev_stats;
866 stats_param->num_peer_stats = ev->num_peer_stats;
867 stats_param->num_peer_extd_stats = ev->num_peer_extd_stats;
868 stats_param->num_bcnflt_stats = ev->num_bcnflt_stats;
869 stats_param->num_chan_stats = ev->num_chan_stats;
870 stats_param->num_mib_stats = ev->num_mib_stats;
871 stats_param->num_mib_extd_stats = ev->num_mib_extd_stats;
872 stats_param->num_bcn_stats = ev->num_bcn_stats;
873 stats_param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
874 wmi_handle,
875 ev->pdev_id);
876
877 /* if chain_stats is not populated */
878 if (!param_buf->chain_stats || !param_buf->num_chain_stats)
879 return QDF_STATUS_SUCCESS;
880
881 if (WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats !=
882 WMITLV_GET_TLVTAG(rssi_event->tlv_header))
883 return QDF_STATUS_SUCCESS;
884
885 if (WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats) !=
886 WMITLV_GET_TLVLEN(rssi_event->tlv_header))
887 return QDF_STATUS_SUCCESS;
888
889 if (rssi_event->num_per_chain_rssi_stats >=
890 WMITLV_GET_TLVLEN(rssi_event->tlv_header)) {
891 wmi_err("num_per_chain_rssi_stats:%u is out of bounds",
892 rssi_event->num_per_chain_rssi_stats);
893 return QDF_STATUS_E_INVAL;
894 }
895 stats_param->num_rssi_stats = rssi_event->num_per_chain_rssi_stats;
896
897 if (param_buf->vdev_extd_stats)
898 stats_param->num_vdev_extd_stats =
899 param_buf->num_vdev_extd_stats;
900
901 /* if peer_adv_stats is not populated */
902 if (param_buf->num_peer_extd2_stats)
903 stats_param->num_peer_adv_stats =
904 param_buf->num_peer_extd2_stats;
905
906 return QDF_STATUS_SUCCESS;
907 }
908
909 /**
910 * extract_pdev_tx_stats() - extract pdev tx stats from event
911 * @tx: destination
912 * @tx_stats: source event data
913 */
extract_pdev_tx_stats(wmi_host_dbg_tx_stats * tx,struct wlan_dbg_tx_stats * tx_stats)914 static void extract_pdev_tx_stats(wmi_host_dbg_tx_stats *tx,
915 struct wlan_dbg_tx_stats *tx_stats)
916 {
917 /* Tx Stats */
918 tx->comp_queued = tx_stats->comp_queued;
919 tx->comp_delivered = tx_stats->comp_delivered;
920 tx->msdu_enqued = tx_stats->msdu_enqued;
921 tx->mpdu_enqued = tx_stats->mpdu_enqued;
922 tx->wmm_drop = tx_stats->wmm_drop;
923 tx->local_enqued = tx_stats->local_enqued;
924 tx->local_freed = tx_stats->local_freed;
925 tx->hw_queued = tx_stats->hw_queued;
926 tx->hw_reaped = tx_stats->hw_reaped;
927 tx->underrun = tx_stats->underrun;
928 tx->tx_abort = tx_stats->tx_abort;
929 tx->mpdus_requed = tx_stats->mpdus_requed;
930 tx->data_rc = tx_stats->data_rc;
931 tx->self_triggers = tx_stats->self_triggers;
932 tx->sw_retry_failure = tx_stats->sw_retry_failure;
933 tx->illgl_rate_phy_err = tx_stats->illgl_rate_phy_err;
934 tx->pdev_cont_xretry = tx_stats->pdev_cont_xretry;
935 tx->pdev_tx_timeout = tx_stats->pdev_tx_timeout;
936 tx->pdev_resets = tx_stats->pdev_resets;
937 tx->stateless_tid_alloc_failure = tx_stats->stateless_tid_alloc_failure;
938 tx->phy_underrun = tx_stats->phy_underrun;
939 tx->txop_ovf = tx_stats->txop_ovf;
940
941 return;
942 }
943
944
945 /**
946 * extract_pdev_rx_stats() - extract pdev rx stats from event
947 * @rx: destination
948 * @rx_stats: source event data
949 */
extract_pdev_rx_stats(wmi_host_dbg_rx_stats * rx,struct wlan_dbg_rx_stats * rx_stats)950 static void extract_pdev_rx_stats(wmi_host_dbg_rx_stats *rx,
951 struct wlan_dbg_rx_stats *rx_stats)
952 {
953 /* Rx Stats */
954 rx->mid_ppdu_route_change = rx_stats->mid_ppdu_route_change;
955 rx->status_rcvd = rx_stats->status_rcvd;
956 rx->r0_frags = rx_stats->r0_frags;
957 rx->r1_frags = rx_stats->r1_frags;
958 rx->r2_frags = rx_stats->r2_frags;
959 /* Only TLV */
960 rx->r3_frags = 0;
961 rx->htt_msdus = rx_stats->htt_msdus;
962 rx->htt_mpdus = rx_stats->htt_mpdus;
963 rx->loc_msdus = rx_stats->loc_msdus;
964 rx->loc_mpdus = rx_stats->loc_mpdus;
965 rx->oversize_amsdu = rx_stats->oversize_amsdu;
966 rx->phy_errs = rx_stats->phy_errs;
967 rx->phy_err_drop = rx_stats->phy_err_drop;
968 rx->mpdu_errs = rx_stats->mpdu_errs;
969
970 return;
971 }
972
973 /**
974 * extract_pdev_stats_tlv() - extract pdev stats from event
975 * @wmi_handle: wmi handle
976 * @evt_buf: pointer to event buffer
977 * @index: Index into pdev stats
978 * @pdev_stats: Pointer to hold pdev stats
979 *
980 * Return: QDF_STATUS_SUCCESS for success or error code
981 */
982 static QDF_STATUS
extract_pdev_stats_tlv(wmi_unified_t wmi_handle,void * evt_buf,uint32_t index,wmi_host_pdev_stats * pdev_stats)983 extract_pdev_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index,
984 wmi_host_pdev_stats *pdev_stats)
985 {
986 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
987 wmi_stats_event_fixed_param *ev_param;
988 uint8_t *data;
989
990 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
991 ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
992 pdev_stats->pdev_id =
993 wmi_handle->ops->convert_target_pdev_id_to_host(wmi_handle,
994 ev_param->pdev_id);
995
996 data = param_buf->data;
997
998 if (index < ev_param->num_pdev_stats) {
999 wmi_pdev_stats *ev = (wmi_pdev_stats *) ((data) +
1000 (index * sizeof(wmi_pdev_stats)));
1001
1002 pdev_stats->chan_nf = ev->chan_nf;
1003 pdev_stats->tx_frame_count = ev->tx_frame_count;
1004 pdev_stats->rx_frame_count = ev->rx_frame_count;
1005 pdev_stats->rx_clear_count = ev->rx_clear_count;
1006 pdev_stats->cycle_count = ev->cycle_count;
1007 pdev_stats->phy_err_count = ev->phy_err_count;
1008 pdev_stats->chan_tx_pwr = ev->chan_tx_pwr;
1009
1010 extract_pdev_tx_stats(&(pdev_stats->pdev_stats.tx),
1011 &(ev->pdev_stats.tx));
1012 extract_pdev_rx_stats(&(pdev_stats->pdev_stats.rx),
1013 &(ev->pdev_stats.rx));
1014 }
1015
1016 return QDF_STATUS_SUCCESS;
1017 }
1018
1019 /**
1020 * extract_vdev_stats_tlv() - extract vdev stats from event
1021 * @wmi_handle: wmi handle
1022 * @evt_buf: pointer to event buffer
1023 * @index: Index into vdev stats
1024 * @vdev_stats: Pointer to hold vdev stats
1025 *
1026 * Return: QDF_STATUS_SUCCESS for success or error code
1027 */
extract_vdev_stats_tlv(wmi_unified_t wmi_handle,void * evt_buf,uint32_t index,wmi_host_vdev_stats * vdev_stats)1028 static QDF_STATUS extract_vdev_stats_tlv(wmi_unified_t wmi_handle,
1029 void *evt_buf, uint32_t index, wmi_host_vdev_stats *vdev_stats)
1030 {
1031 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
1032 wmi_stats_event_fixed_param *ev_param;
1033 uint8_t *data;
1034
1035 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
1036 ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
1037 data = (uint8_t *) param_buf->data;
1038
1039 if (index < ev_param->num_vdev_stats) {
1040 wmi_vdev_stats *ev = (wmi_vdev_stats *) ((data) +
1041 ((ev_param->num_pdev_stats) *
1042 sizeof(wmi_pdev_stats)) +
1043 (index * sizeof(wmi_vdev_stats)));
1044
1045 vdev_stats->vdev_id = ev->vdev_id;
1046 vdev_stats->vdev_snr.bcn_snr = ev->vdev_snr.bcn_snr;
1047 vdev_stats->vdev_snr.dat_snr = ev->vdev_snr.dat_snr;
1048
1049 OS_MEMCPY(vdev_stats->tx_frm_cnt, ev->tx_frm_cnt,
1050 sizeof(ev->tx_frm_cnt));
1051 vdev_stats->rx_frm_cnt = ev->rx_frm_cnt;
1052 OS_MEMCPY(vdev_stats->multiple_retry_cnt,
1053 ev->multiple_retry_cnt,
1054 sizeof(ev->multiple_retry_cnt));
1055 OS_MEMCPY(vdev_stats->fail_cnt, ev->fail_cnt,
1056 sizeof(ev->fail_cnt));
1057 vdev_stats->rts_fail_cnt = ev->rts_fail_cnt;
1058 vdev_stats->rts_succ_cnt = ev->rts_succ_cnt;
1059 vdev_stats->rx_err_cnt = ev->rx_err_cnt;
1060 vdev_stats->rx_discard_cnt = ev->rx_discard_cnt;
1061 vdev_stats->ack_fail_cnt = ev->ack_fail_cnt;
1062 OS_MEMCPY(vdev_stats->tx_rate_history, ev->tx_rate_history,
1063 sizeof(ev->tx_rate_history));
1064 OS_MEMCPY(vdev_stats->bcn_rssi_history, ev->bcn_rssi_history,
1065 sizeof(ev->bcn_rssi_history));
1066
1067 }
1068
1069 return QDF_STATUS_SUCCESS;
1070 }
1071
1072 /**
1073 * extract_peer_stats_tlv() - extract peer stats from event
1074 * @wmi_handle: wmi handle
1075 * @evt_buf: pointer to event buffer
1076 * @index: Index into peer stats
1077 * @peer_stats: Pointer to hold peer stats
1078 *
1079 * Return: QDF_STATUS_SUCCESS for success or error code
1080 */
1081 static QDF_STATUS
extract_peer_stats_tlv(wmi_unified_t wmi_handle,void * evt_buf,uint32_t index,wmi_host_peer_stats * peer_stats)1082 extract_peer_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index,
1083 wmi_host_peer_stats *peer_stats)
1084 {
1085 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
1086 wmi_stats_event_fixed_param *ev_param;
1087 uint8_t *data;
1088
1089 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
1090 ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
1091 data = (uint8_t *) param_buf->data;
1092
1093 if (index < ev_param->num_peer_stats) {
1094 wmi_peer_stats *ev = (wmi_peer_stats *) ((data) +
1095 ((ev_param->num_pdev_stats) * sizeof(wmi_pdev_stats)) +
1096 ((ev_param->num_vdev_stats) * sizeof(wmi_vdev_stats)) +
1097 (index * sizeof(wmi_peer_stats)));
1098
1099 OS_MEMSET(peer_stats, 0, sizeof(wmi_host_peer_stats));
1100
1101 OS_MEMCPY(&(peer_stats->peer_macaddr),
1102 &(ev->peer_macaddr), sizeof(wmi_mac_addr));
1103
1104 peer_stats->peer_rssi = ev->peer_rssi;
1105 peer_stats->peer_tx_rate = ev->peer_tx_rate;
1106 peer_stats->peer_rx_rate = ev->peer_rx_rate;
1107 }
1108
1109 return QDF_STATUS_SUCCESS;
1110 }
1111
1112 /**
1113 * extract_peer_extd_stats_tlv() - extract extended peer stats from event
1114 * @wmi_handle: wmi handle
1115 * @evt_buf: pointer to event buffer
1116 * @index: Index into extended peer stats
1117 * @peer_extd_stats: Pointer to hold extended peer stats
1118 *
1119 * Return: QDF_STATUS_SUCCESS for success or error code
1120 */
1121 static QDF_STATUS
extract_peer_extd_stats_tlv(wmi_unified_t wmi_handle,void * evt_buf,uint32_t index,wmi_host_peer_extd_stats * peer_extd_stats)1122 extract_peer_extd_stats_tlv(wmi_unified_t wmi_handle,
1123 void *evt_buf, uint32_t index,
1124 wmi_host_peer_extd_stats *peer_extd_stats)
1125 {
1126 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
1127 wmi_stats_event_fixed_param *ev_param;
1128 uint8_t *data;
1129
1130 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf;
1131 ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param;
1132 data = (uint8_t *)param_buf->data;
1133 if (!data)
1134 return QDF_STATUS_E_FAILURE;
1135
1136 if (index < ev_param->num_peer_extd_stats) {
1137 wmi_peer_extd_stats *ev = (wmi_peer_extd_stats *) (data +
1138 (ev_param->num_pdev_stats * sizeof(wmi_pdev_stats)) +
1139 (ev_param->num_vdev_stats * sizeof(wmi_vdev_stats)) +
1140 (ev_param->num_peer_stats * sizeof(wmi_peer_stats)) +
1141 (ev_param->num_bcnflt_stats *
1142 sizeof(wmi_bcnfilter_stats_t)) +
1143 (ev_param->num_chan_stats * sizeof(wmi_chan_stats)) +
1144 (ev_param->num_mib_stats * sizeof(wmi_mib_stats)) +
1145 (ev_param->num_bcn_stats * sizeof(wmi_bcn_stats)) +
1146 (index * sizeof(wmi_peer_extd_stats)));
1147
1148 qdf_mem_zero(peer_extd_stats, sizeof(wmi_host_peer_extd_stats));
1149 qdf_mem_copy(&peer_extd_stats->peer_macaddr, &ev->peer_macaddr,
1150 sizeof(wmi_mac_addr));
1151
1152 peer_extd_stats->rx_mc_bc_cnt = ev->rx_mc_bc_cnt;
1153 }
1154
1155 return QDF_STATUS_SUCCESS;
1156
1157 }
1158
1159 /**
1160 * extract_pmf_bcn_protect_stats_tlv() - extract pmf bcn stats from event
1161 * @wmi_handle: wmi handle
1162 * @evt_buf: pointer to event buffer
1163 * @pmf_bcn_stats: Pointer to hold pmf bcn protect stats
1164 *
1165 * Return: QDF_STATUS_SUCCESS for success or error code
1166 */
1167
1168 static QDF_STATUS
extract_pmf_bcn_protect_stats_tlv(wmi_unified_t wmi_handle,void * evt_buf,wmi_host_pmf_bcn_protect_stats * pmf_bcn_stats)1169 extract_pmf_bcn_protect_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf,
1170 wmi_host_pmf_bcn_protect_stats *pmf_bcn_stats)
1171 {
1172 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
1173 wmi_stats_event_fixed_param *ev_param;
1174
1175 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf;
1176 if (!param_buf)
1177 return QDF_STATUS_E_FAILURE;
1178
1179 ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param;
1180
1181 if ((ev_param->stats_id & WMI_REQUEST_PMF_BCN_PROTECT_STAT) &&
1182 param_buf->pmf_bcn_protect_stats) {
1183 pmf_bcn_stats->igtk_mic_fail_cnt =
1184 param_buf->pmf_bcn_protect_stats->igtk_mic_fail_cnt;
1185 pmf_bcn_stats->igtk_replay_cnt =
1186 param_buf->pmf_bcn_protect_stats->igtk_replay_cnt;
1187 pmf_bcn_stats->bcn_mic_fail_cnt =
1188 param_buf->pmf_bcn_protect_stats->bcn_mic_fail_cnt;
1189 pmf_bcn_stats->bcn_replay_cnt =
1190 param_buf->pmf_bcn_protect_stats->bcn_replay_cnt;
1191 }
1192
1193 return QDF_STATUS_SUCCESS;
1194 }
1195
1196 #if defined(WLAN_SUPPORT_INFRA_CTRL_PATH_STATS) || \
1197 defined(WLAN_CONFIG_TELEMETRY_AGENT)
wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops * ops)1198 static void wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops *ops)
1199 {
1200 ops->send_infra_cp_stats_request_cmd =
1201 send_infra_cp_stats_request_cmd_tlv;
1202 }
1203 #else
wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops * ops)1204 static void wmi_infra_cp_stats_ops_attach_tlv(struct wmi_ops *ops)
1205 {
1206 }
1207 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
1208
1209 #ifdef WLAN_FEATURE_SON
1210 /**
1211 * extract_inst_rssi_stats_resp_tlv() - extract inst rssi stats from event
1212 * @wmi_handle: wmi handle
1213 * @evt_buf: pointer to event buffer
1214 * @inst_rssi_resp: Pointer to hold inst rssi response
1215 *
1216 * Return: QDF_STATUS_SUCCESS for success or error code
1217 */
1218 static QDF_STATUS
extract_inst_rssi_stats_resp_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct wmi_host_inst_rssi_stats_resp * inst_rssi_resp)1219 extract_inst_rssi_stats_resp_tlv(wmi_unified_t wmi_handle, void *evt_buf,
1220 struct wmi_host_inst_rssi_stats_resp *inst_rssi_resp)
1221 {
1222 WMI_INST_RSSI_STATS_EVENTID_param_tlvs *param_buf;
1223 wmi_inst_rssi_stats_resp_fixed_param *event;
1224
1225 param_buf = (WMI_INST_RSSI_STATS_EVENTID_param_tlvs *)evt_buf;
1226 event = (wmi_inst_rssi_stats_resp_fixed_param *)param_buf->fixed_param;
1227
1228 inst_rssi_resp->inst_rssi = event->iRSSI;
1229 WMI_CHAR_ARRAY_TO_MAC_ADDR(inst_rssi_resp->peer_macaddr.bytes,
1230 &event->peer_macaddr);
1231 inst_rssi_resp->vdev_id = event->vdev_id;
1232
1233 return QDF_STATUS_SUCCESS;
1234 }
1235
1236 static void
wmi_inst_rssi_stats_ops_attach_tlv(struct wmi_ops * ops)1237 wmi_inst_rssi_stats_ops_attach_tlv(struct wmi_ops *ops)
1238 {
1239 ops->extract_inst_rssi_stats_resp = extract_inst_rssi_stats_resp_tlv;
1240 }
1241 #else
1242 static void
wmi_inst_rssi_stats_ops_attach_tlv(struct wmi_ops * ops)1243 wmi_inst_rssi_stats_ops_attach_tlv(struct wmi_ops *ops)
1244 {
1245 }
1246 #endif
1247
wmi_cp_stats_attach_tlv(wmi_unified_t wmi_handle)1248 void wmi_cp_stats_attach_tlv(wmi_unified_t wmi_handle)
1249 {
1250 struct wmi_ops *ops = wmi_handle->ops;
1251
1252 ops->send_stats_request_cmd = send_stats_request_cmd_tlv;
1253 #ifdef WLAN_FEATURE_BIG_DATA_STATS
1254 ops->send_big_data_stats_request_cmd =
1255 send_big_data_stats_request_cmd_tlv;
1256 #endif
1257 ops->extract_all_stats_count = extract_all_stats_counts_tlv;
1258 ops->extract_pdev_stats = extract_pdev_stats_tlv;
1259 ops->extract_vdev_stats = extract_vdev_stats_tlv;
1260 ops->extract_peer_stats = extract_peer_stats_tlv;
1261 ops->extract_peer_extd_stats = extract_peer_extd_stats_tlv;
1262 wmi_infra_cp_stats_ops_attach_tlv(ops);
1263 ops->extract_pmf_bcn_protect_stats = extract_pmf_bcn_protect_stats_tlv,
1264 wmi_inst_rssi_stats_ops_attach_tlv(ops);
1265
1266 wmi_mc_cp_stats_attach_tlv(wmi_handle);
1267 }
1268