1 /*
2 * Copyright (c) 2018-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_cp_stats_mc_tgt_api.c
22 *
23 * This file provide API definitions to update control plane statistics received
24 * from southbound interface
25 */
26
27 #include "wlan_cp_stats_mc_defs.h"
28 #include "target_if_cp_stats.h"
29 #include "wlan_cp_stats_tgt_api.h"
30 #include "wlan_cp_stats_ucfg_api.h"
31 #include "wlan_cp_stats_mc_tgt_api.h"
32 #include <wlan_cp_stats_mc_ucfg_api.h>
33 #include <wlan_cp_stats_utils_api.h>
34 #include "../../core/src/wlan_cp_stats_defs.h"
35 #include "../../core/src/wlan_cp_stats_obj_mgr_handler.h"
36 #include "son_api.h"
37 #include "wlan_policy_mgr_api.h"
38
tgt_mc_cp_stats_is_last_event(struct stats_event * ev,enum stats_req_type stats_type)39 static bool tgt_mc_cp_stats_is_last_event(struct stats_event *ev,
40 enum stats_req_type stats_type)
41 {
42 bool is_last_event;
43
44 if (IS_MSB_SET(ev->last_event)) {
45 is_last_event = IS_LSB_SET(ev->last_event);
46 } else {
47 if (stats_type == TYPE_CONNECTION_TX_POWER)
48 is_last_event = true;
49 else
50 is_last_event = !!ev->peer_stats;
51 }
52
53 if (is_last_event)
54 cp_stats_debug("Last stats event");
55
56 return is_last_event;
57 }
58
59 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
60 static void
tgt_cp_stats_register_infra_cp_stats_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)61 tgt_cp_stats_register_infra_cp_stats_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
62 {
63 rx_ops->cp_stats_rx_ops.process_infra_stats_event =
64 tgt_mc_cp_stats_process_infra_stats_event;
65 }
66 #else
67 static void
tgt_cp_stats_register_infra_cp_stats_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)68 tgt_cp_stats_register_infra_cp_stats_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
69 {
70 }
71 #endif
72
73 #ifdef WLAN_FEATURE_BIG_DATA_STATS
74 static void
tgt_cp_stats_register_big_data_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)75 tgt_cp_stats_register_big_data_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
76 {
77 rx_ops->cp_stats_rx_ops.process_big_data_stats_event =
78 tgt_mc_cp_stats_process_big_data_stats_event;
79 }
80
81 static QDF_STATUS
send_big_data_stats_req(struct wlan_lmac_if_cp_stats_tx_ops * tx_ops,struct wlan_objmgr_psoc * psoc,struct request_info * req)82 send_big_data_stats_req(struct wlan_lmac_if_cp_stats_tx_ops *tx_ops,
83 struct wlan_objmgr_psoc *psoc,
84 struct request_info *req)
85 {
86 if (!tx_ops->send_req_big_data_stats) {
87 cp_stats_err("could not get send_req_big_data_stats");
88 return QDF_STATUS_E_NULL_VALUE;
89 }
90
91 return tx_ops->send_req_big_data_stats(psoc, req);
92 }
93 #else
94 static void
tgt_cp_stats_register_big_data_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)95 tgt_cp_stats_register_big_data_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
96 {}
97
98 static QDF_STATUS
send_big_data_stats_req(struct wlan_lmac_if_cp_stats_tx_ops * tx_ops,struct wlan_objmgr_psoc * psoc,struct request_info * req)99 send_big_data_stats_req(struct wlan_lmac_if_cp_stats_tx_ops *tx_ops,
100 struct wlan_objmgr_psoc *psoc,
101 struct request_info *req)
102 {
103 return QDF_STATUS_SUCCESS;
104 }
105 #endif
106
tgt_cp_stats_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)107 void tgt_cp_stats_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
108 {
109 rx_ops->cp_stats_rx_ops.process_stats_event =
110 tgt_mc_cp_stats_process_stats_event;
111 tgt_cp_stats_register_infra_cp_stats_rx_ops(rx_ops);
112 tgt_cp_stats_register_big_data_rx_ops(rx_ops);
113 }
114
tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc * psoc,struct stats_event * ev,bool is_station_stats)115 static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc,
116 struct stats_event *ev,
117 bool is_station_stats)
118 {
119 int32_t max_pwr = 0;
120 uint8_t pdev_id;
121 uint8_t mac_id = 0;
122 QDF_STATUS status;
123 struct wlan_objmgr_pdev *pdev;
124 struct request_info last_req = {0};
125 struct wlan_objmgr_vdev *vdev = NULL;
126 struct pdev_mc_cp_stats *pdev_mc_stats;
127 struct pdev_cp_stats *pdev_cp_stats_priv;
128
129 if (!ev->pdev_stats)
130 return;
131
132 if (is_station_stats)
133 status = ucfg_mc_cp_stats_get_pending_req(psoc,
134 TYPE_STATION_STATS, &last_req);
135 else
136 status = ucfg_mc_cp_stats_get_pending_req(psoc,
137 TYPE_CONNECTION_TX_POWER, &last_req);
138
139 if (QDF_IS_STATUS_ERROR(status)) {
140 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
141 goto end;
142 }
143
144 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req.vdev_id,
145 WLAN_CP_STATS_ID);
146 if (!vdev) {
147 cp_stats_err("vdev is null");
148 goto end;
149 }
150
151 pdev = wlan_vdev_get_pdev(vdev);
152 if (!pdev) {
153 cp_stats_err("pdev is null");
154 goto end;
155 }
156
157 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
158 if (pdev_id >= ev->num_pdev_stats) {
159 cp_stats_err("pdev_id: %d invalid", pdev_id);
160 goto end;
161 }
162
163 pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);
164 if (!pdev_cp_stats_priv) {
165 cp_stats_err("pdev_cp_stats_priv is null");
166 goto end;
167 }
168
169 mac_id = policy_mgr_mode_get_macid_by_vdev_id(psoc, last_req.vdev_id);
170
171 wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv);
172 pdev_mc_stats = pdev_cp_stats_priv->pdev_stats;
173 if (!is_station_stats &&
174 pdev_mc_stats->max_pwr != ev->pdev_stats[pdev_id].max_pwr)
175 wlan_son_deliver_tx_power(vdev,
176 ev->pdev_stats[pdev_id].max_pwr);
177 if (mac_id == ev->mac_seq_num)
178 max_pwr = pdev_mc_stats->max_pwr =
179 ev->pdev_stats[pdev_id].max_pwr;
180
181 wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
182
183 end:
184 if (vdev)
185 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
186 }
187
peer_rssi_iterator(struct wlan_objmgr_pdev * pdev,void * peer,void * arg)188 static void peer_rssi_iterator(struct wlan_objmgr_pdev *pdev,
189 void *peer, void *arg)
190 {
191 struct stats_event *ev;
192 struct peer_mc_cp_stats *peer_mc_stats;
193 struct peer_cp_stats *peer_cp_stats_priv;
194 struct peer_extd_stats *peer_extd_mc_stats;
195
196 if (WLAN_PEER_SELF == wlan_peer_get_peer_type(peer)) {
197 cp_stats_debug("ignore self peer: "QDF_MAC_ADDR_FMT,
198 QDF_MAC_ADDR_REF(wlan_peer_get_macaddr(peer)));
199 return;
200 }
201
202 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
203 if (!peer_cp_stats_priv) {
204 cp_stats_err("peer cp stats object is null");
205 return;
206 }
207
208 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
209 peer_mc_stats = peer_cp_stats_priv->peer_stats;
210 ev = arg;
211 ev->peer_stats[ev->num_peer_stats] = *peer_mc_stats;
212 ev->num_peer_stats++;
213
214 peer_extd_mc_stats = peer_mc_stats->extd_stats;
215 ev->peer_extended_stats[ev->num_peer_extd_stats] = *peer_extd_mc_stats;
216 ev->num_peer_extd_stats++;
217 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
218 }
219
220 static void
tgt_mc_cp_stats_prepare_raw_peer_rssi(struct wlan_objmgr_psoc * psoc,struct request_info * last_req)221 tgt_mc_cp_stats_prepare_raw_peer_rssi(struct wlan_objmgr_psoc *psoc,
222 struct request_info *last_req)
223 {
224 uint8_t *mac_addr;
225 uint16_t peer_count;
226 struct stats_event ev = {0};
227 struct wlan_objmgr_pdev *pdev;
228 struct wlan_objmgr_vdev *vdev;
229 struct wlan_objmgr_peer *peer = NULL;
230 struct peer_mc_cp_stats *peer_mc_stats;
231 struct peer_extd_stats *peer_mc_extd_stats;
232 struct peer_cp_stats *peer_cp_stats_priv;
233 void (*get_peer_rssi_cb)(struct stats_event *ev, void *cookie);
234
235 get_peer_rssi_cb = last_req->u.get_peer_rssi_cb;
236 if (!get_peer_rssi_cb) {
237 cp_stats_debug("get_peer_rssi_cb is null");
238 return;
239 }
240
241 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req->vdev_id,
242 WLAN_CP_STATS_ID);
243 if (!vdev) {
244 cp_stats_err("vdev is null");
245 goto end;
246 }
247
248 mac_addr = last_req->peer_mac_addr;
249 if (QDF_IS_ADDR_BROADCAST(mac_addr)) {
250 pdev = wlan_vdev_get_pdev(vdev);
251 peer_count = wlan_pdev_get_peer_count(pdev);
252 ev.peer_stats = qdf_mem_malloc(sizeof(*ev.peer_stats) *
253 peer_count);
254 if (!ev.peer_stats)
255 goto end;
256
257 ev.peer_extended_stats =
258 qdf_mem_malloc(sizeof(*ev.peer_extended_stats) *
259 peer_count);
260 if (!ev.peer_extended_stats)
261 goto end;
262
263 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_PEER_OP,
264 peer_rssi_iterator, &ev,
265 true, WLAN_CP_STATS_ID);
266 } else {
267 peer = wlan_objmgr_get_peer(psoc, last_req->pdev_id,
268 mac_addr, WLAN_CP_STATS_ID);
269 if (!peer) {
270 cp_stats_debug("peer[" QDF_MAC_ADDR_FMT "] is null",
271 QDF_MAC_ADDR_REF(mac_addr));
272 goto end;
273 }
274
275 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
276 if (!peer_cp_stats_priv) {
277 cp_stats_err("peer cp stats object is null");
278 goto end;
279 }
280
281 ev.peer_stats = qdf_mem_malloc(sizeof(*ev.peer_stats));
282 if (!ev.peer_stats)
283 goto end;
284
285 ev.num_peer_stats = 1;
286
287 ev.peer_extended_stats =
288 qdf_mem_malloc(sizeof(*ev.peer_extended_stats));
289 if (!ev.peer_extended_stats)
290 goto end;
291
292 ev.num_peer_extd_stats = 1;
293
294 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
295 peer_mc_stats = peer_cp_stats_priv->peer_stats;
296 *ev.peer_stats = *peer_mc_stats;
297
298 peer_mc_extd_stats = peer_mc_stats->extd_stats;
299 *ev.peer_extended_stats = *peer_mc_extd_stats;
300 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
301 }
302
303 end:
304 get_peer_rssi_cb(&ev, last_req->cookie);
305
306 ucfg_mc_cp_stats_free_stats_resources(&ev);
307
308 if (vdev)
309 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
310 if (peer)
311 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
312 }
313
314 static QDF_STATUS
tgt_mc_cp_stats_update_peer_adv_stats(struct wlan_objmgr_psoc * psoc,struct peer_adv_mc_cp_stats * peer_adv_stats,uint32_t size)315 tgt_mc_cp_stats_update_peer_adv_stats(struct wlan_objmgr_psoc *psoc,
316 struct peer_adv_mc_cp_stats
317 *peer_adv_stats, uint32_t size)
318 {
319 uint8_t *peer_mac_addr;
320 struct wlan_objmgr_peer *peer;
321 struct peer_mc_cp_stats *peer_mc_stats;
322 struct peer_adv_mc_cp_stats *peer_adv_mc_stats;
323 QDF_STATUS status = QDF_STATUS_SUCCESS;
324 struct peer_cp_stats *peer_cp_stats_priv;
325
326 if (!peer_adv_stats)
327 return QDF_STATUS_E_INVAL;
328
329 peer_mac_addr = peer_adv_stats->peer_macaddr;
330 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac_addr,
331 WLAN_CP_STATS_ID);
332 if (!peer) {
333 cp_stats_debug("peer is null");
334 return QDF_STATUS_E_EXISTS;
335 }
336 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
337 if (!peer_cp_stats_priv) {
338 cp_stats_err("peer_cp_stats_priv is null");
339 status = QDF_STATUS_E_EXISTS;
340 goto end;
341 }
342 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
343 peer_mc_stats = peer_cp_stats_priv->peer_stats;
344 peer_adv_mc_stats = peer_mc_stats->adv_stats;
345
346 qdf_mem_copy(peer_adv_mc_stats->peer_macaddr,
347 peer_adv_stats->peer_macaddr,
348 QDF_MAC_ADDR_SIZE);
349 if (peer_adv_stats->fcs_count)
350 peer_adv_mc_stats->fcs_count = peer_adv_stats->fcs_count;
351 if (peer_adv_stats->rx_bytes)
352 peer_adv_mc_stats->rx_bytes = peer_adv_stats->rx_bytes;
353 if (peer_adv_stats->rx_count)
354 peer_adv_mc_stats->rx_count = peer_adv_stats->rx_count;
355 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
356
357 end:
358 if (peer)
359 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
360
361 return status;
362 }
363
364 static QDF_STATUS
tgt_mc_cp_stats_update_peer_stats(struct wlan_objmgr_psoc * psoc,struct peer_mc_cp_stats * peer_stats)365 tgt_mc_cp_stats_update_peer_stats(struct wlan_objmgr_psoc *psoc,
366 struct peer_mc_cp_stats *peer_stats)
367 {
368 uint8_t *peer_mac_addr;
369 struct wlan_objmgr_peer *peer;
370 struct peer_mc_cp_stats *peer_mc_stats;
371 QDF_STATUS status = QDF_STATUS_SUCCESS;
372 struct peer_cp_stats *peer_cp_stats_priv;
373
374 if (!peer_stats)
375 return QDF_STATUS_E_INVAL;
376
377 peer_mac_addr = peer_stats->peer_macaddr;
378 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac_addr,
379 WLAN_CP_STATS_ID);
380 if (!peer) {
381 cp_stats_debug("peer is null");
382 return QDF_STATUS_E_EXISTS;
383 }
384
385 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
386 if (!peer_cp_stats_priv) {
387 cp_stats_err("peer_cp_stats_priv is null");
388 status = QDF_STATUS_E_EXISTS;
389 goto end;
390 }
391
392 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
393 peer_mc_stats = peer_cp_stats_priv->peer_stats;
394 qdf_mem_copy(peer_mc_stats->peer_macaddr,
395 peer_stats->peer_macaddr,
396 QDF_MAC_ADDR_SIZE);
397 if (peer_stats->tx_rate)
398 peer_mc_stats->tx_rate = peer_stats->tx_rate;
399 if (peer_stats->rx_rate)
400 peer_mc_stats->rx_rate = peer_stats->rx_rate;
401 if (peer_stats->peer_rssi)
402 peer_mc_stats->peer_rssi = peer_stats->peer_rssi;
403 cp_stats_nofl_debug("PEER STATS: peer_mac="QDF_MAC_ADDR_FMT", tx_rate=%u, rx_rate=%u, peer_rssi=%d",
404 QDF_MAC_ADDR_REF(peer_mc_stats->peer_macaddr),
405 peer_mc_stats->tx_rate,
406 peer_mc_stats->rx_rate, peer_mc_stats->peer_rssi);
407 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
408
409 end:
410 if (peer)
411 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
412
413 return status;
414 }
415
416 static QDF_STATUS
tgt_mc_cp_stats_update_peer_extd_stats(struct wlan_objmgr_psoc * psoc,struct peer_extd_stats * peer_extended_stats)417 tgt_mc_cp_stats_update_peer_extd_stats(
418 struct wlan_objmgr_psoc *psoc,
419 struct peer_extd_stats *peer_extended_stats)
420 {
421 uint8_t *peer_mac_addr;
422 struct wlan_objmgr_peer *peer;
423 struct peer_mc_cp_stats *peer_mc_stats;
424 struct peer_extd_stats *peer_extd_mc_stats;
425 QDF_STATUS status = QDF_STATUS_SUCCESS;
426 struct peer_cp_stats *peer_cp_stats_priv;
427
428 if (!peer_extended_stats)
429 return QDF_STATUS_E_INVAL;
430
431 peer_mac_addr = peer_extended_stats->peer_macaddr;
432 peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac_addr,
433 WLAN_CP_STATS_ID);
434 if (!peer) {
435 cp_stats_debug("peer is null");
436 return QDF_STATUS_E_EXISTS;
437 }
438
439 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
440 if (!peer_cp_stats_priv) {
441 cp_stats_err("peer_cp_stats_priv is null");
442 status = QDF_STATUS_E_EXISTS;
443 goto end;
444 }
445
446 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
447 peer_mc_stats = peer_cp_stats_priv->peer_stats;
448 peer_extd_mc_stats = peer_mc_stats->extd_stats;
449 if (!peer_extd_mc_stats) {
450 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
451 cp_stats_err("No peer_extd_mc_stats");
452 status = QDF_STATUS_E_INVAL;
453 goto end;
454 }
455 qdf_mem_copy(peer_extd_mc_stats->peer_macaddr,
456 peer_extended_stats->peer_macaddr,
457 QDF_MAC_ADDR_SIZE);
458 if (peer_extended_stats->rx_mc_bc_cnt)
459 peer_extd_mc_stats->rx_mc_bc_cnt =
460 peer_extended_stats->rx_mc_bc_cnt;
461 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
462
463 cp_stats_debug("peer_mac="QDF_MAC_ADDR_FMT", rx_mc_bc_cnt=%u",
464 QDF_MAC_ADDR_REF(peer_extended_stats->peer_macaddr),
465 peer_extended_stats->rx_mc_bc_cnt);
466
467 end:
468 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
469
470 return status;
471 }
472
tgt_mc_cp_stats_extract_peer_extd_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)473 static void tgt_mc_cp_stats_extract_peer_extd_stats(
474 struct wlan_objmgr_psoc *psoc,
475 struct stats_event *ev)
476 {
477 uint32_t i, selected;
478 QDF_STATUS status;
479 struct request_info last_req = {0};
480
481 status = ucfg_mc_cp_stats_get_pending_req(psoc,
482 TYPE_PEER_STATS,
483 &last_req);
484
485 if (QDF_IS_STATUS_ERROR(status)) {
486 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
487 return;
488 }
489
490 selected = ev->num_peer_extd_stats;
491 for (i = 0; i < ev->num_peer_extd_stats; i++) {
492 status = tgt_mc_cp_stats_update_peer_extd_stats(
493 psoc,
494 &ev->peer_extended_stats[i]);
495
496 if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
497 !qdf_mem_cmp(ev->peer_extended_stats[i].peer_macaddr,
498 last_req.peer_mac_addr,
499 QDF_MAC_ADDR_SIZE)) {
500 /* mac is specified, but failed to update the peer */
501 if (QDF_IS_STATUS_ERROR(status))
502 return;
503
504 selected = i;
505 }
506 }
507
508 /* no matched peer */
509 if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
510 selected == ev->num_peer_extd_stats) {
511 cp_stats_rl_err("peer not found stats");
512 return;
513 }
514 }
515
tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev,bool is_station_stats)516 static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc,
517 struct stats_event *ev,
518 bool is_station_stats)
519 {
520 uint32_t i;
521 QDF_STATUS status;
522 struct request_info last_req = {0};
523 bool pending = false;
524 uint32_t selected;
525
526 if (is_station_stats)
527 status = ucfg_mc_cp_stats_get_pending_req(psoc,
528 TYPE_STATION_STATS,
529 &last_req);
530 else
531 status = ucfg_mc_cp_stats_get_pending_req(psoc,
532 TYPE_PEER_STATS,
533 &last_req);
534
535 if (QDF_IS_STATUS_ERROR(status)) {
536 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
537 return;
538 }
539
540 if (!ev->peer_stats)
541 goto extd2_stats;
542
543 selected = ev->num_peer_stats;
544 for (i = 0; i < ev->num_peer_stats; i++) {
545 status = tgt_mc_cp_stats_update_peer_stats(psoc,
546 &ev->peer_stats[i]);
547 if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
548 !qdf_mem_cmp(ev->peer_stats[i].peer_macaddr,
549 last_req.peer_mac_addr,
550 QDF_MAC_ADDR_SIZE)) {
551 /* mac is specified, but failed to update the peer */
552 if (QDF_IS_STATUS_ERROR(status))
553 return;
554
555 selected = i;
556 }
557 }
558
559 /* no matched peer */
560 if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
561 selected == ev->num_peer_stats)
562 cp_stats_debug("peer not found for stats");
563
564 extd2_stats:
565
566 if (!ev->peer_adv_stats)
567 goto complete;
568
569 selected = ev->num_peer_adv_stats;
570 for (i = 0; i < ev->num_peer_adv_stats; i++) {
571 status = tgt_mc_cp_stats_update_peer_adv_stats(
572 psoc, &ev->peer_adv_stats[i],
573 ev->num_peer_adv_stats);
574 if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
575 !qdf_mem_cmp(ev->peer_adv_stats[i].peer_macaddr,
576 last_req.peer_mac_addr,
577 QDF_MAC_ADDR_SIZE)) {
578 /* mac is specified, but failed to update the peer */
579 if (QDF_IS_STATUS_ERROR(status))
580 return;
581
582 selected = i;
583 }
584 }
585
586 /* no matched peer */
587 if (!QDF_IS_ADDR_BROADCAST(last_req.peer_mac_addr) &&
588 selected == ev->num_peer_adv_stats)
589 cp_stats_debug("peer not found for extd stats");
590
591 complete:
592 if (is_station_stats)
593 return;
594
595 tgt_mc_cp_stats_extract_peer_extd_stats(psoc, ev);
596 if (tgt_mc_cp_stats_is_last_event(ev, TYPE_PEER_STATS)) {
597 ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS,
598 &last_req, &pending);
599 if (pending && last_req.u.get_peer_rssi_cb)
600 tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req);
601 }
602 }
603
604 #ifdef WLAN_FEATURE_MIB_STATS
tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)605 static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc,
606 struct stats_event *ev)
607 {
608 QDF_STATUS status;
609 struct request_info last_req = {0};
610 bool pending = false;
611
612 if (!ev->mib_stats) {
613 cp_stats_debug("no mib stats");
614 return;
615 }
616
617 status = ucfg_mc_cp_stats_get_pending_req(psoc,
618 TYPE_MIB_STATS, &last_req);
619
620 if (QDF_IS_STATUS_ERROR(status)) {
621 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
622 return;
623 }
624
625 if (tgt_mc_cp_stats_is_last_event(ev, TYPE_MIB_STATS)) {
626 ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_MIB_STATS,
627 &last_req, &pending);
628 if (last_req.u.get_mib_stats_cb && pending)
629 last_req.u.get_mib_stats_cb(ev, last_req.cookie);
630 }
631 }
632 #else
tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)633 static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc,
634 struct stats_event *ev)
635 {
636 }
637 #endif
638
639 static void
tgt_mc_cp_stats_extract_peer_stats_info_ext(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)640 tgt_mc_cp_stats_extract_peer_stats_info_ext(struct wlan_objmgr_psoc *psoc,
641 struct stats_event *ev)
642 {
643 QDF_STATUS status;
644 struct request_info last_req = {0};
645 bool pending = false;
646
647 if (!ev->peer_stats_info_ext || ev->num_peer_stats_info_ext == 0) {
648 cp_stats_debug("no peer_stats_info_ext");
649 return;
650 }
651
652 status = ucfg_mc_cp_stats_get_pending_req(psoc,
653 TYPE_PEER_STATS_INFO_EXT,
654 &last_req);
655 if (QDF_IS_STATUS_ERROR(status)) {
656 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
657 return;
658 }
659
660 ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS_INFO_EXT,
661 &last_req, &pending);
662 if (last_req.u.get_peer_stats_cb && pending) {
663 last_req.u.get_peer_stats_cb(ev, last_req.cookie);
664 last_req.u.get_peer_stats_cb = NULL;
665 }
666 }
667
668 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
669 #ifdef WLAN_SUPPORT_TWT
670 static void
tgt_mc_infra_cp_stats_extract_twt_stats(struct wlan_objmgr_psoc * psoc,struct infra_cp_stats_event * ev)671 tgt_mc_infra_cp_stats_extract_twt_stats(struct wlan_objmgr_psoc *psoc,
672 struct infra_cp_stats_event *ev)
673 {
674 QDF_STATUS status;
675 get_infra_cp_stats_cb resp_cb = NULL;
676 void *context = NULL;
677
678 status = wlan_cp_stats_infra_cp_get_context(psoc, &resp_cb, &context);
679 if (QDF_IS_STATUS_ERROR(status)) {
680 cp_stats_err("ucfg_get_infra_cp_stats_context failed");
681 return;
682 }
683
684 cp_stats_debug("num_twt_infra_cp_stats = %d action %d",
685 ev->num_twt_infra_cp_stats, ev->action);
686
687 if (resp_cb)
688 resp_cb(ev, context);
689 }
690 #else
691 static void
tgt_mc_infra_cp_stats_extract_twt_stats(struct wlan_objmgr_psoc * psoc,struct infra_cp_stats_event * ev)692 tgt_mc_infra_cp_stats_extract_twt_stats(struct wlan_objmgr_psoc *psoc,
693 struct infra_cp_stats_event *ev)
694 {
695 }
696 #endif
697 #endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
698
699 #ifdef WLAN_FEATURE_MEDIUM_ASSESS
700 static void
tgt_mc_cp_stats_extract_congestion_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)701 tgt_mc_cp_stats_extract_congestion_stats(struct wlan_objmgr_psoc *psoc,
702 struct stats_event *ev)
703 {
704 QDF_STATUS status;
705 uint8_t i, index;
706 struct request_info last_req = {0};
707 struct medium_assess_data data[WLAN_UMAC_MAX_RP_PID] = { {0} };
708 bool is_last_event = tgt_mc_cp_stats_is_last_event(ev,
709 TYPE_CONGESTION_STATS);
710
711 if (!(ev->num_pdev_stats || ev->num_pdev_extd_stats)) {
712 cp_stats_err("no congestion sta for pdev");
713 return;
714 }
715
716 status = ucfg_mc_cp_stats_get_pending_req(psoc,
717 TYPE_CONGESTION_STATS,
718 &last_req);
719 if (QDF_IS_STATUS_ERROR(status)) {
720 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
721 return;
722 }
723
724 for (i = 0; (i < ev->num_pdev_stats) && (i < WLAN_UMAC_MAX_RP_PID);
725 i++){
726 index = ev->pdev_stats[i].pdev_id;
727 if (index >= WLAN_UMAC_MAX_RP_PID) {
728 cp_stats_err("part1 pdev id error");
729 continue;
730 }
731 data[index].part1_valid = true;
732 data[index].cycle_count = ev->pdev_stats[i].cycle_count;
733 data[index].rx_clear_count = ev->pdev_stats[i].rx_clear_count;
734 data[index].tx_frame_count = ev->pdev_stats[i].tx_frame_count;
735 }
736
737 for (i = 0; (i < ev->num_pdev_extd_stats) && (i < WLAN_UMAC_MAX_RP_PID);
738 i++){
739 index = ev->pdev_extd_stats[i].pdev_id;
740 if (index >= WLAN_UMAC_MAX_RP_PID) {
741 cp_stats_err("part2 pdev id error");
742 continue;
743 }
744 data[index].part2_valid = true;
745 data[index].my_rx_count = ev->pdev_extd_stats[i].my_rx_count;
746 }
747
748 if (last_req.u.congestion_notif_cb)
749 last_req.u.congestion_notif_cb(last_req.vdev_id, data,
750 is_last_event);
751
752 }
753 #else
754 static void
tgt_mc_cp_stats_extract_congestion_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)755 tgt_mc_cp_stats_extract_congestion_stats(struct wlan_objmgr_psoc *psoc,
756 struct stats_event *ev)
757 {
758 }
759 #endif
760
761 #ifdef WLAN_FEATURE_11BE_MLO
762 static void
update_ml_vdev_id_from_stats_event(struct request_info * req,uint8_t * vdev_id)763 update_ml_vdev_id_from_stats_event(struct request_info *req,
764 uint8_t *vdev_id)
765 {
766 if (!req->ml_vdev_info.ml_vdev_count) {
767 *vdev_id = req->vdev_id;
768 return;
769 }
770
771 if (*vdev_id == WLAN_UMAC_VDEV_ID_MAX ||
772 *vdev_id >= WLAN_MAX_VDEVS) {
773 cp_stats_err("Invalid vdev[%u] sent by firmware", *vdev_id);
774 *vdev_id = WLAN_UMAC_VDEV_ID_MAX;
775 }
776 }
777 #else
778 static inline void
update_ml_vdev_id_from_stats_event(struct request_info * req,uint8_t * vdev_id)779 update_ml_vdev_id_from_stats_event(struct request_info *req,
780 uint8_t *vdev_id)
781 {
782 *vdev_id = req->vdev_id;
783 }
784 #endif
785
tgt_mc_cp_stats_extract_cca_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)786 static void tgt_mc_cp_stats_extract_cca_stats(struct wlan_objmgr_psoc *psoc,
787 struct stats_event *ev)
788 {
789 struct wlan_objmgr_vdev *vdev;
790 struct vdev_mc_cp_stats *vdev_mc_stats;
791 struct vdev_cp_stats *vdev_cp_stats_priv;
792
793 if (!ev->cca_stats)
794 return;
795
796 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
797 ev->cca_stats->vdev_id,
798 WLAN_CP_STATS_ID);
799 if (!vdev) {
800 cp_stats_err("vdev is null");
801 return;
802 }
803
804 vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
805 if (!vdev_cp_stats_priv) {
806 cp_stats_err("vdev cp stats object is null");
807 goto end;
808 }
809
810 wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
811 vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
812 vdev_mc_stats->cca.congestion = ev->cca_stats->congestion;
813 wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
814
815 end:
816 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
817 }
818
819 static void
tgt_mc_cp_stats_extract_pmf_bcn_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)820 tgt_mc_cp_stats_extract_pmf_bcn_stats(struct wlan_objmgr_psoc *psoc,
821 struct stats_event *ev)
822 {
823 QDF_STATUS status;
824 struct request_info last_req = {0};
825 struct wlan_objmgr_vdev *vdev;
826 struct vdev_mc_cp_stats *vdev_mc_stats;
827 struct vdev_cp_stats *vdev_cp_stats_priv;
828
829 status = ucfg_mc_cp_stats_get_pending_req(psoc,
830 TYPE_STATION_STATS,
831 &last_req);
832 if (QDF_IS_STATUS_ERROR(status)) {
833 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
834 return;
835 }
836
837 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req.vdev_id,
838 WLAN_CP_STATS_ID);
839 if (!vdev) {
840 cp_stats_err("vdev is null");
841 return;
842 }
843
844 vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
845 if (!vdev_cp_stats_priv) {
846 cp_stats_err("vdev cp stats object is null");
847 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
848 return;
849 }
850
851 wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
852 vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
853
854 if (ev->bcn_protect_stats.pmf_bcn_stats_valid)
855 vdev_mc_stats->pmf_bcn_stats = ev->bcn_protect_stats;
856
857 wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
858 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
859 }
860
tgt_mc_cp_stats_extract_vdev_summary_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)861 static void tgt_mc_cp_stats_extract_vdev_summary_stats(
862 struct wlan_objmgr_psoc *psoc,
863 struct stats_event *ev)
864 {
865 uint8_t i, vdev_id = WLAN_INVALID_VDEV_ID;
866 QDF_STATUS status;
867 struct wlan_objmgr_peer *peer = NULL;
868 struct request_info last_req = {0};
869 struct wlan_objmgr_vdev *vdev;
870 struct peer_mc_cp_stats *peer_mc_stats;
871 struct vdev_mc_cp_stats *vdev_mc_stats;
872 struct peer_cp_stats *peer_cp_stats_priv;
873 struct vdev_cp_stats *vdev_cp_stats_priv;
874
875 if (!ev->vdev_summary_stats)
876 return;
877
878 status = ucfg_mc_cp_stats_get_pending_req(psoc,
879 TYPE_STATION_STATS,
880 &last_req);
881 if (QDF_IS_STATUS_ERROR(status)) {
882 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
883 return;
884 }
885
886 for (i = 0; i < ev->num_summary_stats; i++) {
887 vdev_id = ev->vdev_summary_stats[i].vdev_id;
888 update_ml_vdev_id_from_stats_event(&last_req, &vdev_id);
889 if (ev->vdev_summary_stats[i].vdev_id == vdev_id)
890 break;
891 }
892
893 if (i == ev->num_summary_stats) {
894 cp_stats_debug("vdev_id %d not found", vdev_id);
895 return;
896 }
897
898 if (vdev_id == WLAN_INVALID_VDEV_ID)
899 return;
900
901 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
902 WLAN_CP_STATS_ID);
903 if (!vdev) {
904 cp_stats_err("vdev is null");
905 return;
906 }
907
908 vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
909 if (!vdev_cp_stats_priv) {
910 cp_stats_err("vdev cp stats object is null");
911 goto end;
912 }
913
914 wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
915 vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
916 qdf_mem_copy(&vdev_mc_stats->vdev_summary_stats,
917 &ev->vdev_summary_stats[i].stats,
918 sizeof(vdev_mc_stats->vdev_summary_stats));
919
920 wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
921
922 peer = wlan_objmgr_get_peer(psoc, last_req.pdev_id,
923 last_req.peer_mac_addr, WLAN_CP_STATS_ID);
924 if (!peer) {
925 cp_stats_debug("peer is null "QDF_MAC_ADDR_FMT,
926 QDF_MAC_ADDR_REF(last_req.peer_mac_addr));
927 goto end;
928 }
929
930 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
931 if (!peer_cp_stats_priv) {
932 cp_stats_err("peer cp stats object is null");
933 goto end;
934 }
935
936 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
937 peer_mc_stats = peer_cp_stats_priv->peer_stats;
938 peer_mc_stats->peer_rssi = ev->vdev_summary_stats[i].stats.rssi;
939 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
940
941 end:
942 if (peer)
943 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
944 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
945 }
946
tgt_mc_cp_stats_extract_vdev_chain_rssi_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)947 static void tgt_mc_cp_stats_extract_vdev_chain_rssi_stats(
948 struct wlan_objmgr_psoc *psoc,
949 struct stats_event *ev)
950 {
951 uint8_t i, j, vdev_id;
952 QDF_STATUS status;
953 struct request_info last_req = {0};
954 struct wlan_objmgr_vdev *vdev;
955 struct vdev_mc_cp_stats *vdev_mc_stats;
956 struct vdev_cp_stats *vdev_cp_stats_priv;
957
958 if (!ev->vdev_chain_rssi)
959 return;
960
961 status = ucfg_mc_cp_stats_get_pending_req(psoc,
962 TYPE_STATION_STATS,
963 &last_req);
964 if (QDF_IS_STATUS_ERROR(status)) {
965 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
966 return;
967 }
968
969 for (i = 0; i < ev->num_chain_rssi_stats; i++) {
970 vdev_id = ev->vdev_chain_rssi[i].vdev_id;
971 update_ml_vdev_id_from_stats_event(&last_req, &vdev_id);
972 if (ev->vdev_chain_rssi[i].vdev_id != vdev_id)
973 continue;
974
975 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
976 WLAN_CP_STATS_ID);
977 if (!vdev) {
978 cp_stats_err("vdev is null");
979 return;
980 }
981
982 vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
983 if (!vdev_cp_stats_priv) {
984 cp_stats_err("vdev cp stats object is null");
985 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
986 return;
987 }
988
989 wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
990 vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
991 for (j = 0; j < MAX_NUM_CHAINS; j++) {
992 vdev_mc_stats->chain_rssi[j] =
993 ev->vdev_chain_rssi[i].chain_rssi[j];
994 }
995 wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
996
997 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
998 }
999 }
1000
1001 static void
tgt_mc_cp_stats_extract_vdev_extd_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)1002 tgt_mc_cp_stats_extract_vdev_extd_stats(struct wlan_objmgr_psoc *psoc,
1003 struct stats_event *ev)
1004 {
1005 uint8_t i, vdev_id;
1006 QDF_STATUS status;
1007 struct request_info last_req = {0};
1008 struct wlan_objmgr_vdev *vdev;
1009 struct vdev_mc_cp_stats *vdev_mc_stats;
1010 struct vdev_cp_stats *vdev_cp_stats_priv;
1011
1012 if (!ev->vdev_extd_stats)
1013 return;
1014
1015 status = ucfg_mc_cp_stats_get_pending_req(psoc, TYPE_STATION_STATS,
1016 &last_req);
1017 if (QDF_IS_STATUS_ERROR(status)) {
1018 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
1019 return;
1020 }
1021
1022 for (i = 0; i < ev->num_vdev_extd_stats; i++) {
1023 vdev_id = ev->vdev_extd_stats[i].vdev_id;
1024
1025 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
1026 WLAN_CP_STATS_ID);
1027 if (!vdev) {
1028 cp_stats_err("vdev is null");
1029 return;
1030 }
1031
1032 vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
1033 if (!vdev_cp_stats_priv) {
1034 cp_stats_err("vdev cp stats object is null");
1035 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
1036 return;
1037 }
1038
1039 wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
1040 vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
1041 qdf_mem_copy(&vdev_mc_stats->vdev_extd_stats,
1042 &ev->vdev_extd_stats[i],
1043 sizeof(vdev_mc_stats->vdev_extd_stats));
1044
1045 wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
1046 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
1047 }
1048 }
1049
1050 static QDF_STATUS
tgt_send_vdev_mc_cp_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev,struct request_info * last_req)1051 tgt_send_vdev_mc_cp_stats(struct wlan_objmgr_psoc *psoc,
1052 struct stats_event *ev,
1053 struct request_info *last_req)
1054 {
1055 struct wlan_objmgr_vdev *vdev;
1056 struct vdev_mc_cp_stats *vdev_mc_stats;
1057 struct vdev_cp_stats *vdev_cp_stats_priv;
1058
1059 if (!ev || !last_req)
1060 return QDF_STATUS_E_NULL_VALUE;
1061
1062 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req->vdev_id,
1063 WLAN_CP_STATS_ID);
1064 if (!vdev) {
1065 cp_stats_err("vdev object is null");
1066 return QDF_STATUS_E_NULL_VALUE;
1067 }
1068
1069 vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
1070 if (!vdev_cp_stats_priv) {
1071 cp_stats_err("vdev cp stats object is null");
1072 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
1073 return QDF_STATUS_E_NULL_VALUE;
1074 }
1075
1076 wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
1077 vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
1078 ev->vdev_summary_stats[0].vdev_id = last_req->vdev_id;
1079 ev->vdev_summary_stats[0].stats = vdev_mc_stats->vdev_summary_stats;
1080 ev->vdev_chain_rssi[0].vdev_id = last_req->vdev_id;
1081 qdf_mem_copy(ev->vdev_chain_rssi[0].chain_rssi,
1082 vdev_mc_stats->chain_rssi,
1083 sizeof(vdev_mc_stats->chain_rssi));
1084 ev->tx_rate_flags = vdev_mc_stats->tx_rate_flags;
1085
1086 ev->bcn_protect_stats = vdev_mc_stats->pmf_bcn_stats;
1087
1088 qdf_mem_copy(&ev->vdev_extd_stats[0],
1089 &vdev_mc_stats->vdev_extd_stats,
1090 sizeof(vdev_mc_stats->vdev_extd_stats));
1091
1092 wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
1093 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
1094
1095 return QDF_STATUS_SUCCESS;
1096 }
1097
1098 static QDF_STATUS
tgt_send_peer_mc_cp_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev,struct request_info * last_req)1099 tgt_send_peer_mc_cp_stats(struct wlan_objmgr_psoc *psoc,
1100 struct stats_event *ev,
1101 struct request_info *last_req)
1102 {
1103 struct wlan_objmgr_peer *peer;
1104 struct peer_mc_cp_stats *peer_mc_stats;
1105 struct peer_cp_stats *peer_cp_stats_priv;
1106
1107 if (!ev || !last_req)
1108 return QDF_STATUS_E_NULL_VALUE;
1109
1110 peer = wlan_objmgr_get_peer(psoc, last_req->pdev_id,
1111 last_req->peer_mac_addr, WLAN_CP_STATS_ID);
1112 if (!peer) {
1113 cp_stats_debug("peer object is null");
1114 return QDF_STATUS_E_NULL_VALUE;
1115 }
1116
1117 peer_cp_stats_priv = wlan_cp_stats_get_peer_stats_obj(peer);
1118 if (!peer_cp_stats_priv) {
1119 cp_stats_err("peer cp stats object is null");
1120 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
1121 return QDF_STATUS_E_NULL_VALUE;
1122 }
1123
1124 wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv);
1125 peer_mc_stats = peer_cp_stats_priv->peer_stats;
1126 /*
1127 * The linkspeed returned by fw is in kbps so convert
1128 * it in units of 100kbps which is expected by UMAC
1129 */
1130 ev->tx_rate = peer_mc_stats->tx_rate / 100;
1131 ev->rx_rate = peer_mc_stats->rx_rate / 100;
1132
1133 if (peer_mc_stats->adv_stats) {
1134 ev->num_peer_adv_stats = 1;
1135 qdf_mem_copy(ev->peer_adv_stats,
1136 peer_mc_stats->adv_stats,
1137 sizeof(*peer_mc_stats->adv_stats));
1138 }
1139
1140 wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv);
1141 wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
1142
1143 return QDF_STATUS_SUCCESS;
1144 }
1145
1146 static QDF_STATUS
tgt_send_pdev_mc_cp_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev,struct request_info * last_req)1147 tgt_send_pdev_mc_cp_stats(struct wlan_objmgr_psoc *psoc,
1148 struct stats_event *ev,
1149 struct request_info *last_req)
1150 {
1151 struct wlan_objmgr_pdev *pdev;
1152 struct wlan_objmgr_vdev *vdev = NULL;
1153 struct pdev_mc_cp_stats *pdev_mc_stats;
1154 struct pdev_cp_stats *pdev_cp_stats_priv;
1155 int pdev_id;
1156
1157 if (!ev || !last_req)
1158 return QDF_STATUS_E_NULL_VALUE;
1159
1160 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req->vdev_id,
1161 WLAN_CP_STATS_ID);
1162 if (!vdev) {
1163 cp_stats_err("vdev is null");
1164 return QDF_STATUS_E_NULL_VALUE;
1165 }
1166
1167 pdev = wlan_vdev_get_pdev(vdev);
1168 if (!pdev) {
1169 cp_stats_err("pdev is null");
1170 goto end;
1171 }
1172
1173 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1174 if (pdev_id != last_req->pdev_id) {
1175 cp_stats_err("pdev_id: %d invalid", pdev_id);
1176 goto end;
1177 }
1178
1179 pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);
1180 if (!pdev_cp_stats_priv) {
1181 cp_stats_err("pdev_cp_stats_priv is null");
1182 goto end;
1183 }
1184
1185 wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv);
1186 pdev_mc_stats = pdev_cp_stats_priv->pdev_stats;
1187 qdf_mem_copy(ev->pdev_stats,
1188 pdev_mc_stats,
1189 sizeof(*pdev_mc_stats));
1190 wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
1191 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
1192
1193 return QDF_STATUS_SUCCESS;
1194
1195 end:
1196 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
1197 return QDF_STATUS_E_NULL_VALUE;
1198 }
1199
1200 static QDF_STATUS
tgt_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev * vdev,int * dbm)1201 tgt_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, int *dbm)
1202 {
1203 struct wlan_objmgr_pdev *pdev;
1204 struct pdev_mc_cp_stats *pdev_mc_stats;
1205 struct pdev_cp_stats *pdev_cp_stats_priv;
1206 struct vdev_mc_cp_stats *vdev_mc_stats;
1207 struct vdev_cp_stats *vdev_cp_stat;
1208 uint32_t vdev_power = 0;
1209
1210 vdev_cp_stat = wlan_cp_stats_get_vdev_stats_obj(vdev);
1211 if (vdev_cp_stat) {
1212 wlan_cp_stats_vdev_obj_lock(vdev_cp_stat);
1213 vdev_mc_stats = vdev_cp_stat->vdev_stats;
1214 vdev_power = vdev_mc_stats->vdev_extd_stats.vdev_tx_power;
1215 wlan_cp_stats_vdev_obj_unlock(vdev_cp_stat);
1216 if (vdev_power) {
1217 *dbm = vdev_power;
1218 return QDF_STATUS_SUCCESS;
1219 }
1220 }
1221
1222 pdev = wlan_vdev_get_pdev(vdev);
1223 pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);
1224 if (!pdev_cp_stats_priv) {
1225 cp_stats_err("pdev cp stats object is null");
1226 return QDF_STATUS_E_NULL_VALUE;
1227 }
1228
1229 wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv);
1230 pdev_mc_stats = pdev_cp_stats_priv->pdev_stats;
1231 *dbm = pdev_mc_stats->max_pwr;
1232 wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
1233
1234 return QDF_STATUS_SUCCESS;
1235 }
1236
1237 static void
tgt_mc_cp_stats_extract_vdev_and_extd_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)1238 tgt_mc_cp_stats_extract_vdev_and_extd_stats(struct wlan_objmgr_psoc *psoc,
1239 struct stats_event *ev)
1240 {
1241 QDF_STATUS status;
1242 struct request_info last_req = {0};
1243 bool pending = false;
1244 int32_t max_pwr = 0;
1245 struct wlan_objmgr_vdev *vdev = NULL;
1246
1247 status = ucfg_mc_cp_stats_get_pending_req(psoc,
1248 TYPE_CONNECTION_TX_POWER,
1249 &last_req);
1250 if (QDF_IS_STATUS_ERROR(status)) {
1251 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
1252 return;
1253 }
1254
1255 if (ev->pdev_stats)
1256 tgt_mc_cp_stats_extract_tx_power(psoc, ev, false);
1257 else if (ev->vdev_extd_stats)
1258 tgt_mc_cp_stats_extract_vdev_extd_stats(psoc, ev);
1259
1260 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req.vdev_id,
1261 WLAN_CP_STATS_ID);
1262 if (!vdev) {
1263 cp_stats_err("vdev is null");
1264 return;
1265 }
1266 tgt_mc_cp_stats_get_tx_power(vdev, &max_pwr);
1267
1268 wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
1269
1270 if (tgt_mc_cp_stats_is_last_event(ev, TYPE_CONNECTION_TX_POWER)) {
1271 ucfg_mc_cp_stats_reset_pending_req(psoc,
1272 TYPE_CONNECTION_TX_POWER,
1273 &last_req,
1274 &pending);
1275 if (last_req.u.get_tx_power_cb && pending)
1276 last_req.u.get_tx_power_cb(max_pwr, last_req.cookie);
1277 }
1278 }
1279
1280 static void
tgt_mc_cp_stats_send_raw_station_stats(struct wlan_objmgr_psoc * psoc,struct request_info * last_req)1281 tgt_mc_cp_stats_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
1282 struct request_info *last_req)
1283 {
1284 /* station_stats to be given to userspace thread */
1285 struct stats_event info = {0};
1286 void (*get_station_stats_cb)(struct stats_event *info, void *cookie);
1287 QDF_STATUS status;
1288
1289 get_station_stats_cb = last_req->u.get_station_stats_cb;
1290 if (!get_station_stats_cb) {
1291 cp_stats_err("callback is null");
1292 return;
1293 }
1294
1295 info.num_summary_stats = 1;
1296 info.num_chain_rssi_stats = 1;
1297 info.num_vdev_extd_stats = 1;
1298 info.vdev_summary_stats = qdf_mem_malloc(
1299 sizeof(*info.vdev_summary_stats));
1300 info.vdev_chain_rssi = qdf_mem_malloc(sizeof(*info.vdev_chain_rssi));
1301
1302 info.vdev_extd_stats = qdf_mem_malloc(sizeof(*info.vdev_extd_stats));
1303
1304 if (!info.vdev_summary_stats || !info.vdev_chain_rssi ||
1305 !info.vdev_extd_stats)
1306 goto end;
1307
1308 status = tgt_send_vdev_mc_cp_stats(psoc, &info, last_req);
1309 if (QDF_IS_STATUS_ERROR(status)) {
1310 cp_stats_err("tgt_send_vdev_mc_cp_stats failed");
1311 goto end;
1312 }
1313
1314 info.peer_adv_stats = qdf_mem_malloc(sizeof(*info.peer_adv_stats));
1315 if (!info.peer_adv_stats)
1316 goto end;
1317
1318 status = tgt_send_peer_mc_cp_stats(psoc, &info, last_req);
1319 if (QDF_IS_STATUS_ERROR(status)) {
1320 cp_stats_err("tgt_send_peer_mc_cp_stats failed");
1321 goto end;
1322 }
1323
1324 info.num_pdev_stats = 1;
1325 info.pdev_stats = qdf_mem_malloc(sizeof(*info.pdev_stats));
1326 if (!info.pdev_stats)
1327 goto end;
1328
1329 status = tgt_send_pdev_mc_cp_stats(psoc, &info, last_req);
1330 if (QDF_IS_STATUS_ERROR(status)) {
1331 cp_stats_err("tgt_send_pdev_mc_cp_stats failed");
1332 goto end;
1333 }
1334 end:
1335 get_station_stats_cb(&info, last_req->cookie);
1336
1337 ucfg_mc_cp_stats_free_stats_resources(&info);
1338 }
1339
1340 #ifdef WLAN_FEATURE_11BE_MLO
1341 static void
tgt_mc_cp_stats_prepare_n_send_raw_station_stats(struct wlan_objmgr_psoc * psoc,struct request_info * last_req)1342 tgt_mc_cp_stats_prepare_n_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
1343 struct request_info *last_req)
1344 {
1345 uint8_t i;
1346
1347 if (!last_req->ml_vdev_info.ml_vdev_count) {
1348 cp_stats_nofl_debug("Invoking get_station_cb for vdev_id[%d]",
1349 last_req->vdev_id);
1350 tgt_mc_cp_stats_send_raw_station_stats(psoc, last_req);
1351 return;
1352 }
1353
1354 for (i = 0; i < last_req->ml_vdev_info.ml_vdev_count; i++) {
1355 last_req->vdev_id = last_req->ml_vdev_info.ml_vdev_id[i];
1356 qdf_mem_copy(last_req->peer_mac_addr,
1357 &(last_req->ml_peer_mac_addr[i][0]),
1358 QDF_MAC_ADDR_SIZE);
1359 cp_stats_nofl_debug("Invoking get_station_cb for ml vdev_id[%d]",
1360 last_req->vdev_id);
1361 tgt_mc_cp_stats_send_raw_station_stats(psoc, last_req);
1362 }
1363 }
1364 #else
1365 static void
tgt_mc_cp_stats_prepare_n_send_raw_station_stats(struct wlan_objmgr_psoc * psoc,struct request_info * last_req)1366 tgt_mc_cp_stats_prepare_n_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
1367 struct request_info *last_req)
1368 {
1369 tgt_mc_cp_stats_send_raw_station_stats(psoc, last_req);
1370 }
1371 #endif
1372
tgt_mc_cp_stats_extract_station_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)1373 static void tgt_mc_cp_stats_extract_station_stats(
1374 struct wlan_objmgr_psoc *psoc,
1375 struct stats_event *ev)
1376 {
1377 QDF_STATUS status;
1378 struct request_info last_req = {0};
1379 bool pending = false;
1380
1381 status = ucfg_mc_cp_stats_get_pending_req(psoc,
1382 TYPE_STATION_STATS,
1383 &last_req);
1384 if (QDF_IS_STATUS_ERROR(status)) {
1385 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
1386 return;
1387 }
1388
1389 tgt_mc_cp_stats_extract_tx_power(psoc, ev, true);
1390 tgt_mc_cp_stats_extract_peer_stats(psoc, ev, true);
1391 tgt_mc_cp_stats_extract_vdev_summary_stats(psoc, ev);
1392 tgt_mc_cp_stats_extract_vdev_chain_rssi_stats(psoc, ev);
1393 tgt_mc_cp_stats_extract_pmf_bcn_stats(psoc, ev);
1394 tgt_mc_cp_stats_extract_vdev_extd_stats(psoc, ev);
1395
1396 /*
1397 * PEER stats are the last stats sent for get_station statistics.
1398 * reset type_map bit for station stats .
1399 */
1400 if (tgt_mc_cp_stats_is_last_event(ev, TYPE_STATION_STATS)) {
1401 ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS,
1402 &last_req,
1403 &pending);
1404 if (pending && last_req.u.get_station_stats_cb)
1405 tgt_mc_cp_stats_prepare_n_send_raw_station_stats(
1406 psoc, &last_req);
1407 }
1408 }
1409
tgt_mc_cp_send_lost_link_stats(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)1410 static void tgt_mc_cp_send_lost_link_stats(struct wlan_objmgr_psoc *psoc,
1411 struct stats_event *ev)
1412 {
1413 struct psoc_cp_stats *psoc_cp_stats_priv;
1414
1415 psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc);
1416 if (psoc_cp_stats_priv && psoc_cp_stats_priv->legacy_stats_cb)
1417 psoc_cp_stats_priv->legacy_stats_cb(ev);
1418 }
1419
1420 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
tgt_mc_cp_stats_process_infra_stats_event(struct wlan_objmgr_psoc * psoc,struct infra_cp_stats_event * infra_event)1421 QDF_STATUS tgt_mc_cp_stats_process_infra_stats_event(
1422 struct wlan_objmgr_psoc *psoc,
1423 struct infra_cp_stats_event *infra_event)
1424 {
1425 if (!infra_event)
1426 return QDF_STATUS_E_NULL_VALUE;
1427
1428 tgt_mc_infra_cp_stats_extract_twt_stats(psoc, infra_event);
1429
1430 return QDF_STATUS_SUCCESS;
1431 }
1432 #endif
1433
tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc * psoc,struct stats_event * ev)1434 QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
1435 struct stats_event *ev)
1436 {
1437 if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_CONNECTION_TX_POWER))
1438 tgt_mc_cp_stats_extract_vdev_and_extd_stats(psoc, ev);
1439
1440 if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_PEER_STATS))
1441 tgt_mc_cp_stats_extract_peer_stats(psoc, ev, false);
1442
1443 if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_STATION_STATS))
1444 tgt_mc_cp_stats_extract_station_stats(psoc, ev);
1445
1446 if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_MIB_STATS))
1447 tgt_mc_cp_stats_extract_mib_stats(psoc, ev);
1448
1449 if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_PEER_STATS_INFO_EXT))
1450 tgt_mc_cp_stats_extract_peer_stats_info_ext(psoc, ev);
1451
1452 if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_CONGESTION_STATS))
1453 tgt_mc_cp_stats_extract_congestion_stats(psoc, ev);
1454
1455 tgt_mc_cp_stats_extract_cca_stats(psoc, ev);
1456
1457 tgt_mc_cp_send_lost_link_stats(psoc, ev);
1458 return QDF_STATUS_SUCCESS;
1459 }
1460
1461 #ifdef WLAN_FEATURE_BIG_DATA_STATS
1462 QDF_STATUS
tgt_mc_cp_stats_process_big_data_stats_event(struct wlan_objmgr_psoc * psoc,struct big_data_stats_event * ev)1463 tgt_mc_cp_stats_process_big_data_stats_event(struct wlan_objmgr_psoc *psoc,
1464 struct big_data_stats_event *ev)
1465 {
1466 QDF_STATUS status;
1467 struct request_info last_req = {0};
1468 bool pending = false;
1469
1470 if (!ev) {
1471 cp_stats_err("invalid data");
1472 return QDF_STATUS_E_INVAL;
1473 }
1474
1475 status = ucfg_mc_cp_stats_get_pending_req(psoc,
1476 TYPE_BIG_DATA_STATS,
1477 &last_req);
1478 if (QDF_IS_STATUS_ERROR(status)) {
1479 cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
1480 return QDF_STATUS_E_FAILURE;
1481 }
1482
1483 ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_BIG_DATA_STATS,
1484 &last_req, &pending);
1485
1486 if (last_req.u.get_big_data_stats_cb && pending) {
1487 last_req.u.get_big_data_stats_cb(ev, last_req.cookie);
1488 last_req.u.get_big_data_stats_cb = NULL;
1489 } else {
1490 cp_stats_err("callback to send big data stats not found");
1491 return QDF_STATUS_E_FAILURE;
1492 }
1493
1494 return QDF_STATUS_SUCCESS;
1495 }
1496 #endif
1497
tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc * psoc,uint32_t reason,struct wake_lock_stats * stats,uint32_t * unspecified_wake_count)1498 QDF_STATUS tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc,
1499 uint32_t reason,
1500 struct wake_lock_stats *stats,
1501 uint32_t *unspecified_wake_count)
1502 {
1503 struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
1504
1505 tx_ops = target_if_cp_stats_get_tx_ops(psoc);
1506 if (!tx_ops || !tx_ops->inc_wake_lock_stats)
1507 return QDF_STATUS_E_NULL_VALUE;
1508
1509 tx_ops->inc_wake_lock_stats(reason, stats, unspecified_wake_count);
1510
1511 return QDF_STATUS_SUCCESS;
1512 }
1513
tgt_send_mc_cp_stats_req(struct wlan_objmgr_psoc * psoc,enum stats_req_type type,struct request_info * req)1514 QDF_STATUS tgt_send_mc_cp_stats_req(struct wlan_objmgr_psoc *psoc,
1515 enum stats_req_type type,
1516 struct request_info *req)
1517 {
1518 struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
1519 QDF_STATUS status;
1520
1521 tx_ops = target_if_cp_stats_get_tx_ops(psoc);
1522 if (!tx_ops) {
1523 cp_stats_err("could not get tx_ops");
1524 return QDF_STATUS_E_NULL_VALUE;
1525 }
1526
1527 switch (type) {
1528 case TYPE_PEER_STATS_INFO_EXT:
1529 if (!tx_ops->send_req_peer_stats) {
1530 cp_stats_err("could not get send_req_peer_stats");
1531 return QDF_STATUS_E_NULL_VALUE;
1532 }
1533 status = tx_ops->send_req_peer_stats(psoc, req);
1534 break;
1535 case TYPE_BIG_DATA_STATS:
1536 status = send_big_data_stats_req(tx_ops, psoc, req);
1537 break;
1538 default:
1539 if (!tx_ops->send_req_stats) {
1540 cp_stats_err("could not get send_req_stats");
1541 return QDF_STATUS_E_NULL_VALUE;
1542 }
1543 status = tx_ops->send_req_stats(psoc, type, req);
1544 }
1545
1546 return status;
1547 }
1548
tgt_set_pdev_stats_update_period(struct wlan_objmgr_psoc * psoc,uint8_t pdev_id,uint32_t val)1549 QDF_STATUS tgt_set_pdev_stats_update_period(struct wlan_objmgr_psoc *psoc,
1550 uint8_t pdev_id, uint32_t val)
1551 {
1552 struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
1553 QDF_STATUS status;
1554
1555 tx_ops = target_if_cp_stats_get_tx_ops(psoc);
1556 if (!tx_ops || !tx_ops->set_pdev_stats_update_period) {
1557 cp_stats_err("could not get tx_ops");
1558 return QDF_STATUS_E_NULL_VALUE;
1559 }
1560 status = tx_ops->set_pdev_stats_update_period(psoc, pdev_id, val);
1561
1562 return status;
1563 }
1564
1565