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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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