1 /*
2 * Copyright (c) 2011-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: wlan_cfg80211_mc_cp_stats.c
22 *
23 * This file provide definitions to cp stats supported cfg80211 cmd handlers
24 */
25
26 #include <wlan_cfg80211.h>
27 #include <wlan_cp_stats_ucfg_api.h>
28 #include <wlan_cp_stats_mc_defs.h>
29 #include <wlan_cp_stats_mc_ucfg_api.h>
30 #include <wlan_cfg80211_mc_cp_stats.h>
31 #include "wlan_osif_request_manager.h"
32 #include "wlan_objmgr_peer_obj.h"
33 #include "wlan_mlme_twt_ucfg_api.h"
34 #include "cds_utils.h"
35 #include "wlan_hdd_main.h"
36 #include "wlan_hdd_stats.h"
37 #include "../../core/src/wlan_cp_stats_obj_mgr_handler.h"
38
39
40 /* max time in ms, caller may wait for stats request get serviced */
41 #define CP_STATS_WAIT_TIME_STAT 800
42
43 #ifdef WLAN_FEATURE_MIB_STATS
44 /**
45 * wlan_free_mib_stats() - free allocations for mib stats
46 * @stats: Pointer to stats event statucture
47 *
48 * Return: None
49 */
wlan_free_mib_stats(struct stats_event * stats)50 static void wlan_free_mib_stats(struct stats_event *stats)
51 {
52 qdf_mem_free(stats->mib_stats);
53 stats->mib_stats = NULL;
54 }
55 #else
wlan_free_mib_stats(struct stats_event * stats)56 static void wlan_free_mib_stats(struct stats_event *stats)
57 {
58 }
59 #endif
60
61 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
62 #ifdef WLAN_SUPPORT_TWT
wlan_cfg80211_infra_cp_stats_twt_dealloc(void * priv)63 static void wlan_cfg80211_infra_cp_stats_twt_dealloc(void *priv)
64 {
65 struct infra_cp_stats_event *stats = priv;
66
67 qdf_mem_free(stats->twt_infra_cp_stats);
68 stats->twt_infra_cp_stats = NULL;
69 }
70 #else
wlan_cfg80211_infra_cp_stats_twt_dealloc(void * priv)71 static void wlan_cfg80211_infra_cp_stats_twt_dealloc(void *priv)
72 {
73 }
74 #endif /* WLAN_SUPPORT_TWT */
75
76 #ifdef CONFIG_WLAN_BMISS
wlan_cfg80211_infra_cp_stats_bmiss_dealloc(void * priv)77 static void wlan_cfg80211_infra_cp_stats_bmiss_dealloc(void *priv)
78 {
79 struct infra_cp_stats_event *stats = priv;
80
81 qdf_mem_free(stats->bmiss_infra_cp_stats);
82 stats->bmiss_infra_cp_stats = NULL;
83 }
84 #else /* CONFIG_WLAN_BMISS */
wlan_cfg80211_infra_cp_stats_bmiss_dealloc(void * priv)85 static void wlan_cfg80211_infra_cp_stats_bmiss_dealloc(void *priv)
86 {
87 }
88 #endif /* CONFIG_WLAN_BMISS */
89 /**
90 * wlan_cfg80211_mc_infra_cp_stats_dealloc() - callback to free priv
91 * allocations for infra cp stats
92 * @priv: Pointer to priv data statucture
93 *
94 * Return: None
95 */
96 static inline
wlan_cfg80211_mc_infra_cp_stats_dealloc(void * priv)97 void wlan_cfg80211_mc_infra_cp_stats_dealloc(void *priv)
98 {
99 struct infra_cp_stats_event *stats = priv;
100
101 if (!stats) {
102 osif_err("infar_cp_stats is NULL");
103 return;
104 }
105 wlan_cfg80211_infra_cp_stats_twt_dealloc(priv);
106 wlan_cfg80211_infra_cp_stats_bmiss_dealloc(priv);
107 }
108 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
109
110 /**
111 * wlan_cfg80211_mc_cp_stats_free_peer_stats_info_ext() - API to free peer stats
112 * info ext structure
113 * @ev: structure from where peer stats info ext needs to be freed
114 *
115 * Return: none
116 */
wlan_cfg80211_mc_cp_stats_free_peer_stats_info_ext(struct stats_event * ev)117 static void wlan_cfg80211_mc_cp_stats_free_peer_stats_info_ext(
118 struct stats_event *ev)
119 {
120 struct peer_stats_info_ext_event *peer_stats_info =
121 ev->peer_stats_info_ext;
122 uint16_t i;
123
124 if (!ev->peer_stats_info_ext) {
125 ev->num_peer_stats_info_ext = 0;
126 return;
127 }
128 for (i = 0; i < ev->num_peer_stats_info_ext; i++) {
129 qdf_mem_free(peer_stats_info->tx_pkt_per_mcs);
130 peer_stats_info->tx_pkt_per_mcs = NULL;
131 qdf_mem_free(peer_stats_info->rx_pkt_per_mcs);
132 peer_stats_info->tx_pkt_per_mcs = NULL;
133 peer_stats_info++;
134 }
135
136 qdf_mem_free(ev->peer_stats_info_ext);
137 ev->peer_stats_info_ext = NULL;
138 ev->num_peer_stats_info_ext = 0;
139 }
140
141 /**
142 * wlan_cfg80211_mc_cp_stats_dealloc() - callback to free priv
143 * allocations for stats
144 * @priv: Pointer to priv data statucture
145 *
146 * Return: None
147 */
wlan_cfg80211_mc_cp_stats_dealloc(void * priv)148 static void wlan_cfg80211_mc_cp_stats_dealloc(void *priv)
149 {
150 struct stats_event *stats = priv;
151
152 if (!stats) {
153 osif_err("stats is NULL");
154 return;
155 }
156
157 qdf_mem_free(stats->pdev_stats);
158 qdf_mem_free(stats->pdev_extd_stats);
159 qdf_mem_free(stats->peer_stats);
160 qdf_mem_free(stats->cca_stats);
161 qdf_mem_free(stats->vdev_summary_stats);
162 qdf_mem_free(stats->vdev_chain_rssi);
163 qdf_mem_free(stats->peer_adv_stats);
164 wlan_cfg80211_mc_cp_stats_free_peer_stats_info_ext(stats);
165 wlan_free_mib_stats(stats);
166 qdf_mem_free(stats->vdev_extd_stats);
167 }
168
169 #define QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE \
170 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE
171 #define QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
172 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR
173 #define QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
174 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ
175
176 /**
177 * wlan_cfg80211_mc_cp_stats_send_wake_lock_stats() - API to send wakelock stats
178 * @wiphy: wiphy pointer
179 * @stats: stats data to be sent
180 *
181 * Return: 0 on success, error number otherwise.
182 */
wlan_cfg80211_mc_cp_stats_send_wake_lock_stats(struct wiphy * wiphy,struct wake_lock_stats * stats)183 static int wlan_cfg80211_mc_cp_stats_send_wake_lock_stats(struct wiphy *wiphy,
184 struct wake_lock_stats *stats)
185 {
186 struct sk_buff *skb;
187 uint32_t nl_buf_len;
188 uint32_t icmpv6_cnt;
189 uint32_t ipv6_rx_multicast_addr_cnt;
190 uint32_t total_rx_data_wake, rx_multicast_cnt;
191
192 nl_buf_len = NLMSG_HDRLEN;
193 nl_buf_len += QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
194 (NLMSG_HDRLEN + sizeof(uint32_t));
195
196 skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
197
198 if (!skb) {
199 osif_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
200 return -ENOMEM;
201 }
202
203 osif_debug("wow_ucast_wake_up_count %d",
204 stats->ucast_wake_up_count);
205 osif_debug("wow_bcast_wake_up_count %d",
206 stats->bcast_wake_up_count);
207 osif_debug("wow_ipv4_mcast_wake_up_count %d",
208 stats->ipv4_mcast_wake_up_count);
209 osif_debug("wow_ipv6_mcast_wake_up_count %d",
210 stats->ipv6_mcast_wake_up_count);
211 osif_debug("wow_ipv6_mcast_ra_stats %d",
212 stats->ipv6_mcast_ra_stats);
213 osif_debug("wow_ipv6_mcast_ns_stats %d",
214 stats->ipv6_mcast_ns_stats);
215 osif_debug("wow_ipv6_mcast_na_stats %d",
216 stats->ipv6_mcast_na_stats);
217 osif_debug("wow_icmpv4_count %d",
218 stats->icmpv4_count);
219 osif_debug("wow_icmpv6_count %d",
220 stats->icmpv6_count);
221 osif_debug("wow_rssi_breach_wake_up_count %d",
222 stats->rssi_breach_wake_up_count);
223 osif_debug("wow_low_rssi_wake_up_count %d",
224 stats->low_rssi_wake_up_count);
225 osif_debug("wow_gscan_wake_up_count %d",
226 stats->gscan_wake_up_count);
227 osif_debug("wow_pno_complete_wake_up_count %d",
228 stats->pno_complete_wake_up_count);
229 osif_debug("wow_pno_match_wake_up_count %d",
230 stats->pno_match_wake_up_count);
231
232 ipv6_rx_multicast_addr_cnt = stats->ipv6_mcast_wake_up_count;
233 icmpv6_cnt = stats->icmpv6_count;
234 rx_multicast_cnt = stats->ipv4_mcast_wake_up_count +
235 ipv6_rx_multicast_addr_cnt;
236 total_rx_data_wake = stats->ucast_wake_up_count +
237 stats->bcast_wake_up_count + rx_multicast_cnt;
238
239 if (nla_put_u32(skb,
240 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE,
241 0) ||
242 nla_put_u32(skb,
243 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR,
244 0) ||
245 nla_put_u32(skb,
246 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ,
247 0) ||
248 nla_put_u32(skb,
249 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE,
250 0) ||
251 nla_put_u32(skb,
252 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR,
253 0) ||
254 nla_put_u32(skb,
255 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ,
256 0) ||
257 nla_put_u32(skb,
258 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE,
259 total_rx_data_wake) ||
260 nla_put_u32(skb,
261 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT,
262 stats->ucast_wake_up_count) ||
263 nla_put_u32(skb,
264 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT,
265 rx_multicast_cnt) ||
266 nla_put_u32(skb,
267 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT,
268 stats->bcast_wake_up_count) ||
269 nla_put_u32(skb,
270 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT,
271 stats->icmpv4_count) ||
272 nla_put_u32(skb,
273 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT,
274 icmpv6_cnt) ||
275 nla_put_u32(skb,
276 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA,
277 stats->ipv6_mcast_ra_stats) ||
278 nla_put_u32(skb,
279 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA,
280 stats->ipv6_mcast_na_stats) ||
281 nla_put_u32(skb,
282 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS,
283 stats->ipv6_mcast_ns_stats) ||
284 nla_put_u32(skb,
285 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT,
286 stats->ipv4_mcast_wake_up_count) ||
287 nla_put_u32(skb,
288 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT,
289 ipv6_rx_multicast_addr_cnt) ||
290 nla_put_u32(skb,
291 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RSSI_BREACH_CNT,
292 stats->rssi_breach_wake_up_count) ||
293 nla_put_u32(skb,
294 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_LOW_RSSI_CNT,
295 stats->low_rssi_wake_up_count) ||
296 nla_put_u32(skb,
297 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_GSCAN_CNT,
298 stats->gscan_wake_up_count) ||
299 nla_put_u32(skb,
300 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_COMPLETE_CNT,
301 stats->pno_complete_wake_up_count) ||
302 nla_put_u32(skb,
303 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_MATCH_CNT,
304 stats->pno_match_wake_up_count)) {
305 osif_err("nla put fail");
306 goto nla_put_failure;
307 }
308
309 wlan_cfg80211_vendor_cmd_reply(skb);
310 return 0;
311
312 nla_put_failure:
313 wlan_cfg80211_vendor_free_skb(skb);
314 return -EINVAL;
315 }
316
317 #undef QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
318 #undef QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
319 #undef QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
320
wlan_cfg80211_mc_cp_stats_get_wakelock_stats(struct wlan_objmgr_psoc * psoc,struct wiphy * wiphy)321 int wlan_cfg80211_mc_cp_stats_get_wakelock_stats(struct wlan_objmgr_psoc *psoc,
322 struct wiphy *wiphy)
323 {
324 /* refer __wlan_hdd_cfg80211_get_wakelock_stats */
325 QDF_STATUS status;
326 struct wake_lock_stats stats = {0};
327
328 status = ucfg_mc_cp_stats_get_psoc_wake_lock_stats(psoc, &stats);
329 if (QDF_IS_STATUS_ERROR(status))
330 return qdf_status_to_os_return(status);
331
332 return wlan_cfg80211_mc_cp_stats_send_wake_lock_stats(wiphy, &stats);
333 }
334
335 struct tx_power_priv {
336 int dbm;
337 };
338
339 /**
340 * get_tx_power_cb() - "Get tx power" callback function
341 * @tx_power: tx_power
342 * @cookie: a cookie for the request context
343 *
344 * Return: None
345 */
get_tx_power_cb(int tx_power,void * cookie)346 static void get_tx_power_cb(int tx_power, void *cookie)
347 {
348 struct osif_request *request;
349 struct tx_power_priv *priv;
350
351 request = osif_request_get(cookie);
352 if (!request) {
353 osif_err("Obsolete request");
354 return;
355 }
356
357 priv = osif_request_priv(request);
358 priv->dbm = tx_power;
359 osif_request_complete(request);
360 osif_request_put(request);
361 }
362
wlan_cfg80211_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev * vdev,int * dbm)363 int wlan_cfg80211_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev,
364 int *dbm)
365 {
366 int ret = 0;
367 void *cookie;
368 QDF_STATUS status;
369 struct request_info info = {0};
370 struct wlan_objmgr_peer *peer;
371 struct tx_power_priv *priv = NULL;
372 struct osif_request *request = NULL;
373 static const struct osif_request_params params = {
374 .priv_size = sizeof(*priv),
375 .timeout_ms = CP_STATS_WAIT_TIME_STAT,
376 };
377
378 request = osif_request_alloc(¶ms);
379 if (!request) {
380 osif_err("Request allocation failure, return cached value");
381 goto fetch_tx_power;
382 }
383
384 cookie = osif_request_cookie(request);
385 info.cookie = cookie;
386 info.u.get_tx_power_cb = get_tx_power_cb;
387 info.vdev_id = wlan_vdev_get_id(vdev);
388 info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
389 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID);
390 if (!peer) {
391 ret = -EINVAL;
392 goto peer_is_null;
393 }
394 qdf_mem_copy(info.peer_mac_addr, peer->macaddr, QDF_MAC_ADDR_SIZE);
395
396 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
397
398 status = ucfg_mc_cp_stats_send_stats_request(vdev,
399 TYPE_CONNECTION_TX_POWER,
400 &info);
401 if (QDF_IS_STATUS_ERROR(status)) {
402 osif_err("wlan_mc_cp_stats_request_tx_power status: %d",
403 status);
404 ret = qdf_status_to_os_return(status);
405 } else {
406 ret = osif_request_wait_for_response(request);
407 if (ret)
408 osif_err("wait failed or timed out ret: %d", ret);
409 else
410 priv = osif_request_priv(request);
411 }
412
413 fetch_tx_power:
414 if (priv) {
415 *dbm = priv->dbm;
416 } else {
417 status = ucfg_mc_cp_stats_get_tx_power(vdev, dbm);
418 if (QDF_IS_STATUS_ERROR(status)) {
419 osif_err("ucfg_mc_cp_stats_get_tx_power status: %d",
420 status);
421 ret = qdf_status_to_os_return(status);
422 }
423 }
424
425 peer_is_null:
426 /*
427 * either we never sent a request, we sent a request and
428 * received a response or we sent a request and timed out.
429 * regardless we are done with the request.
430 */
431 if (request)
432 osif_request_put(request);
433
434 return ret;
435 }
436
437 /**
438 * get_peer_rssi_cb() - get_peer_rssi_cb callback function
439 * @ev: peer stats buffer
440 * @cookie: a cookie for the request context
441 *
442 * Return: None
443 */
get_peer_rssi_cb(struct stats_event * ev,void * cookie)444 static void get_peer_rssi_cb(struct stats_event *ev, void *cookie)
445 {
446 struct stats_event *priv;
447 struct osif_request *request;
448 uint32_t rssi_size;
449
450 request = osif_request_get(cookie);
451 if (!request) {
452 osif_err("Obsolete request");
453 return;
454 }
455
456 if (!ev->peer_stats) {
457 osif_err("no peer stats");
458 goto get_peer_rssi_cb_fail;
459 }
460
461 priv = osif_request_priv(request);
462 rssi_size = sizeof(*ev->peer_stats) * ev->num_peer_stats;
463 if (rssi_size == 0) {
464 osif_err("Invalid rssi stats");
465 goto get_peer_rssi_cb_fail;
466 }
467
468 priv->peer_stats = qdf_mem_malloc(rssi_size);
469 if (!priv->peer_stats)
470 goto get_peer_rssi_cb_fail;
471
472 priv->num_peer_stats = ev->num_peer_stats;
473 qdf_mem_copy(priv->peer_stats, ev->peer_stats, rssi_size);
474
475 get_peer_rssi_cb_fail:
476 osif_request_complete(request);
477 osif_request_put(request);
478 }
479
480 struct stats_event *
wlan_cfg80211_mc_cp_stats_get_peer_rssi(struct wlan_objmgr_vdev * vdev,uint8_t * mac_addr,int * errno)481 wlan_cfg80211_mc_cp_stats_get_peer_rssi(struct wlan_objmgr_vdev *vdev,
482 uint8_t *mac_addr,
483 int *errno)
484 {
485 void *cookie;
486 QDF_STATUS status;
487 struct stats_event *priv, *out;
488 struct request_info info = {0};
489 struct osif_request *request = NULL;
490 static const struct osif_request_params params = {
491 .priv_size = sizeof(*priv),
492 .timeout_ms = CP_STATS_WAIT_TIME_STAT,
493 .dealloc = wlan_cfg80211_mc_cp_stats_dealloc,
494 };
495
496 out = qdf_mem_malloc(sizeof(*out));
497 if (!out) {
498 *errno = -ENOMEM;
499 return NULL;
500 }
501
502 request = osif_request_alloc(¶ms);
503 if (!request) {
504 osif_err("Request allocation failure, return cached value");
505 *errno = -ENOMEM;
506 qdf_mem_free(out);
507 return NULL;
508 }
509
510 cookie = osif_request_cookie(request);
511 priv = osif_request_priv(request);
512 info.cookie = cookie;
513 info.u.get_peer_rssi_cb = get_peer_rssi_cb;
514 info.vdev_id = wlan_vdev_get_id(vdev);
515 info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
516 qdf_mem_copy(info.peer_mac_addr, mac_addr, QDF_MAC_ADDR_SIZE);
517 status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_PEER_STATS,
518 &info);
519 if (QDF_IS_STATUS_ERROR(status)) {
520 osif_err("stats req failed: %d", status);
521 *errno = qdf_status_to_os_return(status);
522 goto get_peer_rssi_fail;
523 }
524
525 *errno = osif_request_wait_for_response(request);
526 if (*errno) {
527 osif_debug("wait failed or timed out ret: %d", *errno);
528 goto get_peer_rssi_fail;
529 }
530
531 if (!priv->peer_stats || priv->num_peer_stats == 0) {
532 osif_err("Invalid peer stats, count %d, data %pK",
533 priv->num_peer_stats, priv->peer_stats);
534 *errno = -EINVAL;
535 goto get_peer_rssi_fail;
536 }
537 out->num_peer_stats = priv->num_peer_stats;
538 out->peer_stats = priv->peer_stats;
539 priv->peer_stats = NULL;
540 osif_request_put(request);
541
542 return out;
543
544 get_peer_rssi_fail:
545 osif_request_put(request);
546 wlan_cfg80211_mc_cp_stats_free_stats_event(out);
547
548 return NULL;
549 }
550
551 #ifdef WLAN_FEATURE_BIG_DATA_STATS
get_big_data_stats_cb(struct big_data_stats_event * ev,void * cookie)552 static void get_big_data_stats_cb(struct big_data_stats_event *ev, void *cookie)
553 {
554 struct big_data_stats_event *priv;
555 struct osif_request *request;
556
557 request = osif_request_get(cookie);
558 if (!request) {
559 osif_err("Obsolete request");
560 return;
561 }
562
563 priv = osif_request_priv(request);
564 priv->tsf_out_of_sync = ev->tsf_out_of_sync;
565 priv->vdev_id = ev->vdev_id;
566 priv->ani_level = ev->ani_level;
567
568 priv->last_data_tx_pwr = ev->last_data_tx_pwr;
569 priv->target_power_dsss = ev->target_power_dsss;
570 priv->target_power_ofdm = ev->target_power_ofdm;
571 priv->last_tx_data_rix = ev->last_tx_data_rix;
572 priv->last_tx_data_rate_kbps = ev->last_tx_data_rate_kbps;
573
574 osif_request_complete(request);
575 osif_request_put(request);
576 }
577 #endif
578
579 /**
580 * get_station_stats_cb() - get_station_stats_cb callback function
581 * @ev: station stats buffer
582 * @cookie: a cookie for the request context
583 *
584 * Return: None
585 */
get_station_stats_cb(struct stats_event * ev,void * cookie)586 static void get_station_stats_cb(struct stats_event *ev, void *cookie)
587 {
588 struct stats_event *priv;
589 struct osif_request *request;
590 uint32_t summary_size, rssi_size, peer_adv_size = 0, pdev_size;
591 uint32_t vdev_extd_size;
592
593 request = osif_request_get(cookie);
594 if (!request) {
595 osif_err("Obsolete request");
596 return;
597 }
598
599 priv = osif_request_priv(request);
600
601 if (!ev->vdev_summary_stats || !ev->vdev_chain_rssi) {
602 osif_debug("Invalid stats");
603 goto station_stats_cb_fail;
604 }
605
606 summary_size = sizeof(*ev->vdev_summary_stats) * ev->num_summary_stats;
607 rssi_size = sizeof(*ev->vdev_chain_rssi) * ev->num_chain_rssi_stats;
608 if (ev->peer_adv_stats && ev->num_peer_adv_stats)
609 peer_adv_size =
610 sizeof(*ev->peer_adv_stats) * ev->num_peer_adv_stats;
611
612 if (summary_size == 0 || rssi_size == 0) {
613 osif_err("Invalid stats, summary %d rssi %d",
614 summary_size, rssi_size);
615 goto station_stats_cb_fail;
616 }
617 if (priv->vdev_summary_stats || priv->vdev_chain_rssi ||
618 priv->peer_adv_stats) {
619 osif_err("invalid context cookie %pK request %pK",
620 cookie, request);
621 goto station_stats_cb_fail;
622 }
623
624 priv->vdev_summary_stats = qdf_mem_malloc(summary_size);
625 if (!priv->vdev_summary_stats)
626 goto station_stats_cb_fail;
627
628 priv->vdev_chain_rssi = qdf_mem_malloc(rssi_size);
629 if (!priv->vdev_chain_rssi)
630 goto station_stats_cb_fail;
631
632 if (peer_adv_size) {
633 priv->peer_adv_stats = qdf_mem_malloc(peer_adv_size);
634 if (!priv->peer_adv_stats)
635 goto station_stats_cb_fail;
636
637 qdf_mem_copy(priv->peer_adv_stats, ev->peer_adv_stats,
638 peer_adv_size);
639 }
640
641 if (ev->num_pdev_stats && ev->pdev_stats) {
642 pdev_size = sizeof(*ev->pdev_stats) * ev->num_pdev_stats;
643 priv->pdev_stats = qdf_mem_malloc(pdev_size);
644 if (!priv->pdev_stats)
645 goto station_stats_cb_fail;
646
647 qdf_mem_copy(priv->pdev_stats, ev->pdev_stats, pdev_size);
648 }
649
650 if (ev->num_vdev_extd_stats && ev->vdev_extd_stats) {
651 vdev_extd_size =
652 sizeof(*ev->vdev_extd_stats) * ev->num_vdev_extd_stats;
653 priv->vdev_extd_stats = qdf_mem_malloc(vdev_extd_size);
654 if (!priv->vdev_extd_stats)
655 goto station_stats_cb_fail;
656
657 qdf_mem_copy(priv->vdev_extd_stats, ev->vdev_extd_stats,
658 vdev_extd_size);
659 }
660
661 priv->num_summary_stats = ev->num_summary_stats;
662 priv->num_chain_rssi_stats = ev->num_chain_rssi_stats;
663 priv->tx_rate = ev->tx_rate;
664 priv->rx_rate = ev->rx_rate;
665 priv->tx_rate_flags = ev->tx_rate_flags;
666 priv->num_peer_adv_stats = ev->num_peer_adv_stats;
667 qdf_mem_copy(priv->vdev_chain_rssi, ev->vdev_chain_rssi, rssi_size);
668 qdf_mem_copy(priv->vdev_summary_stats, ev->vdev_summary_stats,
669 summary_size);
670 priv->bcn_protect_stats = ev->bcn_protect_stats;
671
672 station_stats_cb_fail:
673 osif_request_complete(request);
674 osif_request_put(request);
675 }
676
677 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
678
679 #ifdef WLAN_SUPPORT_TWT
get_twt_infra_cp_stats(struct infra_cp_stats_event * ev,struct infra_cp_stats_event * priv)680 static void get_twt_infra_cp_stats(struct infra_cp_stats_event *ev,
681 struct infra_cp_stats_event *priv)
682
683 {
684 priv->num_twt_infra_cp_stats = ev->num_twt_infra_cp_stats;
685 priv->twt_infra_cp_stats->dialog_id = ev->twt_infra_cp_stats->dialog_id;
686 priv->twt_infra_cp_stats->status = ev->twt_infra_cp_stats->status;
687 priv->twt_infra_cp_stats->num_sp_cycles =
688 ev->twt_infra_cp_stats->num_sp_cycles;
689 priv->twt_infra_cp_stats->avg_sp_dur_us =
690 ev->twt_infra_cp_stats->avg_sp_dur_us;
691 priv->twt_infra_cp_stats->min_sp_dur_us =
692 ev->twt_infra_cp_stats->min_sp_dur_us;
693 priv->twt_infra_cp_stats->max_sp_dur_us =
694 ev->twt_infra_cp_stats->max_sp_dur_us;
695 priv->twt_infra_cp_stats->tx_mpdu_per_sp =
696 ev->twt_infra_cp_stats->tx_mpdu_per_sp;
697 priv->twt_infra_cp_stats->rx_mpdu_per_sp =
698 ev->twt_infra_cp_stats->rx_mpdu_per_sp;
699 priv->twt_infra_cp_stats->tx_bytes_per_sp =
700 ev->twt_infra_cp_stats->tx_bytes_per_sp;
701 priv->twt_infra_cp_stats->rx_bytes_per_sp =
702 ev->twt_infra_cp_stats->rx_bytes_per_sp;
703 }
704
705 static void
wlan_cfg80211_mc_infra_cp_free_twt_stats(struct infra_cp_stats_event * stats)706 wlan_cfg80211_mc_infra_cp_free_twt_stats(struct infra_cp_stats_event *stats)
707 {
708 qdf_mem_free(stats->twt_infra_cp_stats);
709 }
710 #else
get_twt_infra_cp_stats(struct infra_cp_stats_event * ev,struct infra_cp_stats_event * priv)711 static void get_twt_infra_cp_stats(struct infra_cp_stats_event *ev,
712 struct infra_cp_stats_event *priv)
713 {
714 }
715
716 static void
wlan_cfg80211_mc_infra_cp_free_twt_stats(struct infra_cp_stats_event * stats)717 wlan_cfg80211_mc_infra_cp_free_twt_stats(struct infra_cp_stats_event *stats)
718 {
719 }
720 #endif /* WLAN_SUPPORT_TWT */
721
722 #ifdef CONFIG_WLAN_BMISS
723 static void
wlan_cfg80211_mc_infra_cp_free_bmiss_stats(struct infra_cp_stats_event * stats)724 wlan_cfg80211_mc_infra_cp_free_bmiss_stats(struct infra_cp_stats_event *stats)
725 {
726 if (stats->bmiss_infra_cp_stats) {
727 qdf_mem_free(stats->bmiss_infra_cp_stats);
728 stats->bmiss_infra_cp_stats = NULL;
729 }
730 }
731 #else /* CONFIG_WLAN_BMISS */
732 static void
wlan_cfg80211_mc_infra_cp_free_bmiss_stats(struct infra_cp_stats_event * stats)733 wlan_cfg80211_mc_infra_cp_free_bmiss_stats(struct infra_cp_stats_event *stats)
734 {
735 }
736 #endif/* CONFIG_WLAN_BMISS */
737 static inline void
wlan_cfg80211_mc_infra_cp_stats_free_stats_event(struct infra_cp_stats_event * stats)738 wlan_cfg80211_mc_infra_cp_stats_free_stats_event(
739 struct infra_cp_stats_event *stats)
740 {
741 if (!stats)
742 return;
743 wlan_cfg80211_mc_infra_cp_free_twt_stats(stats);
744 wlan_cfg80211_mc_infra_cp_free_bmiss_stats(stats);
745 qdf_mem_free(stats);
746 }
747
748 /**
749 * infra_cp_stats_response_cb() - callback function to handle stats event
750 * @ev: stats event buffer
751 * @cookie: a cookie for the request context
752 *
753 * Return: None
754 */
755 static inline
infra_cp_stats_response_cb(struct infra_cp_stats_event * ev,void * cookie)756 void infra_cp_stats_response_cb(struct infra_cp_stats_event *ev,
757 void *cookie)
758 {
759 struct infra_cp_stats_event *priv;
760 struct osif_request *request;
761
762 request = osif_request_get(cookie);
763 if (!request) {
764 osif_err("Obsolete request");
765 return;
766 }
767
768 priv = osif_request_priv(request);
769
770 priv->action = ev->action;
771 priv->request_id = ev->request_id;
772 priv->status = ev->status;
773 get_twt_infra_cp_stats(ev, priv);
774
775 osif_request_complete(request);
776 osif_request_put(request);
777 }
778
779 #ifdef WLAN_SUPPORT_TWT
780 /*Infra limits Add comment here*/
781 #define MAX_TWT_STAT_VDEV_ENTRIES 1
782 #define MAX_TWT_STAT_MAC_ADDR_ENTRIES 1
783 struct infra_cp_stats_event *
wlan_cfg80211_mc_twt_get_infra_cp_stats(struct wlan_objmgr_vdev * vdev,uint32_t dialog_id,uint8_t twt_peer_mac[QDF_MAC_ADDR_SIZE],int * errno)784 wlan_cfg80211_mc_twt_get_infra_cp_stats(struct wlan_objmgr_vdev *vdev,
785 uint32_t dialog_id,
786 uint8_t twt_peer_mac[QDF_MAC_ADDR_SIZE],
787 int *errno)
788 {
789 void *cookie;
790 QDF_STATUS status;
791 struct infra_cp_stats_event *priv, *out;
792 struct twt_infra_cp_stats_event *twt_event;
793 struct wlan_objmgr_peer *peer;
794 struct osif_request *request;
795 struct infra_cp_stats_cmd_info info = {0};
796 get_infra_cp_stats_cb resp_cb = NULL;
797 void *context = NULL;
798 static const struct osif_request_params params = {
799 .priv_size = sizeof(*priv),
800 .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT,
801 .dealloc = wlan_cfg80211_mc_infra_cp_stats_dealloc,
802 };
803
804 osif_debug("Enter");
805 status = wlan_cp_stats_infra_cp_get_context(wlan_vdev_get_psoc(vdev),
806 &resp_cb, &context);
807 if (QDF_IS_STATUS_ERROR(status)) {
808 *errno = -EFAULT;
809 return NULL;
810 }
811 if (resp_cb) {
812 osif_debug("another request already in progress");
813 *errno = -EBUSY;
814 return NULL;
815 }
816 out = qdf_mem_malloc(sizeof(*out));
817 if (!out) {
818 *errno = -ENOMEM;
819 return NULL;
820 }
821 out->twt_infra_cp_stats =
822 qdf_mem_malloc(sizeof(*out->twt_infra_cp_stats));
823 if (!out->twt_infra_cp_stats) {
824 qdf_mem_free(out);
825 *errno = -ENOMEM;
826 return NULL;
827 }
828
829 request = osif_request_alloc(¶ms);
830 if (!request) {
831 *errno = -ENOMEM;
832 wlan_cfg80211_mc_infra_cp_stats_free_stats_event(out);
833 return NULL;
834 }
835
836 cookie = osif_request_cookie(request);
837 priv = osif_request_priv(request);
838
839 priv->twt_infra_cp_stats =
840 qdf_mem_malloc(sizeof(*priv->twt_infra_cp_stats));
841 if (!priv->twt_infra_cp_stats) {
842 *errno = -ENOMEM;
843 goto free_stats_event;
844 }
845 twt_event = priv->twt_infra_cp_stats;
846
847 info.request_cookie = cookie;
848 info.stats_id = TYPE_REQ_CTRL_PATH_TWT_STAT;
849 info.action = ACTION_REQ_CTRL_PATH_STAT_GET;
850 info.infra_cp_stats_resp_cb = infra_cp_stats_response_cb;
851 info.num_pdev_ids = 0;
852 info.num_vdev_ids = MAX_TWT_STAT_VDEV_ENTRIES;
853 info.vdev_id[0] = wlan_vdev_get_id(vdev);
854 info.num_mac_addr_list = MAX_TWT_STAT_MAC_ADDR_ENTRIES;
855 qdf_mem_copy(&info.peer_mac_addr[0], twt_peer_mac, QDF_MAC_ADDR_SIZE);
856
857 info.dialog_id = dialog_id;
858 info.num_pdev_ids = 0;
859
860 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID);
861 if (!peer) {
862 osif_err("peer is null");
863 *errno = -EINVAL;
864 goto free_stats_event;
865 }
866 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
867
868 status = ucfg_infra_cp_stats_register_resp_cb(wlan_vdev_get_psoc(vdev),
869 &info);
870 if (QDF_IS_STATUS_ERROR(status)) {
871 osif_err("Failed to register resp callback: %d", status);
872 *errno = qdf_status_to_os_return(status);
873 goto free_stats_event;
874 }
875
876 status = ucfg_send_infra_cp_stats_request(vdev, &info);
877 if (QDF_IS_STATUS_ERROR(status)) {
878 osif_err("Failed to send twt stats request status: %d",
879 status);
880 *errno = qdf_status_to_os_return(status);
881 goto get_twt_stats_fail;
882 }
883
884 *errno = osif_request_wait_for_response(request);
885 if (*errno) {
886 osif_err("wait failed or timed out ret: %d", *errno);
887 goto get_twt_stats_fail;
888 }
889
890 out->num_twt_infra_cp_stats = priv->num_twt_infra_cp_stats;
891 out->request_id = priv->request_id;
892 out->twt_infra_cp_stats->dialog_id = twt_event->dialog_id;
893 out->twt_infra_cp_stats->status = twt_event->status;
894 out->twt_infra_cp_stats->num_sp_cycles = twt_event->num_sp_cycles;
895 out->twt_infra_cp_stats->avg_sp_dur_us = twt_event->avg_sp_dur_us;
896 out->twt_infra_cp_stats->min_sp_dur_us = twt_event->min_sp_dur_us;
897 out->twt_infra_cp_stats->max_sp_dur_us = twt_event->max_sp_dur_us;
898 out->twt_infra_cp_stats->tx_mpdu_per_sp = twt_event->tx_mpdu_per_sp;
899 out->twt_infra_cp_stats->rx_mpdu_per_sp = twt_event->rx_mpdu_per_sp;
900 out->twt_infra_cp_stats->tx_bytes_per_sp = twt_event->tx_bytes_per_sp;
901 out->twt_infra_cp_stats->rx_bytes_per_sp = twt_event->rx_bytes_per_sp;
902 qdf_mem_copy(&out->twt_infra_cp_stats->peer_macaddr, twt_peer_mac,
903 QDF_MAC_ADDR_SIZE);
904 osif_request_put(request);
905
906 status = ucfg_infra_cp_stats_deregister_resp_cb(
907 wlan_vdev_get_psoc(vdev));
908 if (QDF_IS_STATUS_ERROR(status))
909 hdd_err("Failed to deregister resp callback: %d", status);
910 osif_debug("Exit");
911
912 return out;
913
914 get_twt_stats_fail:
915 status = ucfg_infra_cp_stats_deregister_resp_cb(
916 wlan_vdev_get_psoc(vdev));
917 if (QDF_IS_STATUS_ERROR(status))
918 hdd_err("Failed to deregister resp callback: %d", status);
919
920 free_stats_event:
921 osif_request_put(request);
922 wlan_cfg80211_mc_infra_cp_stats_free_stats_event(out);
923
924 osif_debug("Exit");
925
926 return NULL;
927 }
928
929 /**
930 * infra_cp_stats_reset_cb() - callback function to handle stats event
931 * due to reset action
932 * @ev: stats event buffer
933 * @cookie: a cookie for the request context
934 *
935 * Return: None
936 */
infra_cp_stats_reset_cb(struct infra_cp_stats_event * ev,void * cookie)937 static void infra_cp_stats_reset_cb(struct infra_cp_stats_event *ev,
938 void *cookie)
939 {
940 struct infra_cp_stats_event *priv;
941 struct osif_request *request;
942
943 request = osif_request_get(cookie);
944 if (!request) {
945 osif_err("Obsolete request");
946 return;
947 }
948
949 priv = osif_request_priv(request);
950
951 osif_debug("clear stats action %d req_id %d, status %d num_cp_stats %d",
952 ev->action, ev->request_id, ev->status,
953 ev->num_twt_infra_cp_stats);
954
955 osif_request_complete(request);
956 osif_request_put(request);
957 }
958
959 /**
960 * wlan_cfg80211_mc_twt_clear_infra_cp_stats() - send clear twt statistics
961 * request to firmware
962 * @vdev: vdev id
963 * @dialog_id: dialog id of the twt session.
964 * @twt_peer_mac: peer mac address
965 *
966 * Return: 0 for success or error code for failure
967 */
968 int
wlan_cfg80211_mc_twt_clear_infra_cp_stats(struct wlan_objmgr_vdev * vdev,uint32_t dialog_id,uint8_t twt_peer_mac[QDF_MAC_ADDR_SIZE])969 wlan_cfg80211_mc_twt_clear_infra_cp_stats(
970 struct wlan_objmgr_vdev *vdev,
971 uint32_t dialog_id,
972 uint8_t twt_peer_mac[QDF_MAC_ADDR_SIZE])
973 {
974 int ret;
975 void *cookie;
976 QDF_STATUS status;
977 struct infra_cp_stats_event *priv;
978 struct wlan_objmgr_psoc *psoc;
979 struct wlan_objmgr_peer *peer;
980 struct osif_request *request;
981 struct infra_cp_stats_cmd_info info = {0};
982 get_infra_cp_stats_cb resp_cb = NULL;
983 void *context = NULL;
984 static const struct osif_request_params params = {
985 .priv_size = sizeof(*priv),
986 .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT,
987 .dealloc = wlan_cfg80211_mc_infra_cp_stats_dealloc,
988 };
989
990 osif_debug("Enter");
991
992 psoc = wlan_vdev_get_psoc(vdev);
993 if (!psoc)
994 return -EINVAL;
995
996 status = wlan_cp_stats_infra_cp_get_context(psoc, &resp_cb, &context);
997 if (QDF_IS_STATUS_ERROR(status))
998 return -EINVAL;
999
1000 if (resp_cb) {
1001 osif_debug("another request already in progress");
1002 return -EINVAL;
1003 }
1004 request = osif_request_alloc(¶ms);
1005 if (!request)
1006 return -ENOMEM;
1007
1008 ucfg_mlme_set_twt_command_in_progress(psoc,
1009 (struct qdf_mac_addr *)twt_peer_mac,
1010 dialog_id,
1011 WLAN_TWT_CLEAR_STATISTICS);
1012
1013 cookie = osif_request_cookie(request);
1014 priv = osif_request_priv(request);
1015
1016 priv->twt_infra_cp_stats =
1017 qdf_mem_malloc(sizeof(*priv->twt_infra_cp_stats));
1018 if (!priv->twt_infra_cp_stats) {
1019 ret = -ENOMEM;
1020 goto clear_twt_stats_fail;
1021 }
1022
1023 info.request_cookie = cookie;
1024 info.stats_id = TYPE_REQ_CTRL_PATH_TWT_STAT;
1025 info.action = ACTION_REQ_CTRL_PATH_STAT_RESET;
1026
1027 info.infra_cp_stats_resp_cb = infra_cp_stats_reset_cb;
1028 info.num_pdev_ids = 0;
1029 info.num_vdev_ids = MAX_TWT_STAT_VDEV_ENTRIES;
1030 info.vdev_id[0] = wlan_vdev_get_id(vdev);
1031 info.num_mac_addr_list = MAX_TWT_STAT_MAC_ADDR_ENTRIES;
1032 qdf_mem_copy(&info.peer_mac_addr[0], twt_peer_mac, QDF_MAC_ADDR_SIZE);
1033
1034 info.dialog_id = dialog_id;
1035 info.num_pdev_ids = 0;
1036
1037 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID);
1038 if (!peer) {
1039 osif_err("peer is null");
1040 ret = -EINVAL;
1041 goto clear_twt_stats_fail;
1042 }
1043 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
1044
1045 status = ucfg_infra_cp_stats_register_resp_cb(psoc, &info);
1046 if (QDF_IS_STATUS_ERROR(status)) {
1047 osif_err("Failed to register resp callback: %d", status);
1048 ret = qdf_status_to_os_return(status);
1049 goto clear_twt_stats_fail;
1050 }
1051
1052 status = ucfg_send_infra_cp_stats_request(vdev, &info);
1053 if (QDF_IS_STATUS_ERROR(status)) {
1054 osif_err("Failed to send twt stats request status: %d",
1055 status);
1056 ret = qdf_status_to_os_return(status);
1057 goto deregister_cb;
1058 }
1059
1060 ret = osif_request_wait_for_response(request);
1061 if (ret)
1062 osif_err("wait failed or timed out ret: %d", ret);
1063
1064 deregister_cb:
1065 status = ucfg_infra_cp_stats_deregister_resp_cb(
1066 wlan_vdev_get_psoc(vdev));
1067 if (QDF_IS_STATUS_ERROR(status))
1068 hdd_err("Failed to deregister resp callback: %d", status);
1069
1070 clear_twt_stats_fail:
1071 ucfg_mlme_set_twt_command_in_progress(psoc,
1072 (struct qdf_mac_addr *)twt_peer_mac,
1073 dialog_id,
1074 WLAN_TWT_NONE);
1075 osif_request_put(request);
1076 osif_debug("Exit");
1077
1078 return ret;
1079 }
1080 #endif
1081 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
1082
1083 struct stats_event *
wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev * vdev,int * errno)1084 wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev,
1085 int *errno)
1086 {
1087 void *cookie;
1088 QDF_STATUS status;
1089 struct stats_event *priv, *out;
1090 struct wlan_objmgr_peer *peer;
1091 struct osif_request *request;
1092 struct request_info info = {0};
1093 static const struct osif_request_params params = {
1094 .priv_size = sizeof(*priv),
1095 .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT,
1096 .dealloc = wlan_cfg80211_mc_cp_stats_dealloc,
1097 };
1098
1099 osif_debug("Enter");
1100
1101 out = qdf_mem_malloc(sizeof(*out));
1102 if (!out) {
1103 *errno = -ENOMEM;
1104 return NULL;
1105 }
1106
1107 request = osif_request_alloc(¶ms);
1108 if (!request) {
1109 qdf_mem_free(out);
1110 *errno = -ENOMEM;
1111 return NULL;
1112 }
1113
1114 cookie = osif_request_cookie(request);
1115 priv = osif_request_priv(request);
1116 info.cookie = cookie;
1117 info.u.get_station_stats_cb = get_station_stats_cb;
1118 info.vdev_id = wlan_vdev_get_id(vdev);
1119 info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
1120 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID);
1121 if (!peer) {
1122 osif_err("peer is null");
1123 *errno = -EINVAL;
1124 goto get_station_stats_fail;
1125 }
1126 qdf_mem_copy(info.peer_mac_addr, peer->macaddr, QDF_MAC_ADDR_SIZE);
1127
1128 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
1129
1130 status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_STATION_STATS,
1131 &info);
1132 if (QDF_IS_STATUS_ERROR(status)) {
1133 osif_err("Failed to send stats request status: %d", status);
1134 *errno = qdf_status_to_os_return(status);
1135 goto get_station_stats_fail;
1136 }
1137
1138 *errno = osif_request_wait_for_response(request);
1139 if (*errno) {
1140 osif_err("wait failed or timed out ret: %d", *errno);
1141 goto get_station_stats_fail;
1142 }
1143
1144 if (!priv->vdev_summary_stats || !priv->vdev_chain_rssi ||
1145 priv->num_summary_stats == 0 || priv->num_chain_rssi_stats == 0) {
1146 osif_err("Invalid stats");
1147 osif_err("summary %d:%pK, rssi %d:%pK",
1148 priv->num_summary_stats, priv->vdev_summary_stats,
1149 priv->num_chain_rssi_stats, priv->vdev_chain_rssi);
1150 *errno = -EINVAL;
1151 goto get_station_stats_fail;
1152 }
1153
1154 out->tx_rate = priv->tx_rate;
1155 out->rx_rate = priv->rx_rate;
1156 out->tx_rate_flags = priv->tx_rate_flags;
1157 out->num_summary_stats = priv->num_summary_stats;
1158 out->num_chain_rssi_stats = priv->num_chain_rssi_stats;
1159 out->vdev_summary_stats = priv->vdev_summary_stats;
1160 priv->vdev_summary_stats = NULL;
1161 out->vdev_chain_rssi = priv->vdev_chain_rssi;
1162 priv->vdev_chain_rssi = NULL;
1163 out->num_peer_adv_stats = priv->num_peer_adv_stats;
1164 if (priv->peer_adv_stats)
1165 out->peer_adv_stats = priv->peer_adv_stats;
1166 priv->peer_adv_stats = NULL;
1167 if (priv->pdev_stats)
1168 out->pdev_stats = priv->pdev_stats;
1169 priv->pdev_stats = NULL;
1170 if (priv->vdev_extd_stats)
1171 out->vdev_extd_stats = priv->vdev_extd_stats;
1172 priv->vdev_extd_stats = NULL;
1173
1174 out->bcn_protect_stats = priv->bcn_protect_stats;
1175 osif_request_put(request);
1176
1177 osif_debug("Exit");
1178
1179 return out;
1180
1181 get_station_stats_fail:
1182 osif_request_put(request);
1183 wlan_cfg80211_mc_cp_stats_free_stats_event(out);
1184
1185 osif_debug("Exit");
1186
1187 return NULL;
1188 }
1189
1190 #ifdef WLAN_FEATURE_BIG_DATA_STATS
1191 struct big_data_stats_event *
wlan_cfg80211_mc_cp_get_big_data_stats(struct wlan_objmgr_vdev * vdev,int * errno)1192 wlan_cfg80211_mc_cp_get_big_data_stats(struct wlan_objmgr_vdev *vdev,
1193 int *errno)
1194 {
1195 void *cookie;
1196 QDF_STATUS status;
1197 struct big_data_stats_event *priv, *out;
1198 struct hdd_context *hdd_ctx = NULL;
1199 struct osif_request *request;
1200 struct request_info info = {0};
1201 struct request_info last_req = {0};
1202 bool pending = false;
1203
1204 static const struct osif_request_params params = {
1205 .priv_size = sizeof(*priv),
1206 .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT,
1207 };
1208
1209 osif_debug("Enter");
1210
1211 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1212 if (wlan_hdd_validate_context(hdd_ctx))
1213 return NULL;
1214
1215 out = qdf_mem_malloc(sizeof(*out));
1216 if (!out)
1217 return NULL;
1218
1219 request = osif_request_alloc(¶ms);
1220 if (!request) {
1221 qdf_mem_free(out);
1222 return NULL;
1223 }
1224
1225 cookie = osif_request_cookie(request);
1226 priv = osif_request_priv(request);
1227 info.cookie = cookie;
1228 info.u.get_big_data_stats_cb = get_big_data_stats_cb;
1229 info.vdev_id = wlan_vdev_get_id(vdev);
1230 info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
1231
1232 status = ucfg_send_big_data_stats_request(vdev,
1233 TYPE_BIG_DATA_STATS,
1234 &info);
1235 if (QDF_IS_STATUS_ERROR(status)) {
1236 osif_err("Failed to send stats request status: %d", status);
1237 *errno = qdf_status_to_os_return(status);
1238 goto get_station_stats_fail;
1239 }
1240
1241 *errno = osif_request_wait_for_response(request);
1242 if (*errno) {
1243 osif_err("wait failed or timed out ret: %d", *errno);
1244 ucfg_mc_cp_stats_reset_pending_req(hdd_ctx->psoc,
1245 TYPE_BIG_DATA_STATS,
1246 &last_req, &pending);
1247 goto get_station_stats_fail;
1248 }
1249
1250 osif_debug("vdev_id: %d tsf_out_of_sync: %d ani_level: %d tx_pwr_last_data_frm: %d target_power_dsss: %d target_power_ofdm: %d rix_last_data_frm: %d tx_rate_last_data_frm: %d",
1251 priv->vdev_id,
1252 priv->tsf_out_of_sync, priv->ani_level,
1253 priv->last_data_tx_pwr, priv->target_power_dsss,
1254 priv->target_power_ofdm, priv->last_tx_data_rix,
1255 priv->last_tx_data_rate_kbps);
1256
1257 out->vdev_id = priv->vdev_id;
1258 out->tsf_out_of_sync = priv->tsf_out_of_sync;
1259 out->ani_level = priv->ani_level;
1260 out->last_data_tx_pwr = priv->last_data_tx_pwr;
1261 out->target_power_dsss = priv->target_power_dsss;
1262 out->target_power_ofdm = priv->target_power_ofdm;
1263 out->last_tx_data_rix = priv->last_tx_data_rix;
1264 out->last_tx_data_rate_kbps = priv->last_tx_data_rate_kbps;
1265 osif_request_put(request);
1266
1267 osif_debug("Exit");
1268
1269 return out;
1270
1271 get_station_stats_fail:
1272 osif_request_put(request);
1273 wlan_cfg80211_mc_cp_stats_free_big_data_stats_event(out);
1274
1275 osif_debug("Exit");
1276
1277 return NULL;
1278 }
1279 #endif
1280
1281 #ifdef WLAN_FEATURE_MIB_STATS
1282 /**
1283 * get_mib_stats_cb() - get mib stats from fw callback function
1284 * @ev: mib stats buffer
1285 * @cookie: a cookie for the request context
1286 *
1287 * Return: None
1288 */
get_mib_stats_cb(struct stats_event * ev,void * cookie)1289 static void get_mib_stats_cb(struct stats_event *ev, void *cookie)
1290 {
1291 struct stats_event *priv;
1292 struct osif_request *request;
1293
1294 request = osif_request_get(cookie);
1295 if (!request) {
1296 osif_err("Obsolete request");
1297 return;
1298 }
1299
1300 priv = osif_request_priv(request);
1301
1302 priv->mib_stats = qdf_mem_malloc(sizeof(*ev->mib_stats));
1303 if (!priv->mib_stats)
1304 goto get_mib_stats_cb_fail;
1305
1306 priv->num_mib_stats = ev->num_mib_stats;
1307 qdf_mem_copy(priv->mib_stats, ev->mib_stats, sizeof(*ev->mib_stats));
1308
1309 get_mib_stats_cb_fail:
1310 osif_request_complete(request);
1311 osif_request_put(request);
1312 }
1313
1314 struct stats_event *
wlan_cfg80211_mc_cp_stats_get_mib_stats(struct wlan_objmgr_vdev * vdev,int * errno)1315 wlan_cfg80211_mc_cp_stats_get_mib_stats(struct wlan_objmgr_vdev *vdev,
1316 int *errno)
1317 {
1318 void *cookie;
1319 QDF_STATUS status;
1320 struct stats_event *priv, *out;
1321 struct wlan_objmgr_peer *peer;
1322 struct osif_request *request;
1323 struct request_info info = {0};
1324 static const struct osif_request_params params = {
1325 .priv_size = sizeof(*priv),
1326 .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT,
1327 .dealloc = wlan_cfg80211_mc_cp_stats_dealloc,
1328 };
1329
1330 out = qdf_mem_malloc(sizeof(*out));
1331 if (!out) {
1332 *errno = -ENOMEM;
1333 return NULL;
1334 }
1335
1336 request = osif_request_alloc(¶ms);
1337 if (!request) {
1338 qdf_mem_free(out);
1339 *errno = -ENOMEM;
1340 return NULL;
1341 }
1342
1343 cookie = osif_request_cookie(request);
1344 priv = osif_request_priv(request);
1345 info.cookie = cookie;
1346 info.u.get_mib_stats_cb = get_mib_stats_cb;
1347 info.vdev_id = wlan_vdev_get_id(vdev);
1348 info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
1349 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID);
1350 if (!peer) {
1351 osif_err("peer is null");
1352 *errno = -EINVAL;
1353 goto get_mib_stats_fail;
1354 }
1355 qdf_mem_copy(info.peer_mac_addr, peer->macaddr, QDF_MAC_ADDR_SIZE);
1356
1357 osif_debug("vdev id %d, pdev id %d, peer " QDF_MAC_ADDR_FMT,
1358 info.vdev_id, info.pdev_id,
1359 QDF_MAC_ADDR_REF(info.peer_mac_addr));
1360
1361 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
1362
1363 status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_MIB_STATS,
1364 &info);
1365 if (QDF_IS_STATUS_ERROR(status)) {
1366 osif_err("Failed to send stats request status: %d", status);
1367 *errno = qdf_status_to_os_return(status);
1368 goto get_mib_stats_fail;
1369 }
1370
1371 *errno = osif_request_wait_for_response(request);
1372 if (*errno) {
1373 osif_err("wait failed or timed out ret: %d", *errno);
1374 goto get_mib_stats_fail;
1375 }
1376
1377 if (!priv->mib_stats || priv->num_mib_stats == 0 ) {
1378 osif_err("Invalid mib stats %d:%pK",
1379 priv->num_mib_stats, priv->mib_stats);
1380 *errno = -EINVAL;
1381 goto get_mib_stats_fail;
1382 }
1383
1384 out->num_mib_stats = priv->num_mib_stats;
1385 out->mib_stats = priv->mib_stats;
1386 priv->mib_stats = NULL;
1387
1388 osif_request_put(request);
1389
1390 return out;
1391
1392 get_mib_stats_fail:
1393 osif_request_put(request);
1394 wlan_cfg80211_mc_cp_stats_free_stats_event(out);
1395
1396 return NULL;
1397 }
1398 #endif
1399
1400 /**
1401 * copy_peer_stats_info_ext - Copy peer ext stats info from stats event to
1402 * destination peer stats info
1403 * @dst_peer_stats_info: Destination peer ext stats pointer where peer ext info
1404 * needs to be copied.
1405 * @ev: Stats event pointer from where peers stats info needs to be copied
1406 *
1407 * Return: Void
1408 */
1409 static void
copy_peer_stats_info_ext(struct peer_stats_info_ext_event * dst_peer_stats_info,struct stats_event * ev)1410 copy_peer_stats_info_ext(struct peer_stats_info_ext_event *dst_peer_stats_info,
1411 struct stats_event *ev)
1412 {
1413 uint32_t i, j;
1414 struct peer_stats_info_ext_event *src_peer_stats_info =
1415 ev->peer_stats_info_ext;
1416 struct peer_stats_info_ext_event *peer_stats_info = dst_peer_stats_info;
1417
1418 for (i = 0; i < ev->num_peer_stats_info_ext; i++) {
1419 qdf_mem_copy(&peer_stats_info->peer_macaddr,
1420 &src_peer_stats_info->peer_macaddr,
1421 sizeof(peer_stats_info->peer_macaddr));
1422 peer_stats_info->tx_packets = src_peer_stats_info->tx_packets;
1423 peer_stats_info->tx_bytes = src_peer_stats_info->tx_bytes;
1424 peer_stats_info->rx_packets = src_peer_stats_info->rx_packets;
1425 peer_stats_info->rx_bytes = src_peer_stats_info->rx_bytes;
1426 peer_stats_info->tx_retries = src_peer_stats_info->tx_retries;
1427 peer_stats_info->tx_failed = src_peer_stats_info->tx_failed;
1428 peer_stats_info->tx_succeed = src_peer_stats_info->tx_succeed;
1429 peer_stats_info->rssi = src_peer_stats_info->rssi;
1430 peer_stats_info->tx_rate = src_peer_stats_info->tx_rate;
1431 peer_stats_info->tx_rate_code =
1432 src_peer_stats_info->tx_rate_code;
1433 peer_stats_info->rx_rate = src_peer_stats_info->rx_rate;
1434 peer_stats_info->rx_rate_code =
1435 src_peer_stats_info->rx_rate_code;
1436 for (j = 0; j < WMI_MAX_CHAINS; j++)
1437 peer_stats_info->peer_rssi_per_chain[j] =
1438 src_peer_stats_info->peer_rssi_per_chain[j];
1439
1440 if (src_peer_stats_info->num_tx_rate_counts) {
1441 peer_stats_info->tx_pkt_per_mcs =
1442 qdf_mem_malloc(
1443 src_peer_stats_info->num_tx_rate_counts *
1444 sizeof(uint32_t));
1445 if (!peer_stats_info->tx_pkt_per_mcs)
1446 return;
1447
1448 peer_stats_info->num_tx_rate_counts =
1449 src_peer_stats_info->num_tx_rate_counts;
1450 qdf_mem_copy(peer_stats_info->tx_pkt_per_mcs,
1451 src_peer_stats_info->tx_pkt_per_mcs,
1452 peer_stats_info->num_tx_rate_counts *
1453 sizeof(uint32_t));
1454 }
1455 if (src_peer_stats_info->num_rx_rate_counts) {
1456 peer_stats_info->rx_pkt_per_mcs =
1457 qdf_mem_malloc(
1458 src_peer_stats_info->num_rx_rate_counts *
1459 sizeof(uint32_t));
1460 if (!peer_stats_info->rx_pkt_per_mcs)
1461 return;
1462
1463 peer_stats_info->num_rx_rate_counts =
1464 src_peer_stats_info->num_rx_rate_counts;
1465 qdf_mem_copy(peer_stats_info->rx_pkt_per_mcs,
1466 src_peer_stats_info->rx_pkt_per_mcs,
1467 peer_stats_info->num_rx_rate_counts *
1468 sizeof(uint32_t));
1469 }
1470 src_peer_stats_info++;
1471 peer_stats_info++;
1472 }
1473 }
1474
1475 /**
1476 * get_peer_stats_cb() - get_peer_stats_cb callback function
1477 * @ev: peer stats buffer
1478 * @cookie: a cookie for the request context
1479 *
1480 * Return: None
1481 */
get_peer_stats_cb(struct stats_event * ev,void * cookie)1482 static void get_peer_stats_cb(struct stats_event *ev, void *cookie)
1483 {
1484 struct stats_event *priv;
1485 struct osif_request *request;
1486 uint32_t peer_stats_info_size;
1487
1488 request = osif_request_get(cookie);
1489 if (!request) {
1490 osif_err("Obsolete request");
1491 return;
1492 }
1493
1494 priv = osif_request_priv(request);
1495 peer_stats_info_size = sizeof(*ev->peer_stats_info_ext) *
1496 ev->num_peer_stats_info_ext;
1497
1498 if (priv->peer_stats_info_ext) {
1499 osif_err("invalid context cookie %pK request %pK",
1500 cookie, request);
1501 goto peer_stats_cb_fail;
1502 }
1503
1504 priv->peer_stats_info_ext = qdf_mem_malloc(peer_stats_info_size);
1505 if (!priv->peer_stats_info_ext)
1506 goto peer_stats_cb_fail;
1507
1508 copy_peer_stats_info_ext(priv->peer_stats_info_ext, ev);
1509
1510 priv->num_peer_stats_info_ext = ev->num_peer_stats_info_ext;
1511
1512 peer_stats_cb_fail:
1513 osif_request_complete(request);
1514 osif_request_put(request);
1515 }
1516
1517 /**
1518 * get_station_adv_stats_cb() - get_station_adv_stats_cb callback function
1519 * @ev: station stats buffer
1520 * @cookie: a cookie for the request context
1521 *
1522 * Return: None
1523 */
get_station_adv_stats_cb(struct stats_event * ev,void * cookie)1524 static void get_station_adv_stats_cb(struct stats_event *ev, void *cookie)
1525 {
1526 struct stats_event *priv;
1527 struct osif_request *request;
1528 uint32_t peer_adv_size;
1529
1530 request = osif_request_get(cookie);
1531 if (!request) {
1532 osif_err("Obsolete request");
1533 return;
1534 }
1535
1536 priv = osif_request_priv(request);
1537 if (!ev->peer_adv_stats || ev->num_peer_adv_stats == 0) {
1538 osif_debug("Invalid stats");
1539 goto station_adv_stats_cb_fail;
1540 }
1541
1542 peer_adv_size = sizeof(*ev->peer_adv_stats) * ev->num_peer_adv_stats;
1543
1544 if (peer_adv_size) {
1545 priv->peer_adv_stats = qdf_mem_malloc(peer_adv_size);
1546 if (!priv->peer_adv_stats)
1547 goto station_adv_stats_cb_fail;
1548
1549 qdf_mem_copy(priv->peer_adv_stats, ev->peer_adv_stats,
1550 peer_adv_size);
1551 }
1552 priv->num_peer_adv_stats = ev->num_peer_adv_stats;
1553
1554 station_adv_stats_cb_fail:
1555 osif_request_complete(request);
1556 osif_request_put(request);
1557 }
1558
1559 #ifdef WLAN_FEATURE_11BE_MLO
1560 /**
1561 * wlan_cfg80211_get_mlstats_vdev_peer - get peer per ml vdev
1562 * @psoc: pointer to psoc struct
1563 * @req_info: pointer to request info struct
1564 *
1565 * Return: QDF_STATUS_SUCCESS on success
1566 */
1567 static QDF_STATUS
wlan_cfg80211_get_mlstats_vdev_peer(struct wlan_objmgr_psoc * psoc,struct request_info * req_info)1568 wlan_cfg80211_get_mlstats_vdev_peer(struct wlan_objmgr_psoc *psoc,
1569 struct request_info *req_info)
1570 {
1571 struct wlan_objmgr_vdev *vdev;
1572 struct wlan_objmgr_peer *peer;
1573 struct mlo_stats_vdev_params *info = &req_info->ml_vdev_info;
1574 int i;
1575
1576 for (i = 0; i < info->ml_vdev_count; i++) {
1577 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1578 info->ml_vdev_id[i],
1579 WLAN_OSIF_STATS_ID);
1580 if (!vdev) {
1581 hdd_err("vdev object is NULL for vdev %d",
1582 info->ml_vdev_id[i]);
1583 return QDF_STATUS_E_INVAL;
1584 }
1585
1586 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
1587 WLAN_OSIF_STATS_ID);
1588 if (!peer) {
1589 hdd_err("peer is null");
1590 wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_STATS_ID);
1591 return QDF_STATUS_E_INVAL;
1592 }
1593
1594 qdf_mem_copy(&req_info->ml_peer_mac_addr[i][0], peer->macaddr,
1595 QDF_MAC_ADDR_SIZE);
1596
1597 wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_STATS_ID);
1598 wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_STATS_ID);
1599 }
1600 return QDF_STATUS_SUCCESS;
1601 }
1602
1603 static QDF_STATUS
wlan_cfg80211_get_mlstats_vdev_params(struct wlan_objmgr_vdev * vdev,struct request_info * info)1604 wlan_cfg80211_get_mlstats_vdev_params(struct wlan_objmgr_vdev *vdev,
1605 struct request_info *info)
1606 {
1607 struct wlan_objmgr_psoc *psoc;
1608 bool is_mlo_vdev;
1609 QDF_STATUS status;
1610
1611 psoc = wlan_vdev_get_psoc(vdev);
1612 if (!psoc)
1613 return QDF_STATUS_E_INVAL;
1614
1615 is_mlo_vdev = wlan_vdev_mlme_get_is_mlo_vdev(psoc, info->vdev_id);
1616 if (is_mlo_vdev) {
1617 status = mlo_get_mlstats_vdev_params(psoc, &info->ml_vdev_info,
1618 info->vdev_id);
1619 if (QDF_IS_STATUS_ERROR(status)) {
1620 osif_err("unable to get vdev params for mlo stats");
1621 return status;
1622 }
1623 }
1624
1625 status = wlan_cfg80211_get_mlstats_vdev_peer(psoc, info);
1626 return status;
1627 }
1628 #else
1629 static QDF_STATUS
wlan_cfg80211_get_mlstats_vdev_params(struct wlan_objmgr_vdev * vdev,struct request_info * info)1630 wlan_cfg80211_get_mlstats_vdev_params(struct wlan_objmgr_vdev *vdev,
1631 struct request_info *info)
1632 {
1633 return QDF_STATUS_SUCCESS;
1634 }
1635 #endif
1636
1637 struct stats_event *
wlan_cfg80211_mc_cp_stats_get_peer_stats(struct wlan_objmgr_vdev * vdev,const uint8_t * mac_addr,int * errno)1638 wlan_cfg80211_mc_cp_stats_get_peer_stats(struct wlan_objmgr_vdev *vdev,
1639 const uint8_t *mac_addr,
1640 int *errno)
1641 {
1642 void *cookie;
1643 QDF_STATUS status;
1644 struct stats_event *priv, *out;
1645 struct osif_request *request;
1646 struct request_info info = {0};
1647 static const struct osif_request_params params = {
1648 .priv_size = sizeof(*priv),
1649 .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT,
1650 .dealloc = wlan_cfg80211_mc_cp_stats_dealloc,
1651 };
1652
1653 osif_debug("Enter");
1654
1655 out = qdf_mem_malloc(sizeof(*out));
1656 if (!out) {
1657 *errno = -ENOMEM;
1658 return NULL;
1659 }
1660
1661 request = osif_request_alloc(¶ms);
1662 if (!request) {
1663 qdf_mem_free(out);
1664 *errno = -ENOMEM;
1665 return NULL;
1666 }
1667
1668 cookie = osif_request_cookie(request);
1669 priv = osif_request_priv(request);
1670 info.cookie = cookie;
1671 info.u.get_peer_stats_cb = get_peer_stats_cb;
1672 info.vdev_id = wlan_vdev_get_id(vdev);
1673 info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
1674 qdf_mem_copy(info.peer_mac_addr, mac_addr, QDF_MAC_ADDR_SIZE);
1675 status = ucfg_mc_cp_stats_send_stats_request(vdev,
1676 TYPE_PEER_STATS_INFO_EXT,
1677 &info);
1678 if (QDF_IS_STATUS_ERROR(status)) {
1679 osif_err("Failed to send stats request status: %d", status);
1680 *errno = qdf_status_to_os_return(status);
1681 goto get_peer_stats_fail;
1682 }
1683
1684 *errno = osif_request_wait_for_response(request);
1685 if (*errno) {
1686 osif_err("wait failed or timed out ret: %d", *errno);
1687 goto get_peer_stats_fail;
1688 }
1689
1690 if (!priv->peer_stats_info_ext || priv->num_peer_stats_info_ext == 0) {
1691 osif_err("Invalid stats");
1692 osif_err("Peer stats info ext %d:%pK",
1693 priv->num_peer_stats_info_ext,
1694 priv->peer_stats_info_ext);
1695 *errno = -EINVAL;
1696 goto get_peer_stats_fail;
1697 }
1698
1699 out->num_peer_stats_info_ext = priv->num_peer_stats_info_ext;
1700 out->peer_stats_info_ext = priv->peer_stats_info_ext;
1701 priv->peer_stats_info_ext = NULL;
1702 osif_request_put(request);
1703
1704 request = osif_request_alloc(¶ms);
1705 if (!request) {
1706 wlan_cfg80211_mc_cp_stats_free_stats_event(out);
1707 *errno = -ENOMEM;
1708 return NULL;
1709 }
1710
1711 cookie = osif_request_cookie(request);
1712 priv = osif_request_priv(request);
1713 info.cookie = cookie;
1714 info.u.get_station_stats_cb = get_station_adv_stats_cb;
1715
1716 status = wlan_cfg80211_get_mlstats_vdev_params(vdev, &info);
1717 if (QDF_IS_STATUS_ERROR(status)) {
1718 *errno = qdf_status_to_os_return(status);
1719 goto get_peer_stats_fail;
1720 }
1721
1722 status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_STATION_STATS,
1723 &info);
1724 if (QDF_IS_STATUS_ERROR(status)) {
1725 osif_err("Failed to send stats request status: %d", status);
1726 *errno = qdf_status_to_os_return(status);
1727 goto get_peer_stats_fail;
1728 }
1729
1730 *errno = osif_request_wait_for_response(request);
1731 if (*errno) {
1732 osif_err("wait failed or timed out ret: %d", *errno);
1733 goto get_peer_stats_fail;
1734 }
1735
1736 if (!priv->peer_adv_stats || priv->num_peer_adv_stats == 0) {
1737 osif_debug("Invalid stats");
1738 goto get_peer_stats_fail;
1739 }
1740
1741 out->num_peer_adv_stats = priv->num_peer_adv_stats;
1742 out->peer_adv_stats = priv->peer_adv_stats;
1743 priv->peer_adv_stats = NULL;
1744 osif_request_put(request);
1745 osif_debug("Exit");
1746 return out;
1747 get_peer_stats_fail:
1748 osif_request_put(request);
1749 wlan_cfg80211_mc_cp_stats_free_stats_event(out);
1750
1751 osif_debug("Exit");
1752
1753 return NULL;
1754 }
1755
wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event * stats)1756 void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats)
1757 {
1758 if (!stats)
1759 return;
1760
1761 qdf_mem_free(stats->pdev_stats);
1762 qdf_mem_free(stats->peer_stats);
1763 qdf_mem_free(stats->cca_stats);
1764 qdf_mem_free(stats->vdev_summary_stats);
1765 qdf_mem_free(stats->vdev_chain_rssi);
1766 qdf_mem_free(stats->peer_adv_stats);
1767 wlan_free_mib_stats(stats);
1768 wlan_cfg80211_mc_cp_stats_free_peer_stats_info_ext(stats);
1769 qdf_mem_free(stats->vdev_extd_stats);
1770 qdf_mem_free(stats);
1771 }
1772
1773 #ifdef WLAN_FEATURE_BIG_DATA_STATS
1774 void
wlan_cfg80211_mc_cp_stats_free_big_data_stats_event(struct big_data_stats_event * stats)1775 wlan_cfg80211_mc_cp_stats_free_big_data_stats_event(
1776 struct big_data_stats_event *stats)
1777 {
1778 if (!stats)
1779 return;
1780
1781 qdf_mem_free(stats);
1782 }
1783 #endif
1784
1785 #ifdef CONFIG_WLAN_BMISS
get_bmiss_infra_cp_stats(struct infra_cp_stats_event * ev,struct infra_cp_stats_event * priv)1786 static void get_bmiss_infra_cp_stats(struct infra_cp_stats_event *ev,
1787 struct infra_cp_stats_event *priv)
1788
1789 {
1790 int idx = 0;
1791
1792 if (!ev || !ev->bmiss_infra_cp_stats) {
1793 osif_err("got bmiss_infra_cp_stats as NULL");
1794 return;
1795 }
1796 priv->bmiss_infra_cp_stats->num_pre_bmiss =
1797 ev->bmiss_infra_cp_stats->num_pre_bmiss;
1798 for (idx = 0; idx < BMISS_STATS_RSSI_SAMPLES_MAX; idx++) {
1799 priv->bmiss_infra_cp_stats->rssi_samples[idx].rssi =
1800 ev->bmiss_infra_cp_stats->rssi_samples[idx].rssi;
1801 priv->bmiss_infra_cp_stats->rssi_samples[idx].sample_time =
1802 ev->bmiss_infra_cp_stats->rssi_samples[idx].sample_time;
1803 }
1804 priv->bmiss_infra_cp_stats->rssi_sample_curr_index =
1805 ev->bmiss_infra_cp_stats->rssi_sample_curr_index;
1806 priv->bmiss_infra_cp_stats->num_first_bmiss =
1807 ev->bmiss_infra_cp_stats->num_first_bmiss;
1808 priv->bmiss_infra_cp_stats->num_final_bmiss =
1809 ev->bmiss_infra_cp_stats->num_final_bmiss;
1810 priv->bmiss_infra_cp_stats->num_null_sent_in_first_bmiss =
1811 ev->bmiss_infra_cp_stats->num_null_sent_in_first_bmiss;
1812 priv->bmiss_infra_cp_stats->num_null_failed_in_first_bmiss =
1813 ev->bmiss_infra_cp_stats->num_null_failed_in_first_bmiss;
1814 priv->bmiss_infra_cp_stats->num_null_sent_in_final_bmiss =
1815 ev->bmiss_infra_cp_stats->num_null_sent_in_final_bmiss;
1816 priv->bmiss_infra_cp_stats->num_null_failed_in_final_bmiss =
1817 ev->bmiss_infra_cp_stats->num_null_failed_in_final_bmiss;
1818 priv->bmiss_infra_cp_stats->cons_bmiss_stats.num_of_bmiss_sequences =
1819 ev->bmiss_infra_cp_stats->cons_bmiss_stats.num_of_bmiss_sequences;
1820 priv->bmiss_infra_cp_stats->cons_bmiss_stats.num_bitmask_wraparound =
1821 ev->bmiss_infra_cp_stats->cons_bmiss_stats.num_bitmask_wraparound;
1822 priv->bmiss_infra_cp_stats->cons_bmiss_stats.num_bcn_hist_lost =
1823 ev->bmiss_infra_cp_stats->cons_bmiss_stats.num_bcn_hist_lost;
1824 }
1825
1826 /**
1827 * infra_cp_stats_bmiss_response_cb() - callback function to handle stats event
1828 * @ev: stats event buffer
1829 * @cookie: a cookie for the request context
1830 *
1831 * Return: None
1832 */
1833 static inline
infra_cp_stats_bmiss_response_cb(struct infra_cp_stats_event * ev,void * cookie)1834 void infra_cp_stats_bmiss_response_cb(struct infra_cp_stats_event *ev,
1835 void *cookie)
1836 {
1837 struct infra_cp_stats_event *priv;
1838 struct osif_request *request;
1839
1840 osif_debug("Enter");
1841
1842 request = osif_request_get(cookie);
1843 if (!request) {
1844 osif_err("Obsolete request");
1845 return;
1846 }
1847
1848 priv = osif_request_priv(request);
1849
1850 priv->action = ev->action;
1851 priv->request_id = ev->request_id;
1852 priv->status = ev->status;
1853 get_bmiss_infra_cp_stats(ev, priv);
1854
1855 osif_request_complete(request);
1856 osif_request_put(request);
1857 }
1858
1859 #define MAX_BMISS_STAT_VDEV_ENTRIES 1
1860 #define MAX_BMISS_STAT_MAC_ADDR_ENTRIES 1
1861
1862 struct infra_cp_stats_event *
wlan_cfg80211_mc_bmiss_get_infra_cp_stats(struct wlan_objmgr_vdev * vdev,uint8_t mac[QDF_MAC_ADDR_SIZE],int * errno)1863 wlan_cfg80211_mc_bmiss_get_infra_cp_stats(struct wlan_objmgr_vdev *vdev,
1864 uint8_t mac[QDF_MAC_ADDR_SIZE],
1865 int *errno)
1866 {
1867 void *cookie;
1868 int idx = 0;
1869 QDF_STATUS status;
1870 struct infra_cp_stats_event *priv, *out;
1871 struct bmiss_infra_cp_stats_event *bmiss_event;
1872 struct osif_request *request;
1873 struct infra_cp_stats_cmd_info info = {0};
1874 get_infra_cp_stats_cb resp_cb = NULL;
1875 void *context = NULL;
1876 static const struct osif_request_params params = {
1877 .priv_size = sizeof(*priv),
1878 .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT,
1879 .dealloc = wlan_cfg80211_mc_infra_cp_stats_dealloc,
1880 };
1881
1882 osif_debug("Enter");
1883 status = wlan_cp_stats_infra_cp_get_context(wlan_vdev_get_psoc(vdev),
1884 &resp_cb, &context);
1885 if (QDF_IS_STATUS_ERROR(status)) {
1886 *errno = -EFAULT;
1887 return NULL;
1888 }
1889 if (resp_cb) {
1890 osif_debug("another request already in progress");
1891 *errno = -EBUSY;
1892 return NULL;
1893 }
1894
1895 out = qdf_mem_malloc(sizeof(*out));
1896 if (!out) {
1897 *errno = -ENOMEM;
1898 return NULL;
1899 }
1900
1901 out->bmiss_infra_cp_stats =
1902 qdf_mem_malloc(sizeof(*out->bmiss_infra_cp_stats));
1903 if (!out->bmiss_infra_cp_stats) {
1904 qdf_mem_free(out);
1905 *errno = -ENOMEM;
1906 return NULL;
1907 }
1908
1909 request = osif_request_alloc(¶ms);
1910 if (!request) {
1911 qdf_mem_free(out->bmiss_infra_cp_stats);
1912 qdf_mem_free(out);
1913 *errno = -ENOMEM;
1914 return NULL;
1915 }
1916
1917 cookie = osif_request_cookie(request);
1918 priv = osif_request_priv(request);
1919
1920 priv->bmiss_infra_cp_stats =
1921 qdf_mem_malloc(sizeof(*priv->bmiss_infra_cp_stats));
1922 if (!priv->bmiss_infra_cp_stats) {
1923 qdf_mem_free(out->bmiss_infra_cp_stats);
1924 qdf_mem_free(out);
1925 *errno = -ENOMEM;
1926 return NULL;
1927 }
1928 bmiss_event = priv->bmiss_infra_cp_stats;
1929 info.request_cookie = cookie;
1930 info.stats_id = TYPE_REQ_CTRL_PATH_BMISS_STAT;
1931 info.action = ACTION_REQ_CTRL_PATH_STAT_GET;
1932 info.infra_cp_stats_resp_cb = infra_cp_stats_bmiss_response_cb;
1933 info.num_pdev_ids = 0;
1934 info.num_vdev_ids = MAX_BMISS_STAT_VDEV_ENTRIES;
1935 info.vdev_id[0] = wlan_vdev_get_id(vdev);
1936 info.num_mac_addr_list = MAX_TWT_STAT_MAC_ADDR_ENTRIES;
1937 info.num_pdev_ids = 0;
1938
1939 qdf_mem_copy(&info.peer_mac_addr[0], mac, QDF_MAC_ADDR_SIZE);
1940 status = ucfg_infra_cp_stats_register_resp_cb(wlan_vdev_get_psoc(vdev),
1941 &info);
1942 if (QDF_IS_STATUS_ERROR(status)) {
1943 osif_err("Failed to register resp callback: %d", status);
1944 *errno = qdf_status_to_os_return(status);
1945 goto free_stats;
1946 }
1947
1948 status = ucfg_send_infra_cp_stats_request(vdev, &info);
1949 if (QDF_IS_STATUS_ERROR(status)) {
1950 osif_err("Failed to send bmiss stats request status: %d",
1951 status);
1952 *errno = qdf_status_to_os_return(status);
1953 goto get_bmiss_stats_fail;
1954 }
1955
1956 *errno = osif_request_wait_for_response(request);
1957 if (*errno) {
1958 osif_err("wait failed or timed out ret: %d", *errno);
1959 goto get_bmiss_stats_fail;
1960 }
1961
1962 out->request_id = priv->request_id;
1963 out->bmiss_infra_cp_stats->num_pre_bmiss = bmiss_event->num_pre_bmiss;
1964 out->bmiss_infra_cp_stats->num_pre_bmiss =
1965 bmiss_event->num_pre_bmiss;
1966 for (idx = 0; idx < BMISS_STATS_RSSI_SAMPLES_MAX; idx++) {
1967 out->bmiss_infra_cp_stats->rssi_samples[idx].rssi =
1968 bmiss_event->rssi_samples[idx].rssi;
1969 out->bmiss_infra_cp_stats->rssi_samples[idx].sample_time =
1970 bmiss_event->rssi_samples[idx].sample_time;
1971 }
1972 out->bmiss_infra_cp_stats->rssi_sample_curr_index =
1973 bmiss_event->rssi_sample_curr_index;
1974 out->bmiss_infra_cp_stats->num_first_bmiss =
1975 bmiss_event->num_first_bmiss;
1976 out->bmiss_infra_cp_stats->num_null_sent_in_first_bmiss =
1977 bmiss_event->num_null_sent_in_first_bmiss;
1978 out->bmiss_infra_cp_stats->num_null_failed_in_first_bmiss =
1979 bmiss_event->num_null_failed_in_first_bmiss;
1980 out->bmiss_infra_cp_stats->num_null_sent_in_final_bmiss =
1981 bmiss_event->num_null_sent_in_final_bmiss;
1982 out->bmiss_infra_cp_stats->num_null_failed_in_final_bmiss =
1983 bmiss_event->num_null_failed_in_final_bmiss;
1984 out->bmiss_infra_cp_stats->cons_bmiss_stats.num_of_bmiss_sequences =
1985 bmiss_event->cons_bmiss_stats.num_of_bmiss_sequences;
1986 out->bmiss_infra_cp_stats->cons_bmiss_stats.num_bitmask_wraparound =
1987 bmiss_event->cons_bmiss_stats.num_bitmask_wraparound;
1988 out->bmiss_infra_cp_stats->cons_bmiss_stats.num_bcn_hist_lost =
1989 bmiss_event->cons_bmiss_stats.num_bcn_hist_lost;
1990
1991 qdf_mem_copy(&out->bmiss_infra_cp_stats->peer_macaddr, mac,
1992 QDF_MAC_ADDR_SIZE);
1993 osif_request_put(request);
1994 status = ucfg_infra_cp_stats_deregister_resp_cb(
1995 wlan_vdev_get_psoc(vdev));
1996 if (QDF_IS_STATUS_ERROR(status))
1997 hdd_err("Failed to deregister resp callback: %d", status);
1998 osif_debug("Exit");
1999 return out;
2000 get_bmiss_stats_fail:
2001 status = ucfg_infra_cp_stats_deregister_resp_cb(
2002 wlan_vdev_get_psoc(vdev));
2003 if (QDF_IS_STATUS_ERROR(status))
2004 hdd_err("Failed to deregister resp callback: %d", status);
2005 free_stats:
2006 osif_request_put(request);
2007 wlan_cfg80211_mc_infra_cp_stats_free_stats_event(out);
2008 osif_debug("Exit");
2009 return NULL;
2010 }
2011 #endif /* CONFIG_WLAN_BMISS */
2012
2013