1 /*
2 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include "wlan_mlo_mgr_main.h"
19 #include "qdf_module.h"
20 #include "qdf_types.h"
21 #include "wlan_cmn.h"
22 #include "wlan_mlo_mgr_msgq.h"
23 #include "wlan_objmgr_peer_obj.h"
24 #include "wlan_mlo_mgr_peer.h"
25 #include "wlan_mlo_mgr_ap.h"
26 #include "wlan_crypto_global_api.h"
27 #include "wlan_mlo_mgr_setup.h"
28 #include "wlan_utility.h"
29 #include "wlan_mlo_epcs.h"
30
mlo_partner_peer_create_post(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev_link,struct wlan_mlo_peer_context * ml_peer,qdf_nbuf_t frm_buf,struct mlo_partner_info * ml_info)31 static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
32 struct wlan_objmgr_vdev *vdev_link,
33 struct wlan_mlo_peer_context *ml_peer,
34 qdf_nbuf_t frm_buf,
35 struct mlo_partner_info *ml_info)
36 {
37 struct peer_create_notif_s peer_create;
38 QDF_STATUS status;
39 uint8_t i;
40 uint8_t link_id;
41
42 if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) ==
43 QDF_STATUS_SUCCESS) {
44 peer_create.vdev_link = vdev_link;
45 } else {
46 mlo_err("VDEV is not in created state");
47 return;
48 }
49
50 wlan_mlo_peer_get_ref(ml_peer);
51 peer_create.ml_peer = ml_peer;
52 link_id = wlan_vdev_get_link_id(vdev_link);
53 for (i = 0; i < ml_info->num_partner_links; i++) {
54 if (link_id != ml_info->partner_link_info[i].link_id)
55 continue;
56
57 qdf_copy_macaddr(&peer_create.addr,
58 &ml_info->partner_link_info[i].link_addr);
59 break;
60 }
61
62 status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf);
63
64 if (QDF_IS_STATUS_ERROR(status)) {
65 wlan_mlo_peer_release_ref(ml_peer);
66 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
67 mlo_err("nbuf clone is failed");
68 return;
69 }
70
71 status = mlo_msgq_post(MLO_PEER_CREATE, ml_dev, &peer_create);
72 if (status != QDF_STATUS_SUCCESS) {
73 qdf_nbuf_free(frm_buf);
74 wlan_mlo_peer_release_ref(ml_peer);
75 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
76 }
77 }
78
mlo_partner_peer_reassoc_post(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev_link,struct wlan_mlo_peer_context * ml_peer,qdf_nbuf_t frm_buf,struct mlo_partner_info * ml_info)79 static void mlo_partner_peer_reassoc_post(struct wlan_mlo_dev_context *ml_dev,
80 struct wlan_objmgr_vdev *vdev_link,
81 struct wlan_mlo_peer_context *ml_peer,
82 qdf_nbuf_t frm_buf,
83 struct mlo_partner_info *ml_info)
84 {
85 struct peer_create_notif_s peer_create;
86 QDF_STATUS status;
87 uint8_t i;
88 uint8_t link_id;
89
90 if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) ==
91 QDF_STATUS_SUCCESS) {
92 peer_create.vdev_link = vdev_link;
93 } else {
94 mlo_err("VDEV is not in created state");
95 return;
96 }
97
98 wlan_mlo_peer_get_ref(ml_peer);
99 peer_create.ml_peer = ml_peer;
100 link_id = wlan_vdev_get_link_id(vdev_link);
101 for (i = 0; i < ml_info->num_partner_links; i++) {
102 if (link_id != ml_info->partner_link_info[i].link_id)
103 continue;
104
105 qdf_copy_macaddr(&peer_create.addr,
106 &ml_info->partner_link_info[i].link_addr);
107 break;
108 }
109
110 status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf);
111
112 if (QDF_IS_STATUS_ERROR(status)) {
113 wlan_mlo_peer_release_ref(ml_peer);
114 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
115 mlo_err("nbuf clone is failed");
116 return;
117 }
118
119 status = mlo_msgq_post(MLO_PEER_REASSOC, ml_dev, &peer_create);
120 if (status != QDF_STATUS_SUCCESS) {
121 qdf_nbuf_free(frm_buf);
122 wlan_mlo_peer_release_ref(ml_peer);
123 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
124 }
125 }
126
mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_peer * peer)127 static void mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context *ml_dev,
128 struct wlan_objmgr_peer *peer)
129 {
130 struct peer_assoc_notify_s peer_assoc;
131 QDF_STATUS status;
132
133 peer_assoc.peer = peer;
134 status = mlo_msgq_post(MLO_PEER_ASSOC, ml_dev, &peer_assoc);
135 if (status != QDF_STATUS_SUCCESS)
136 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
137 }
138
mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_peer * peer)139 static void mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context *ml_dev,
140 struct wlan_objmgr_peer *peer)
141 {
142 struct peer_assoc_fail_notify_s peer_assoc_fail;
143 QDF_STATUS status;
144
145 peer_assoc_fail.peer = peer;
146 status = mlo_msgq_post(MLO_PEER_ASSOC_FAIL, ml_dev, &peer_assoc_fail);
147 if (status != QDF_STATUS_SUCCESS)
148 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
149 }
150
mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_peer * peer)151 static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev,
152 struct wlan_objmgr_peer *peer)
153 {
154 struct peer_discon_notify_s peer_disconn;
155 QDF_STATUS status;
156 struct wlan_objmgr_vdev *vdev;
157 enum QDF_OPMODE opmode;
158
159 vdev = wlan_peer_get_vdev(peer);
160 opmode = wlan_vdev_mlme_get_opmode(vdev);
161
162 if (opmode == QDF_SAP_MODE) {
163 peer_disconn.peer = peer;
164 status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev,
165 &peer_disconn);
166 if (status != QDF_STATUS_SUCCESS)
167 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
168 } else {
169 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
170 }
171 }
172
mlo_link_peer_deauth_init(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_peer * peer,uint8_t is_disassoc)173 static void mlo_link_peer_deauth_init(struct wlan_mlo_dev_context *ml_dev,
174 struct wlan_objmgr_peer *peer,
175 uint8_t is_disassoc)
176 {
177 struct peer_deauth_notify_s peer_deauth;
178 QDF_STATUS status;
179
180 peer_deauth.peer = peer;
181 peer_deauth.is_disassoc = is_disassoc;
182 status = mlo_msgq_post(MLO_PEER_DEAUTH, ml_dev, &peer_deauth);
183 if (status != QDF_STATUS_SUCCESS)
184 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
185 }
186
187 #ifdef UMAC_MLO_AUTH_DEFER
mlo_peer_process_pending_auth(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer)188 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
189 struct wlan_mlo_peer_context *ml_peer)
190 {
191 struct peer_auth_process_notif_s peer_auth;
192 struct mlpeer_auth_params *recv_auth;
193 uint8_t i;
194 QDF_STATUS status;
195
196 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
197 mlo_peer_lock_acquire(ml_peer);
198 recv_auth = ml_peer->pending_auth[i];
199 if (!recv_auth) {
200 mlo_peer_lock_release(ml_peer);
201 continue;
202 }
203 peer_auth.auth_params = recv_auth;
204 ml_peer->pending_auth[i] = NULL;
205
206 mlo_peer_lock_release(ml_peer);
207
208 status = mlo_msgq_post(MLO_PEER_PENDING_AUTH, ml_dev,
209 &peer_auth);
210 if (QDF_IS_STATUS_ERROR(status))
211 mlo_peer_free_auth_param(peer_auth.auth_params);
212 }
213 }
214 #else
mlo_peer_process_pending_auth(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer)215 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
216 struct wlan_mlo_peer_context *ml_peer)
217 {
218 }
219 #endif
220
221 QDF_STATUS
wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context * ml_peer)222 wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context *ml_peer)
223 {
224 QDF_STATUS status;
225
226 if (!ml_peer)
227 return QDF_STATUS_E_FAILURE;
228
229 mlo_peer_lock_acquire(ml_peer);
230
231 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED)
232 status = QDF_STATUS_SUCCESS;
233 else
234 status = QDF_STATUS_E_FAILURE;
235
236 mlo_peer_lock_release(ml_peer);
237
238 return status;
239 }
240
wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context * ml_peer)241 QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer)
242 {
243 QDF_STATUS status;
244
245 if (!ml_peer)
246 return QDF_STATUS_E_FAILURE;
247
248 mlo_peer_lock_acquire(ml_peer);
249
250 if (ml_peer->mlpeer_state == ML_PEER_ASSOC_DONE)
251 status = QDF_STATUS_SUCCESS;
252 else
253 status = QDF_STATUS_E_FAILURE;
254
255 mlo_peer_lock_release(ml_peer);
256
257 return status;
258 }
259
260 qdf_export_symbol(wlan_mlo_peer_is_assoc_done);
261
wlan_mlo_peer_get_assoc_peer(struct wlan_mlo_peer_context * ml_peer)262 struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer(
263 struct wlan_mlo_peer_context *ml_peer)
264 {
265 struct wlan_mlo_link_peer_entry *peer_entry;
266 struct wlan_objmgr_peer *assoc_peer = NULL;
267
268 if (!ml_peer)
269 return NULL;
270
271 mlo_peer_lock_acquire(ml_peer);
272
273 peer_entry = &ml_peer->peer_list[0];
274
275 if (peer_entry->link_peer)
276 assoc_peer = peer_entry->link_peer;
277
278 mlo_peer_lock_release(ml_peer);
279
280 return assoc_peer;
281 }
282
283 qdf_export_symbol(wlan_mlo_peer_get_assoc_peer);
284
wlan_mlo_peer_get_bridge_peer(struct wlan_mlo_peer_context * ml_peer)285 struct wlan_objmgr_peer *wlan_mlo_peer_get_bridge_peer(
286 struct wlan_mlo_peer_context *ml_peer)
287 {
288 struct wlan_mlo_link_peer_entry *peer_entry = NULL;
289 struct wlan_objmgr_peer *bridge_peer = NULL;
290 struct wlan_objmgr_peer *link_peer = NULL;
291 int i = 0;
292
293 if (!ml_peer)
294 return NULL;
295
296 mlo_peer_lock_acquire(ml_peer);
297
298 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
299 peer_entry = &ml_peer->peer_list[i];
300 if (!peer_entry)
301 continue;
302
303 link_peer = peer_entry->link_peer;
304 if (!link_peer)
305 continue;
306
307 if (wlan_peer_get_peer_type(link_peer) ==
308 WLAN_PEER_MLO_BRIDGE) {
309 if (peer_entry->is_primary)
310 bridge_peer = link_peer;
311 else
312 mlo_err("Bridge peer is not primary");
313
314 break;
315 }
316 }
317 mlo_peer_lock_release(ml_peer);
318
319 return bridge_peer;
320 }
321
322 qdf_export_symbol(wlan_mlo_peer_get_bridge_peer);
323
324 struct wlan_objmgr_vdev *
wlan_mlo_peer_get_primary_link_vdev(struct wlan_mlo_peer_context * ml_peer)325 wlan_mlo_peer_get_primary_link_vdev(struct wlan_mlo_peer_context *ml_peer)
326 {
327 struct wlan_mlo_link_peer_entry *peer_entry = NULL;
328 struct wlan_objmgr_peer *link_peer;
329 struct wlan_objmgr_vdev *link_vdev;
330 uint8_t i;
331
332 if (!ml_peer) {
333 mlo_err("ml_peer is null");
334 return NULL;
335 }
336 mlo_peer_lock_acquire(ml_peer);
337
338 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
339 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
340 mlo_peer_lock_release(ml_peer);
341 mlo_err("ml_peer is not created and association is not done");
342 return NULL;
343 }
344
345 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
346 peer_entry = &ml_peer->peer_list[i];
347 link_peer = peer_entry->link_peer;
348 if (!link_peer)
349 continue;
350
351 if (peer_entry->is_primary) {
352 link_vdev = wlan_peer_get_vdev(link_peer);
353 if (!link_vdev) {
354 mlo_peer_lock_release(ml_peer);
355 mlo_err("link vdev not found");
356 return NULL;
357 }
358 if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_MLO_MGR_ID) !=
359 QDF_STATUS_SUCCESS) {
360 mlo_peer_lock_release(ml_peer);
361 mlo_err("taking ref failed");
362 return NULL;
363 }
364 mlo_peer_lock_release(ml_peer);
365 return link_vdev;
366 }
367 }
368 mlo_peer_lock_release(ml_peer);
369 mlo_err("None of the peer is designated as primary");
370
371 return NULL;
372 }
373
mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer)374 bool mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
375 struct wlan_objmgr_peer *peer)
376 {
377 struct wlan_mlo_link_peer_entry *peer_entry;
378 bool is_assoc_peer = false;
379
380 if (!ml_peer || !peer)
381 return is_assoc_peer;
382
383 peer_entry = &ml_peer->peer_list[0];
384
385 if (peer_entry->link_peer == peer)
386 is_assoc_peer = true;
387
388 return is_assoc_peer;
389 }
390
wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer)391 bool wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
392 struct wlan_objmgr_peer *peer)
393 {
394 bool is_assoc_peer = false;
395
396 if (!ml_peer || !peer)
397 return is_assoc_peer;
398
399 mlo_peer_lock_acquire(ml_peer);
400
401 is_assoc_peer = mlo_peer_is_assoc_peer(ml_peer, peer);
402
403 mlo_peer_lock_release(ml_peer);
404
405 return is_assoc_peer;
406 }
407
wlan_mlo_peer_is_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer)408 bool wlan_mlo_peer_is_link_peer(struct wlan_mlo_peer_context *ml_peer,
409 struct wlan_objmgr_peer *peer)
410 {
411 struct wlan_mlo_link_peer_entry *peer_entry;
412 bool is_link_peer = false;
413 uint16_t i;
414
415 if (!ml_peer || !peer)
416 return is_link_peer;
417
418 mlo_peer_lock_acquire(ml_peer);
419
420 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
421 peer_entry = &ml_peer->peer_list[i];
422 if (!peer_entry->link_peer)
423 continue;
424
425 if (peer == peer_entry->link_peer) {
426 is_link_peer = true;
427 break;
428 }
429 }
430
431 mlo_peer_lock_release(ml_peer);
432
433 return is_link_peer;
434 }
435
wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer * assoc_peer)436 void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer)
437 {
438 struct wlan_mlo_dev_context *ml_dev;
439 struct wlan_mlo_peer_context *ml_peer;
440 struct wlan_objmgr_peer *link_peer;
441 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
442 struct wlan_mlo_link_peer_entry *peer_entry;
443 uint16_t i;
444
445 ml_peer = assoc_peer->mlo_peer_ctx;
446 if (!ml_peer)
447 return;
448
449 mlo_peer_lock_acquire(ml_peer);
450
451 if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
452 mlo_peer_lock_release(ml_peer);
453 return;
454 }
455
456 ml_peer->mlpeer_state = ML_PEER_ASSOC_DONE;
457 ml_dev = ml_peer->ml_dev;
458
459 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
460 link_peers[i] = NULL;
461 peer_entry = &ml_peer->peer_list[i];
462
463 if (!peer_entry->link_peer)
464 continue;
465
466 if (peer_entry->link_peer == assoc_peer)
467 continue;
468
469 link_peer = peer_entry->link_peer;
470
471 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
472 QDF_STATUS_SUCCESS)
473 continue;
474
475 link_peers[i] = link_peer;
476 }
477 wlan_mlo_peer_wsi_link_add(ml_peer);
478 mlo_peer_lock_release(ml_peer);
479
480 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
481 if (!link_peers[i])
482 continue;
483
484 /* Prepare and queue message */
485 mlo_link_peer_assoc_notify(ml_dev, link_peers[i]);
486 }
487 }
488
wlan_mlo_link_peer_assoc_set(struct wlan_objmgr_peer * peer,bool is_sent)489 void wlan_mlo_link_peer_assoc_set(struct wlan_objmgr_peer *peer, bool is_sent)
490 {
491 struct wlan_mlo_peer_context *ml_peer;
492 struct wlan_mlo_link_peer_entry *peer_entry;
493 uint16_t i;
494
495 ml_peer = peer->mlo_peer_ctx;
496 if (!ml_peer)
497 return;
498
499 mlo_peer_lock_acquire(ml_peer);
500
501 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
502 peer_entry = &ml_peer->peer_list[i];
503
504 if (!peer_entry->link_peer)
505 continue;
506
507 if (peer_entry->link_peer == peer) {
508 peer_entry->peer_assoc_sent = is_sent;
509 break;
510 }
511 }
512 mlo_peer_lock_release(ml_peer);
513 }
514
515 qdf_export_symbol(wlan_mlo_link_peer_assoc_set);
516
wlan_mlo_peer_get_del_hw_bitmap(struct wlan_objmgr_peer * peer,uint32_t * hw_link_id_bitmap)517 void wlan_mlo_peer_get_del_hw_bitmap(struct wlan_objmgr_peer *peer,
518 uint32_t *hw_link_id_bitmap)
519 {
520 struct wlan_mlo_peer_context *ml_peer;
521 struct wlan_mlo_link_peer_entry *peer_entry;
522 uint16_t i;
523
524 ml_peer = peer->mlo_peer_ctx;
525 if (!ml_peer)
526 return;
527
528 mlo_peer_lock_acquire(ml_peer);
529
530 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
531 peer_entry = &ml_peer->peer_list[i];
532
533 if (!peer_entry->link_peer)
534 continue;
535
536 if (peer_entry->link_peer == peer) {
537 /* Peer assoc is not sent, no need to send bitmap */
538 if (!peer_entry->peer_assoc_sent)
539 break;
540
541 continue;
542 }
543 if (!peer_entry->peer_assoc_sent)
544 *hw_link_id_bitmap |= 1 << peer_entry->hw_link_id;
545 }
546 mlo_peer_lock_release(ml_peer);
547 }
548
549 qdf_export_symbol(wlan_mlo_peer_get_del_hw_bitmap);
550
551 void
wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * src_peer,uint8_t is_disassoc)552 wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer,
553 struct wlan_objmgr_peer *src_peer,
554 uint8_t is_disassoc)
555 {
556 struct wlan_mlo_dev_context *ml_dev;
557 struct wlan_objmgr_peer *link_peer;
558 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
559 struct wlan_mlo_link_peer_entry *peer_entry;
560 uint16_t i;
561 uint8_t deauth_sent = 0;
562
563 if (!ml_peer)
564 return;
565
566 mlo_peer_lock_acquire(ml_peer);
567
568 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
569 mlo_peer_lock_release(ml_peer);
570 return;
571 }
572
573 ml_dev = ml_peer->ml_dev;
574
575 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
576 link_peers[i] = NULL;
577 peer_entry = &ml_peer->peer_list[i];
578 if (!peer_entry->link_peer)
579 continue;
580
581 link_peer = peer_entry->link_peer;
582
583 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
584 QDF_STATUS_SUCCESS)
585 continue;
586
587 link_peers[i] = link_peer;
588 }
589
590 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
591
592 mlo_peer_lock_release(ml_peer);
593
594 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
595 if (!link_peers[i])
596 continue;
597
598 /* Prepare and queue message */
599 /* skip sending deauth on src peer */
600 if ((deauth_sent) ||
601 (src_peer && (src_peer == link_peers[i]))) {
602 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
603 } else {
604 mlo_link_peer_deauth_init(ml_dev, link_peers[i],
605 is_disassoc);
606 deauth_sent = 1;
607 }
608 }
609 }
610
611 qdf_export_symbol(wlan_mlo_peer_deauth_init);
612
wlan_mlo_peer_delete(struct wlan_mlo_peer_context * ml_peer)613 void wlan_mlo_peer_delete(struct wlan_mlo_peer_context *ml_peer)
614 {
615 struct wlan_mlo_dev_context *ml_dev;
616 struct wlan_objmgr_peer *link_peer;
617 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
618 struct wlan_mlo_link_peer_entry *peer_entry;
619 uint16_t i;
620
621 if (!ml_peer)
622 return;
623
624 mlo_peer_lock_acquire(ml_peer);
625
626 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
627 mlo_peer_lock_release(ml_peer);
628 return;
629 }
630
631 ml_dev = ml_peer->ml_dev;
632
633 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
634 link_peers[i] = NULL;
635 peer_entry = &ml_peer->peer_list[i];
636 if (!peer_entry->link_peer)
637 continue;
638
639 link_peer = peer_entry->link_peer;
640
641 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
642 QDF_STATUS_SUCCESS)
643 continue;
644
645 link_peers[i] = link_peer;
646 }
647
648 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
649
650 mlo_peer_lock_release(ml_peer);
651
652 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
653 if (!link_peers[i])
654 continue;
655
656 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
657 }
658 }
659
660 void
wlan_mlo_partner_peer_create_failed_notify(struct wlan_mlo_peer_context * ml_peer)661 wlan_mlo_partner_peer_create_failed_notify(
662 struct wlan_mlo_peer_context *ml_peer)
663 {
664 struct wlan_mlo_dev_context *ml_dev;
665 struct wlan_objmgr_peer *link_peer;
666 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
667 struct wlan_mlo_link_peer_entry *peer_entry;
668 uint16_t i;
669
670 if (!ml_peer)
671 return;
672
673 mlo_peer_lock_acquire(ml_peer);
674
675 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
676 mlo_peer_lock_release(ml_peer);
677 return;
678 }
679
680 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
681 ml_dev = ml_peer->ml_dev;
682
683 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
684 link_peers[i] = NULL;
685 peer_entry = &ml_peer->peer_list[i];
686 if (!peer_entry->link_peer)
687 continue;
688
689 link_peer = peer_entry->link_peer;
690 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
691 QDF_STATUS_SUCCESS)
692 continue;
693
694 link_peers[i] = link_peer;
695 }
696 mlo_peer_lock_release(ml_peer);
697
698 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
699 if (!link_peers[i])
700 continue;
701
702 /* Prepare and queue message */
703 if (i == 0)
704 mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]);
705 else
706 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
707 }
708 }
709
wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer * src_peer)710 void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer)
711 {
712 struct wlan_mlo_dev_context *ml_dev;
713 struct wlan_mlo_peer_context *ml_peer;
714 struct wlan_objmgr_peer *link_peer;
715 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
716 struct wlan_mlo_link_peer_entry *peer_entry;
717 struct wlan_objmgr_vdev *vdev = NULL;
718 uint16_t i;
719
720 ml_peer = src_peer->mlo_peer_ctx;
721 if (!ml_peer)
722 return;
723
724 vdev = wlan_peer_get_vdev(src_peer);
725 if (!vdev)
726 return;
727
728 /* Do not change peer state to disconnect initiated for
729 * link switch case, this can lead to not sending deauth frame
730 * incase of actual disconnect and AP might drop the next connect
731 * request as it might think STA is still in connected state.
732 */
733 if (wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev))
734 return;
735
736 mlo_peer_lock_acquire(ml_peer);
737
738 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
739 mlo_peer_lock_release(ml_peer);
740 return;
741 }
742
743 wlan_mlo_peer_wsi_link_delete(ml_peer);
744
745 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
746
747 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
748 mlo_peer_lock_release(ml_peer);
749 return;
750 }
751
752 ml_dev = ml_peer->ml_dev;
753 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
754 link_peers[i] = NULL;
755 peer_entry = &ml_peer->peer_list[i];
756 if (!peer_entry->link_peer) {
757 mlo_debug("link peer is null");
758 continue;
759 }
760
761 if (peer_entry->link_peer == src_peer)
762 continue;
763
764 link_peer = peer_entry->link_peer;
765 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
766 QDF_STATUS_SUCCESS)
767 continue;
768
769 link_peers[i] = link_peer;
770 }
771 mlo_peer_lock_release(ml_peer);
772
773 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
774 if (!link_peers[i])
775 continue;
776
777 /* Prepare and queue message */
778 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
779 }
780 }
781
782 qdf_export_symbol(wlan_mlo_partner_peer_disconnect_notify);
783
mlo_peer_populate_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * link_peer)784 static void mlo_peer_populate_link_peer(
785 struct wlan_mlo_peer_context *ml_peer,
786 struct wlan_objmgr_peer *link_peer)
787 {
788 mlo_peer_lock_acquire(ml_peer);
789 wlan_mlo_peer_get_ref(ml_peer);
790 link_peer->mlo_peer_ctx = ml_peer;
791 mlo_peer_lock_release(ml_peer);
792 }
793
mlo_reset_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * link_peer)794 static void mlo_reset_link_peer(
795 struct wlan_mlo_peer_context *ml_peer,
796 struct wlan_objmgr_peer *link_peer)
797 {
798 mlo_peer_lock_acquire(ml_peer);
799 link_peer->mlo_peer_ctx = NULL;
800 wlan_peer_clear_mlo(link_peer);
801 mlo_peer_lock_release(ml_peer);
802 }
803
mlo_peer_free(struct wlan_mlo_peer_context * ml_peer)804 static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer)
805 {
806 struct wlan_mlo_dev_context *ml_dev;
807
808 ml_dev = ml_peer->ml_dev;
809 if (!ml_dev) {
810 mlo_err("ML DEV is NULL");
811 return;
812 }
813
814 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT " is freed",
815 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
816 mlo_peer_lock_destroy(ml_peer);
817 epcs_dev_peer_lock_destroy(&ml_peer->epcs_info);
818 mlo_ap_ml_ptqm_peerid_free(ml_dev, ml_peer->mlo_peer_id);
819 mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id);
820 mlo_peer_free_aid(ml_dev, ml_peer);
821 mlo_peer_free_primary_umac(ml_dev, ml_peer);
822 qdf_mem_free(ml_peer);
823 }
824
mlo_peer_cleanup(struct wlan_mlo_peer_context * ml_peer)825 void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer)
826 {
827 struct wlan_mlo_dev_context *ml_dev;
828
829 if (!ml_peer) {
830 mlo_err("ML PEER is NULL");
831 return;
832 }
833 ml_dev = ml_peer->ml_dev;
834 if (!ml_dev) {
835 mlo_err("ML DEV is NULL");
836 return;
837 }
838
839 mlo_dev_mlpeer_detach(ml_dev, ml_peer);
840 /* If any Auth req is received during ML peer delete */
841 mlo_peer_process_pending_auth(ml_dev, ml_peer);
842 mlo_peer_free(ml_peer);
843 }
844
mlo_peer_attach_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * link_peer,qdf_nbuf_t frm_buf)845 static QDF_STATUS mlo_peer_attach_link_peer(
846 struct wlan_mlo_peer_context *ml_peer,
847 struct wlan_objmgr_peer *link_peer,
848 qdf_nbuf_t frm_buf)
849 {
850 struct wlan_mlo_link_peer_entry *peer_entry;
851 QDF_STATUS status = QDF_STATUS_E_RESOURCES;
852 struct wlan_objmgr_pdev *pdev;
853 struct wlan_objmgr_vdev *vdev;
854 uint16_t i;
855
856 if (!link_peer)
857 return QDF_STATUS_E_FAILURE;
858
859 vdev = wlan_peer_get_vdev(link_peer);
860 if (!vdev)
861 return QDF_STATUS_E_FAILURE;
862
863 mlo_peer_lock_acquire(ml_peer);
864
865 if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
866 mlo_peer_lock_release(ml_peer);
867 mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)",
868 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
869 ml_peer->mlpeer_state);
870 return status;
871 }
872
873 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
874 peer_entry = &ml_peer->peer_list[i];
875 if (peer_entry->link_peer)
876 continue;
877
878 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
879 QDF_STATUS_SUCCESS) {
880 mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state",
881 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
882 QDF_MAC_ADDR_REF
883 (wlan_peer_get_macaddr(link_peer)));
884 break;
885 }
886 peer_entry->link_peer = link_peer;
887 qdf_atomic_inc(&vdev->vdev_objmgr.wlan_ml_peer_count);
888 qdf_copy_macaddr(&peer_entry->link_addr,
889 (struct qdf_mac_addr *)&link_peer->macaddr[0]);
890
891 peer_entry->link_ix = wlan_vdev_get_link_id(vdev);
892 pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer));
893 peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
894 mlo_peer_assign_primary_umac(ml_peer, peer_entry);
895 if (frm_buf)
896 peer_entry->assoc_rsp_buf = frm_buf;
897 else
898 peer_entry->assoc_rsp_buf = NULL;
899
900 status = QDF_STATUS_SUCCESS;
901 break;
902 }
903 if (QDF_IS_STATUS_SUCCESS(status))
904 ml_peer->link_peer_cnt++;
905
906 mlo_peer_lock_release(ml_peer);
907
908 return status;
909 }
910
mlo_peer_get_link_peer_assoc_resp_buf(struct wlan_mlo_peer_context * ml_peer,uint8_t link_ix)911 qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf(
912 struct wlan_mlo_peer_context *ml_peer,
913 uint8_t link_ix)
914 {
915 struct wlan_mlo_link_peer_entry *peer_entry;
916 qdf_nbuf_t frm_buf = NULL;
917 uint8_t i;
918
919 if (!ml_peer)
920 return NULL;
921
922 if (link_ix > MAX_MLO_LINK_PEERS)
923 return NULL;
924
925 mlo_peer_lock_acquire(ml_peer);
926 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
927 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
928 mlo_peer_lock_release(ml_peer);
929 return NULL;
930 }
931
932 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
933 peer_entry = &ml_peer->peer_list[i];
934
935 if (!peer_entry->link_peer)
936 continue;
937
938 if (peer_entry->link_ix == link_ix) {
939 if (!peer_entry->assoc_rsp_buf)
940 break;
941
942 frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf);
943 break;
944 }
945 }
946 mlo_peer_lock_release(ml_peer);
947
948 return frm_buf;
949 }
950
wlan_mlo_peer_free_all_link_assoc_resp_buf(struct wlan_objmgr_peer * link_peer)951 void wlan_mlo_peer_free_all_link_assoc_resp_buf(
952 struct wlan_objmgr_peer *link_peer)
953 {
954 struct wlan_mlo_link_peer_entry *peer_entry;
955 struct wlan_mlo_peer_context *ml_peer;
956 uint8_t i;
957
958 ml_peer = link_peer->mlo_peer_ctx;
959 if (!ml_peer)
960 return;
961
962 mlo_peer_lock_acquire(ml_peer);
963
964 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
965 peer_entry = &ml_peer->peer_list[i];
966
967 if (peer_entry->assoc_rsp_buf) {
968 qdf_nbuf_free(peer_entry->assoc_rsp_buf);
969 peer_entry->assoc_rsp_buf = NULL;
970 }
971 }
972 mlo_peer_lock_release(ml_peer);
973 }
974
mlo_peer_detach_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * link_peer)975 static QDF_STATUS mlo_peer_detach_link_peer(
976 struct wlan_mlo_peer_context *ml_peer,
977 struct wlan_objmgr_peer *link_peer)
978 {
979 struct wlan_mlo_link_peer_entry *peer_entry;
980 QDF_STATUS status = QDF_STATUS_E_RESOURCES;
981 uint16_t i;
982 struct wlan_objmgr_vdev *vdev;
983
984 mlo_peer_lock_acquire(ml_peer);
985
986 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
987 peer_entry = &ml_peer->peer_list[i];
988 if (!peer_entry->link_peer)
989 continue;
990
991 if (peer_entry->link_peer != link_peer)
992 continue;
993
994 if (peer_entry->assoc_rsp_buf) {
995 qdf_nbuf_free(peer_entry->assoc_rsp_buf);
996 peer_entry->assoc_rsp_buf = NULL;
997 }
998 vdev = wlan_peer_get_vdev(link_peer);
999 if (vdev) {
1000 qdf_atomic_dec(&vdev->vdev_objmgr.wlan_ml_peer_count);
1001 } else {
1002 mlo_err("vdev is null for ml_peer: " QDF_MAC_ADDR_FMT
1003 "mld mac addr: " QDF_MAC_ADDR_FMT,
1004 QDF_MAC_ADDR_REF(link_peer->macaddr),
1005 QDF_MAC_ADDR_REF(link_peer->mldaddr));
1006 qdf_assert_always(vdev);
1007 }
1008 wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID);
1009 peer_entry->link_peer = NULL;
1010 ml_peer->link_peer_cnt--;
1011 status = QDF_STATUS_SUCCESS;
1012 break;
1013 }
1014 mlo_peer_lock_release(ml_peer);
1015
1016 return status;
1017 }
1018 #if defined (SAP_MULTI_LINK_EMULATION)
1019 /*Skip link vdev check. Second link does not have vdev*/
mlo_dev_get_link_vdevs(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_dev_context * ml_dev,struct mlo_partner_info * ml_info,struct wlan_objmgr_vdev * link_vdevs[])1020 static QDF_STATUS mlo_dev_get_link_vdevs(
1021 struct wlan_objmgr_vdev *vdev,
1022 struct wlan_mlo_dev_context *ml_dev,
1023 struct mlo_partner_info *ml_info,
1024 struct wlan_objmgr_vdev *link_vdevs[])
1025 {
1026 return QDF_STATUS_SUCCESS;
1027 }
1028 #else
mlo_dev_get_link_vdevs(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_dev_context * ml_dev,struct mlo_partner_info * ml_info,struct wlan_objmgr_vdev * link_vdevs[])1029 static QDF_STATUS mlo_dev_get_link_vdevs(
1030 struct wlan_objmgr_vdev *vdev,
1031 struct wlan_mlo_dev_context *ml_dev,
1032 struct mlo_partner_info *ml_info,
1033 struct wlan_objmgr_vdev *link_vdevs[])
1034 {
1035 uint16_t i, j;
1036 struct wlan_objmgr_vdev *vdev_link;
1037 uint8_t link_id;
1038
1039 if (!ml_dev) {
1040 mlo_err("ml_dev is null");
1041 return QDF_STATUS_E_INVAL;
1042 }
1043
1044 if (!ml_info) {
1045 mlo_err("ml_info is null");
1046 return QDF_STATUS_E_INVAL;
1047 }
1048
1049 mlo_debug("num_partner_links %d", ml_info->num_partner_links);
1050 for (i = 0; i < ml_info->num_partner_links; i++) {
1051 link_id = ml_info->partner_link_info[i].link_id;
1052 vdev_link = mlo_get_vdev_by_link_id(vdev, link_id,
1053 WLAN_MLO_MGR_ID);
1054 if (vdev_link) {
1055 link_vdevs[i] = vdev_link;
1056 } else {
1057 /* release ref which were taken before failure */
1058 for (j = 0; j < i; j++) {
1059 vdev_link = link_vdevs[j];
1060 if (!vdev_link)
1061 continue;
1062
1063 wlan_objmgr_vdev_release_ref(vdev_link,
1064 WLAN_MLO_MGR_ID);
1065 }
1066 return QDF_STATUS_E_INVAL;
1067 }
1068 }
1069
1070 return QDF_STATUS_SUCCESS;
1071 }
1072 #endif
1073
mlo_dev_release_link_vdevs(struct wlan_objmgr_vdev * link_vdevs[])1074 static void mlo_dev_release_link_vdevs(
1075 struct wlan_objmgr_vdev *link_vdevs[])
1076 {
1077 uint16_t i;
1078 struct wlan_objmgr_vdev *vdev_link;
1079
1080 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1081 vdev_link = link_vdevs[i];
1082 if (!vdev_link)
1083 continue;
1084
1085 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
1086 }
1087 }
1088
1089 #ifdef WLAN_FEATURE_11BE
1090 static void
wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context * ml_peer,struct mlo_partner_info * ml_info)1091 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
1092 struct mlo_partner_info *ml_info)
1093 {
1094 ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val;
1095 }
1096
1097 static void
wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context * ml_peer)1098 wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer)
1099 {
1100 ml_peer->epcs_info.state = EPCS_DOWN;
1101 ml_peer->epcs_info.self_gen_dialog_token = 0;
1102 }
1103
1104 #else
1105 static void
wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context * ml_peer,struct mlo_partner_info * ml_info)1106 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
1107 struct mlo_partner_info *ml_info)
1108 {}
1109
1110 static void
wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context * ml_peer)1111 wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer)
1112 {}
1113 #endif /* WLAN_FEATURE_11BE */
1114
1115 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1116 struct wlan_objmgr_vdev*
mlo_get_link_vdev_from_psoc_id(struct wlan_mlo_dev_context * ml_dev,uint8_t psoc_id,bool get_bridge_vdev)1117 mlo_get_link_vdev_from_psoc_id(struct wlan_mlo_dev_context *ml_dev,
1118 uint8_t psoc_id, bool get_bridge_vdev)
1119 {
1120 uint8_t i;
1121 uint16_t num_bridge_vdev = 0;
1122 uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS;
1123 struct wlan_objmgr_vdev *link_vdev;
1124 QDF_STATUS status;
1125
1126 if (WLAN_OBJMGR_MAX_DEVICES <= psoc_id)
1127 return NULL;
1128
1129 if (!ml_dev)
1130 return NULL;
1131
1132 /* if there are no bridge vdevs available,
1133 * fall back to actual link vdevs
1134 */
1135 status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev);
1136 if (!get_bridge_vdev || (status != QDF_STATUS_SUCCESS) ||
1137 !num_bridge_vdev)
1138 max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS;
1139
1140 for (i = 0; i < max_vdevs; i++) {
1141 if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1142 link_vdev = ml_dev->wlan_bridge_vdev_list[i];
1143 else
1144 link_vdev = ml_dev->wlan_vdev_list[i];
1145 if (!link_vdev)
1146 continue;
1147 if (psoc_id != wlan_vdev_get_psoc_id(link_vdev))
1148 continue;
1149 if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_MLO_MGR_ID) !=
1150 QDF_STATUS_SUCCESS) {
1151 mlo_err("VDEV is not in created state");
1152 return NULL;
1153 }
1154 return link_vdev;
1155 }
1156
1157 return NULL;
1158 }
1159
1160 static
mlo_bridge_peer_create_post(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer,uint8_t psoc_id)1161 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
1162 struct wlan_mlo_peer_context *ml_peer,
1163 uint8_t psoc_id)
1164 {
1165 struct peer_create_notif_s peer_create;
1166 struct wlan_objmgr_vdev *vdev_link;
1167 QDF_STATUS status;
1168
1169 /* Bridge peer not required */
1170 if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES)
1171 return QDF_STATUS_SUCCESS;
1172
1173 vdev_link = mlo_get_link_vdev_from_psoc_id(ml_dev, psoc_id, true);
1174
1175 if (!vdev_link) {
1176 mlo_err("VDEV derivation in unsuccessful for %u psoc",
1177 psoc_id);
1178 return QDF_STATUS_E_FAILURE;
1179 }
1180
1181 peer_create.vdev_link = vdev_link;
1182 wlan_mlo_peer_get_ref(ml_peer);
1183 peer_create.ml_peer = ml_peer;
1184
1185 qdf_copy_macaddr(&peer_create.addr,
1186 &ml_peer->peer_mld_addr);
1187
1188 peer_create.frm_buf = NULL;
1189
1190 status = mlo_msgq_post(MLO_BRIDGE_PEER_CREATE, ml_dev, &peer_create);
1191 if (status != QDF_STATUS_SUCCESS) {
1192 wlan_mlo_peer_release_ref(ml_peer);
1193 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
1194 }
1195
1196 return status;
1197 }
1198
1199 static QDF_STATUS
wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_vdev * link_vdevs[],uint8_t num_partner_links,uint8_t * bridge_psoc_id)1200 wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev,
1201 struct wlan_mlo_peer_context *ml_peer,
1202 struct wlan_objmgr_vdev *link_vdevs[],
1203 uint8_t num_partner_links,
1204 uint8_t *bridge_psoc_id)
1205 {
1206 struct wlan_mlo_dev_context *ml_dev;
1207 struct wlan_objmgr_vdev *ml_vdev;
1208 uint8_t psoc_ids[WLAN_NUM_TWO_LINK_PSOC];
1209 uint8_t comp_psoc_id, i, is_adjacent;
1210 uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
1211 uint16_t num_bridge_vdev = 0;
1212 uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS;
1213 QDF_STATUS status;
1214
1215 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE)
1216 return QDF_STATUS_SUCCESS;
1217
1218 /* Return from here for 3 link association */
1219 if (WLAN_NUM_TWO_LINK_PSOC != num_partner_links)
1220 return QDF_STATUS_SUCCESS;
1221
1222 ml_dev = vdev->mlo_dev_ctx;
1223 if (!ml_dev)
1224 return QDF_STATUS_E_FAILURE;
1225
1226 for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++)
1227 psoc_ids[i] = wlan_vdev_get_psoc_id(link_vdevs[i]);
1228
1229 status = mlo_chip_adjacent(psoc_ids[0], psoc_ids[1],
1230 &is_adjacent);
1231 if (QDF_STATUS_SUCCESS != status) {
1232 mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
1233 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1234 psoc_ids[0], psoc_ids[1]);
1235 return status;
1236 }
1237
1238 if (is_adjacent)
1239 return QDF_STATUS_SUCCESS;
1240
1241 /* if there are no bridge vdevs available,
1242 * fall back to actual link vdevs
1243 */
1244 status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev);
1245 if ((status != QDF_STATUS_SUCCESS) || !num_bridge_vdev) {
1246 mlo_err_rl("Using actual vdev as bridge vdev");
1247 max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS;
1248 }
1249
1250 for (i = 0; i < max_vdevs; i++) {
1251 if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1252 ml_vdev = ml_dev->wlan_bridge_vdev_list[i];
1253 else
1254 ml_vdev = ml_dev->wlan_vdev_list[i];
1255 if (!ml_vdev || (wlan_vdev_is_up(ml_vdev) != QDF_STATUS_SUCCESS))
1256 continue;
1257 comp_psoc_id = wlan_vdev_get_psoc_id(ml_vdev);
1258 if ((comp_psoc_id != psoc_ids[0]) &&
1259 (comp_psoc_id != psoc_ids[1])) {
1260 bridge_peer_psoc_id = comp_psoc_id;
1261 break;
1262 }
1263 }
1264
1265 if (bridge_peer_psoc_id >= WLAN_OBJMGR_MAX_DEVICES) {
1266 mlo_err("Invalid psoc or psoc not found for " QDF_MAC_ADDR_FMT " psoc %u",
1267 ether_sprintf(ml_peer->peer_mld_addr.bytes),
1268 bridge_peer_psoc_id);
1269 return QDF_STATUS_E_FAILURE;
1270 }
1271
1272 /* Check if derived psoc is adjecent to both links */
1273 for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) {
1274 status = mlo_chip_adjacent(psoc_ids[i], bridge_peer_psoc_id,
1275 &is_adjacent);
1276 if (QDF_STATUS_SUCCESS != status) {
1277 mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
1278 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1279 psoc_ids[i], bridge_peer_psoc_id);
1280 return status;
1281 }
1282 if (!is_adjacent) {
1283 mlo_err("Derived psoc is not adjecent to one of the links for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u psoc_2 %u",
1284 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1285 psoc_ids[0], psoc_ids[1], bridge_peer_psoc_id);
1286 return QDF_STATUS_E_FAILURE;
1287 }
1288 }
1289
1290 /* Add vdev corresponds to bridge link to link_vdevs so
1291 * that primary UMAC derivation follows 3-link assoc.
1292 */
1293 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1294 if (link_vdevs[i])
1295 continue;
1296
1297 link_vdevs[i] = mlo_get_link_vdev_from_psoc_id(ml_dev,
1298 bridge_peer_psoc_id,
1299 true);
1300 if (!link_vdevs[i])
1301 return QDF_STATUS_E_FAILURE;
1302
1303 ml_peer->max_links++;
1304 *bridge_psoc_id = bridge_peer_psoc_id;
1305 break;
1306 }
1307
1308 if (i == WLAN_UMAC_MLO_MAX_VDEVS) {
1309 mlo_err("Unable to append bridge peer vdev to link vdev list");
1310 return QDF_STATUS_E_FAILURE;
1311 }
1312
1313 mlo_debug("%u is adjecent psoc for " QDF_MAC_ADDR_FMT " is_adjacent %u",
1314 bridge_peer_psoc_id,
1315 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1316 is_adjacent);
1317
1318 return status;
1319 }
1320 #else
1321 static
mlo_bridge_peer_create_post(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer,uint8_t psoc_id)1322 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
1323 struct wlan_mlo_peer_context *ml_peer,
1324 uint8_t psoc_id)
1325 {
1326 return QDF_STATUS_SUCCESS;
1327 }
1328
1329 static QDF_STATUS
wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_vdev * link_vdevs[],uint8_t num_partner_links,uint8_t * bridge_psoc_id)1330 wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev,
1331 struct wlan_mlo_peer_context *ml_peer,
1332 struct wlan_objmgr_vdev *link_vdevs[],
1333 uint8_t num_partner_links,
1334 uint8_t *bridge_psoc_id)
1335 {
1336 return QDF_STATUS_SUCCESS;
1337 }
1338 #endif
1339
wlan_mlo_peer_asreq(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * link_peer,struct mlo_partner_info * ml_info,qdf_nbuf_t frm_buf)1340 QDF_STATUS wlan_mlo_peer_asreq(struct wlan_objmgr_vdev *vdev,
1341 struct wlan_objmgr_peer *link_peer,
1342 struct mlo_partner_info *ml_info,
1343 qdf_nbuf_t frm_buf)
1344 {
1345 struct wlan_mlo_dev_context *ml_dev;
1346 struct wlan_mlo_peer_context *ml_peer = NULL;
1347 struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1348 struct wlan_objmgr_vdev *vdev_link;
1349 QDF_STATUS status;
1350 uint16_t i;
1351 uint16_t j;
1352 uint16_t link_count;
1353 struct wlan_mlo_link_peer_entry *peer_entry;
1354 struct wlan_objmgr_peer *iter_peer;
1355
1356 /* get ML VDEV from VDEV */
1357 ml_dev = vdev->mlo_dev_ctx;
1358 if (!ml_dev) {
1359 mlo_err("ML dev ctx is NULL");
1360 return QDF_STATUS_E_NULL_VALUE;
1361 }
1362
1363 ml_peer = link_peer->mlo_peer_ctx;
1364 if (!ml_peer) {
1365 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " ML peer is NULL",
1366 ml_dev->mld_id,
1367 QDF_MAC_ADDR_REF(link_peer->mldaddr));
1368
1369 return QDF_STATUS_E_FAILURE;
1370 }
1371
1372 if (!wlan_mlo_peer_is_assoc_peer(ml_peer, link_peer)) {
1373 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT "Assoc req received on non-assoc peer" QDF_MAC_ADDR_FMT,
1374 ml_dev->mld_id,
1375 QDF_MAC_ADDR_REF(link_peer->mldaddr),
1376 QDF_MAC_ADDR_REF(link_peer->macaddr));
1377
1378 return QDF_STATUS_E_FAILURE;
1379 }
1380
1381 status = mlo_dev_get_link_vdevs(vdev, ml_dev,
1382 ml_info, link_vdevs);
1383 if (QDF_IS_STATUS_ERROR(status)) {
1384 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
1385 ml_dev->mld_id,
1386 QDF_MAC_ADDR_REF(link_peer->mldaddr));
1387 return QDF_STATUS_E_FAILURE;
1388 }
1389
1390 /* If ML peer state is not in Assoc done state, drop REASSOC req */
1391 if (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE) {
1392 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid state %d",
1393 ml_dev->mld_id,
1394 QDF_MAC_ADDR_REF(link_peer->mldaddr),
1395 ml_peer->mlpeer_state);
1396
1397 mlo_dev_release_link_vdevs(link_vdevs);
1398
1399 return QDF_STATUS_E_FAILURE;
1400 }
1401
1402 link_count = 0;
1403 for (j = 0; j < ml_peer->max_links; j++) {
1404 peer_entry = &ml_peer->peer_list[j];
1405 iter_peer = peer_entry->link_peer;
1406 if (!iter_peer)
1407 continue;
1408
1409 if (wlan_peer_get_peer_type(iter_peer) ==
1410 WLAN_PEER_MLO_BRIDGE) {
1411 link_count++;
1412 continue;
1413 }
1414
1415 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1416 vdev_link = link_vdevs[i];
1417 if (!vdev_link)
1418 continue;
1419
1420 if (vdev_link != wlan_peer_get_vdev(iter_peer))
1421 continue;
1422
1423 link_count++;
1424 break;
1425 }
1426 }
1427 if (link_count != ml_peer->link_peer_cnt) {
1428 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " incorrect link peers",
1429 ml_dev->mld_id,
1430 QDF_MAC_ADDR_REF(link_peer->mldaddr));
1431 mlo_dev_release_link_vdevs(link_vdevs);
1432
1433 return QDF_STATUS_E_INVAL;
1434 }
1435
1436 /* Notify other vdevs about assoc req */
1437 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1438 vdev_link = link_vdevs[i];
1439 if (!vdev_link)
1440 continue;
1441
1442 if (vdev_link == vdev)
1443 continue;
1444
1445 mlo_partner_peer_reassoc_post(ml_dev, vdev_link,
1446 ml_peer, frm_buf, ml_info);
1447 }
1448
1449 mlo_dev_release_link_vdevs(link_vdevs);
1450
1451 if (QDF_IS_STATUS_ERROR(wlan_mlo_validate_reassocreq(ml_peer))) {
1452 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc proc is failed %pK",
1453 ml_dev->mld_id,
1454 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1455 ml_peer);
1456
1457 return QDF_STATUS_E_FAILURE;
1458 }
1459
1460 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc handled %pK",
1461 ml_dev->mld_id,
1462 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1463 ml_peer);
1464
1465 return QDF_STATUS_SUCCESS;
1466 }
1467 #if defined (SAP_MULTI_LINK_EMULATION)
1468 static void
set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer * assoc_peer,struct wlan_mlo_peer_context * ml_peer)1469 set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer *assoc_peer,
1470 struct wlan_mlo_peer_context *ml_peer)
1471 {
1472 assoc_peer = ml_peer->peer_list[0].link_peer;
1473 if (assoc_peer)
1474 mlo_mlme_peer_assoc_resp(assoc_peer);
1475 }
1476 #else
1477 static void
set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer * assoc_peer,struct wlan_mlo_peer_context * ml_peer)1478 set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer *assoc_peer,
1479 struct wlan_mlo_peer_context *ml_peer)
1480 {
1481 }
1482 #endif
wlan_mlo_peer_create(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * link_peer,struct mlo_partner_info * ml_info,qdf_nbuf_t frm_buf,uint16_t aid)1483 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
1484 struct wlan_objmgr_peer *link_peer,
1485 struct mlo_partner_info *ml_info,
1486 qdf_nbuf_t frm_buf,
1487 uint16_t aid)
1488 {
1489 struct wlan_mlo_dev_context *ml_dev;
1490 struct wlan_mlo_peer_context *ml_peer = NULL;
1491 struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1492 struct wlan_objmgr_vdev *tmp_link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1493 struct wlan_objmgr_vdev *vdev_link;
1494 QDF_STATUS status;
1495 uint16_t i, j;
1496 struct wlan_objmgr_peer *assoc_peer = NULL;
1497 uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
1498 bool is_ml_peer_attached = false;
1499
1500 /* get ML VDEV from VDEV */
1501 ml_dev = vdev->mlo_dev_ctx;
1502
1503 if (!ml_dev) {
1504 mlo_err("ML dev ctx is NULL");
1505 return QDF_STATUS_E_NULL_VALUE;
1506 }
1507
1508 /* Check resources of Partner VDEV */
1509 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1510 if (wlan_mlo_is_mld_ctx_exist(
1511 (struct qdf_mac_addr *)&link_peer->mldaddr[0])) {
1512 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system",
1513 ml_dev->mld_id,
1514 QDF_MAC_ADDR_REF(link_peer->mldaddr));
1515 return QDF_STATUS_E_FAILURE;
1516 }
1517 /* Limit max assoc links */
1518 if (ml_info->num_partner_links > WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS) {
1519 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " exceeds MAX assoc limit of %d",
1520 ml_dev->mld_id,
1521 QDF_MAC_ADDR_REF(link_peer->mldaddr),
1522 WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS);
1523 return QDF_STATUS_E_RESOURCES;
1524 }
1525
1526 status = mlo_dev_get_link_vdevs(vdev, ml_dev,
1527 ml_info, link_vdevs);
1528 if (QDF_IS_STATUS_ERROR(status)) {
1529 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
1530 ml_dev->mld_id,
1531 QDF_MAC_ADDR_REF(link_peer->mldaddr));
1532 return QDF_STATUS_E_FAILURE;
1533 }
1534 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1535 vdev_link = link_vdevs[i];
1536 if (!vdev_link) {
1537 mlo_debug("vdev_link is null");
1538 continue;
1539 }
1540
1541 if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link)
1542 != QDF_STATUS_SUCCESS) {
1543 mlo_dev_release_link_vdevs(link_vdevs);
1544
1545 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d",
1546 ml_dev->mld_id,
1547 QDF_MAC_ADDR_REF
1548 (link_peer->mldaddr),
1549 wlan_vdev_get_id(vdev_link));
1550 return QDF_STATUS_E_INVAL;
1551 }
1552 }
1553
1554 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1555 vdev_link = link_vdevs[i];
1556 if (vdev_link && (vdev_link != vdev) &&
1557 (wlan_vdev_get_peer_count(vdev_link) >
1558 wlan_vdev_get_max_peer_count(vdev_link))) {
1559 mlo_dev_release_link_vdevs(link_vdevs);
1560 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d",
1561 ml_dev->mld_id,
1562 QDF_MAC_ADDR_REF
1563 (link_peer->mldaddr),
1564 wlan_vdev_get_id(vdev_link));
1565 return QDF_STATUS_E_RESOURCES;
1566 }
1567 }
1568 }
1569 /* When roam to MLO AP, partner link vdev1 is updated first,
1570 * ml peer need be created and attached for partner link peer.
1571 *
1572 * When roam target AP and current AP have same MLD address, don't
1573 * delete old ML peer and re-create new one, just update different
1574 * info.
1575 */
1576 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1577 ml_peer = wlan_mlo_get_mlpeer(ml_dev,
1578 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1579 if (ml_peer) {
1580 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT
1581 " existed, state %d",
1582 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1583 ml_peer->mlpeer_state);
1584 ml_peer->mlpeer_state = ML_PEER_CREATED;
1585 ml_peer->max_links = ml_info->num_partner_links;
1586 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1587 is_ml_peer_attached = true;
1588 }
1589 }
1590 if (!ml_peer) {
1591 /* Allocate MLO peer */
1592 ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
1593 if (!ml_peer) {
1594 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed",
1595 ml_dev->mld_id,
1596 QDF_MAC_ADDR_REF(link_peer->mldaddr));
1597 mlo_dev_release_link_vdevs(link_vdevs);
1598 return QDF_STATUS_E_NOMEM;
1599 }
1600
1601 qdf_atomic_init(&ml_peer->ref_cnt);
1602 mlo_peer_lock_create(ml_peer);
1603 ml_peer->ml_dev = ml_dev;
1604 ml_peer->mlpeer_state = ML_PEER_CREATED;
1605 ml_peer->max_links = ml_info->num_partner_links;
1606 ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
1607 ml_peer->migrate_primary_umac_psoc_id =
1608 ML_PRIMARY_UMAC_ID_INVAL;
1609 ml_peer->primary_umac_migration_in_progress = false;
1610
1611 ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
1612 if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) {
1613 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id",
1614 ml_dev->mld_id,
1615 QDF_MAC_ADDR_REF
1616 (ml_peer->peer_mld_addr.bytes));
1617 mlo_peer_free(ml_peer);
1618 mlo_dev_release_link_vdevs(link_vdevs);
1619 return QDF_STATUS_E_RESOURCES;
1620 }
1621
1622 qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
1623 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1624 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1625 epcs_dev_peer_lock_create(&ml_peer->epcs_info);
1626 wlan_mlo_peer_initialize_epcs_info(ml_peer);
1627
1628 /* Allocate AID */
1629 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1630 if (aid == (uint16_t)-1) {
1631 status = mlo_peer_allocate_aid(ml_dev, ml_peer);
1632 if (status != QDF_STATUS_SUCCESS) {
1633 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed",
1634 ml_dev->mld_id,
1635 QDF_MAC_ADDR_REF
1636 (ml_peer->peer_mld_addr.bytes));
1637 mlo_peer_free(ml_peer);
1638 mlo_dev_release_link_vdevs(link_vdevs);
1639 return status;
1640 }
1641 } else {
1642 ml_peer->assoc_id = aid;
1643 }
1644 }
1645 }
1646
1647 /* Populate Link peer pointer, peer MAC address,
1648 * MLD address. HW link ID, update ref count
1649 */
1650 status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL);
1651 if (QDF_IS_STATUS_ERROR(status)) {
1652 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed",
1653 ml_dev->mld_id,
1654 QDF_MAC_ADDR_REF
1655 (ml_peer->peer_mld_addr.bytes));
1656 /* If there is another link peer attached for this ML peer,
1657 * ml peer can't be detached and freed.
1658 */
1659 if (is_ml_peer_attached && ml_peer->link_peer_cnt)
1660 return status;
1661 if (is_ml_peer_attached)
1662 mlo_dev_mlpeer_detach(ml_dev, ml_peer);
1663 mlo_peer_free(ml_peer);
1664 mlo_dev_release_link_vdevs(link_vdevs);
1665 return status;
1666 }
1667
1668 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1669 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1670 if (!link_vdevs[i]) {
1671 mlo_debug("vdev_link is null");
1672 continue;
1673 }
1674
1675 if (wlan_objmgr_vdev_try_get_ref(link_vdevs[i], WLAN_MLO_MGR_ID) !=
1676 QDF_STATUS_SUCCESS) {
1677 mlo_err("VDEV is not in created state");
1678 /* release ref which were taken before failure */
1679 for (j = 0; j < i; j++) {
1680 if (!link_vdevs[i])
1681 continue;
1682
1683 wlan_objmgr_vdev_release_ref(link_vdevs[i],
1684 WLAN_MLO_MGR_ID);
1685 }
1686 mlo_reset_link_peer(ml_peer, link_peer);
1687 mlo_peer_free(ml_peer);
1688 mlo_dev_release_link_vdevs(link_vdevs);
1689
1690 return QDF_STATUS_E_FAILURE;
1691 }
1692 tmp_link_vdevs[i] = link_vdevs[i];
1693 }
1694
1695 status = wlan_mlo_get_bridge_peer_psoc_id(vdev, ml_peer,
1696 tmp_link_vdevs,
1697 ml_info->num_partner_links,
1698 &bridge_peer_psoc_id);
1699 if (QDF_STATUS_SUCCESS != status) {
1700 mlo_err("MLD ID %d: Failed to derive bridge peer psoc id",
1701 ml_dev->mld_id);
1702 mlo_reset_link_peer(ml_peer, link_peer);
1703 mlo_peer_free(ml_peer);
1704 mlo_dev_release_link_vdevs(link_vdevs);
1705 mlo_dev_release_link_vdevs(tmp_link_vdevs);
1706 wlan_objmgr_peer_release_ref(link_peer,
1707 WLAN_MLO_MGR_ID);
1708 return QDF_STATUS_E_FAILURE;
1709 }
1710 }
1711
1712 /* Allocate Primary UMAC */
1713 mlo_peer_allocate_primary_umac(ml_dev, ml_peer, tmp_link_vdevs);
1714
1715 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
1716 mlo_dev_release_link_vdevs(tmp_link_vdevs);
1717
1718 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1719 mlo_peer_populate_link_peer(ml_peer, link_peer);
1720
1721 mlo_peer_populate_nawds_params(ml_peer, ml_info);
1722 mlo_peer_populate_mesh_params(ml_peer, ml_info);
1723
1724 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
1725 ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
1726 !is_ml_peer_attached)) {
1727 /* Reject creation for AP mode, If ML peer is present with
1728 * MLD MAC address, For PSTA case, all MLD STAs are connected
1729 * to same MLD AP, it can have duplicate MLD address entries
1730 * for STA MLDs
1731 */
1732 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1733 mlo_mgr_ml_peer_exist_on_diff_ml_ctx(&link_peer->mldaddr[0],
1734 NULL)) {
1735 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is exists, creation failed",
1736 ml_dev->mld_id,
1737 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1738 mlo_reset_link_peer(ml_peer, link_peer);
1739 mlo_peer_free(ml_peer);
1740 mlo_dev_release_link_vdevs(link_vdevs);
1741 wlan_objmgr_peer_release_ref(link_peer,
1742 WLAN_MLO_MGR_ID);
1743 return QDF_STATUS_E_EXISTS;
1744 }
1745
1746 /* Attach MLO peer to ML Peer table */
1747 status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
1748 if (status != QDF_STATUS_SUCCESS) {
1749 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed",
1750 ml_dev->mld_id,
1751 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1752 mlo_reset_link_peer(ml_peer, link_peer);
1753 wlan_objmgr_peer_release_ref(link_peer,
1754 WLAN_MLO_MGR_ID);
1755 mlo_peer_free(ml_peer);
1756 mlo_dev_release_link_vdevs(link_vdevs);
1757 return status;
1758 }
1759 }
1760
1761 wlan_mlo_peer_get_ref(ml_peer);
1762
1763 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1764 /* Notify other vdevs about link peer creation */
1765 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1766 vdev_link = link_vdevs[i];
1767 if (!vdev_link)
1768 continue;
1769
1770 if (vdev_link == vdev)
1771 continue;
1772
1773 mlo_partner_peer_create_post(ml_dev, vdev_link,
1774 ml_peer, frm_buf, ml_info);
1775 }
1776 /* Create bridge peer */
1777 status = mlo_bridge_peer_create_post(ml_dev, ml_peer,
1778 bridge_peer_psoc_id);
1779 if (QDF_STATUS_SUCCESS != status) {
1780 mlo_err("MLD ID %d: Bridge peer creation failed",
1781 ml_dev->mld_id);
1782 wlan_mlo_partner_peer_create_failed_notify(ml_peer);
1783 mlo_dev_release_link_vdevs(link_vdevs);
1784 wlan_mlo_peer_release_ref(ml_peer);
1785 return QDF_STATUS_E_FAILURE;
1786 }
1787 }
1788 mlo_dev_release_link_vdevs(link_vdevs);
1789
1790 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
1791 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed",
1792 ml_dev->mld_id,
1793 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1794 wlan_mlo_peer_release_ref(ml_peer);
1795 return QDF_STATUS_E_FAILURE;
1796 }
1797
1798 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK",
1799 ml_dev->mld_id,
1800 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1801 ml_peer);
1802
1803 /*
1804 * wlan_mlo_peer_create() is trigggered after getting peer
1805 * assoc confirm from FW. For single link MLO connection, it is
1806 * OK to trigger assoc response from here.
1807 */
1808 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1809 (!wlan_mlo_peer_is_nawds(ml_peer))) {
1810 if ((ml_peer->max_links == 1) &&
1811 (ml_peer->link_peer_cnt == 1)) {
1812 assoc_peer = ml_peer->peer_list[0].link_peer;
1813 if (assoc_peer)
1814 mlo_mlme_peer_assoc_resp(assoc_peer);
1815 } else {
1816 set_assoc_peer_for_2link_sap(assoc_peer, ml_peer);
1817 }
1818 }
1819
1820
1821 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
1822 wlan_clear_peer_level_tid_to_link_mapping(vdev);
1823
1824 wlan_mlo_peer_release_ref(ml_peer);
1825
1826 return QDF_STATUS_SUCCESS;
1827 }
1828
wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer,qdf_nbuf_t frm_buf)1829 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
1830 struct wlan_objmgr_peer *peer,
1831 qdf_nbuf_t frm_buf)
1832 {
1833 QDF_STATUS status;
1834 struct wlan_objmgr_peer *assoc_peer;
1835 struct wlan_objmgr_vdev *vdev = NULL;
1836
1837 if (!ml_peer)
1838 return QDF_STATUS_E_FAILURE;
1839
1840 vdev = wlan_peer_get_vdev(peer);
1841 if (!vdev)
1842 return QDF_STATUS_E_FAILURE;
1843
1844 /* Populate Link peer pointer, peer MAC address,
1845 * MLD address. HW link ID, update ref count
1846 */
1847 status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf);
1848 if (QDF_IS_STATUS_ERROR(status))
1849 return status;
1850
1851 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1852 mlo_peer_populate_link_peer(ml_peer, peer);
1853
1854 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1855 if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1856 assoc_peer = ml_peer->peer_list[0].link_peer;
1857 if (assoc_peer)
1858 mlo_mlme_peer_assoc_resp(assoc_peer);
1859 }
1860 }
1861
1862 return status;
1863 }
1864
wlan_mlo_link_asresp_attach(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer,qdf_nbuf_t frm_buf)1865 QDF_STATUS wlan_mlo_link_asresp_attach(struct wlan_mlo_peer_context *ml_peer,
1866 struct wlan_objmgr_peer *peer,
1867 qdf_nbuf_t frm_buf)
1868 {
1869 uint16_t i;
1870 struct wlan_mlo_link_peer_entry *peer_entry;
1871
1872 if (!ml_peer) {
1873 mlo_err(" ml peer is NULL");
1874 return QDF_STATUS_E_FAILURE;
1875 }
1876
1877 if (!peer) {
1878 ml_peer->link_asresp_cnt++;
1879 mlo_err(" ml peer or link peer pointer is NULL");
1880 return QDF_STATUS_E_FAILURE;
1881 }
1882 mlo_peer_lock_acquire(ml_peer);
1883
1884 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1885 peer_entry = &ml_peer->peer_list[i];
1886 if (!peer_entry->link_peer)
1887 continue;
1888
1889 if (peer == peer_entry->link_peer) {
1890 ml_peer->link_asresp_cnt++;
1891 /* Free previous assoc resp buffer */
1892 if (peer_entry->assoc_rsp_buf) {
1893 qdf_nbuf_free(peer_entry->assoc_rsp_buf);
1894 peer_entry->assoc_rsp_buf = NULL;
1895 }
1896
1897 if (frm_buf)
1898 peer_entry->assoc_rsp_buf = frm_buf;
1899 else
1900 peer_entry->assoc_rsp_buf = NULL;
1901
1902 break;
1903 }
1904 }
1905
1906 mlo_peer_lock_release(ml_peer);
1907
1908 return QDF_STATUS_SUCCESS;
1909 }
1910
wlan_mlo_link_peer_delete(struct wlan_objmgr_peer * peer)1911 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
1912 {
1913 struct wlan_mlo_peer_context *ml_peer;
1914
1915 ml_peer = peer->mlo_peer_ctx;
1916
1917 if (!ml_peer)
1918 return QDF_STATUS_E_NOENT;
1919
1920 if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED)
1921 wlan_mlo_peer_wsi_link_delete(ml_peer);
1922
1923 mlo_reset_link_peer(ml_peer, peer);
1924 mlo_peer_detach_link_peer(ml_peer, peer);
1925
1926 if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED)
1927 wlan_mlo_peer_wsi_link_add(ml_peer);
1928
1929 wlan_mlo_peer_release_ref(ml_peer);
1930
1931 return QDF_STATUS_SUCCESS;
1932 }
1933
1934 qdf_export_symbol(wlan_mlo_link_peer_delete);
1935
mlo_peer_get_link_peer_assoc_req_buf(struct wlan_mlo_peer_context * ml_peer,uint8_t link_ix)1936 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf(
1937 struct wlan_mlo_peer_context *ml_peer,
1938 uint8_t link_ix)
1939 {
1940 struct wlan_objmgr_peer *peer = NULL;
1941 qdf_nbuf_t assocbuf = NULL;
1942
1943 if (!ml_peer)
1944 return NULL;
1945
1946 peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
1947 if (!peer)
1948 return NULL;
1949
1950 assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix);
1951
1952 return assocbuf;
1953 }
1954
wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer * peer,struct mlo_tgt_partner_info * ml_links)1955 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer,
1956 struct mlo_tgt_partner_info *ml_links)
1957 {
1958 struct wlan_mlo_peer_context *ml_peer;
1959 struct wlan_mlo_link_peer_entry *peer_entry;
1960 struct wlan_objmgr_peer *link_peer;
1961 struct wlan_objmgr_vdev *link_vdev;
1962 uint8_t i, ix, idx = 0;
1963 struct wlan_mlo_eml_cap *ml_emlcap;
1964
1965 ml_peer = peer->mlo_peer_ctx;
1966 ml_links->num_partner_links = 0;
1967
1968 if (!ml_peer)
1969 return;
1970
1971 ml_emlcap = &ml_peer->mlpeer_emlcap;
1972
1973 mlo_peer_lock_acquire(ml_peer);
1974
1975 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1976 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1977 mlo_peer_lock_release(ml_peer);
1978 return;
1979 }
1980
1981 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1982 peer_entry = &ml_peer->peer_list[i];
1983 link_peer = peer_entry->link_peer;
1984
1985 if (!link_peer)
1986 continue;
1987 idx++;
1988 if (link_peer == peer)
1989 continue;
1990 link_vdev = wlan_peer_get_vdev(link_peer);
1991 if (!link_vdev)
1992 continue;
1993
1994 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1995 break;
1996
1997 ix = ml_links->num_partner_links;
1998 ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev);
1999 ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id;
2000 ml_links->link_info[ix].mlo_enabled = 1;
2001 ml_links->link_info[ix].mlo_assoc_link =
2002 wlan_peer_mlme_is_assoc_peer(link_peer);
2003 ml_links->link_info[ix].mlo_primary_umac =
2004 peer_entry->is_primary;
2005 ml_links->link_info[ix].mlo_logical_link_index_valid = 1;
2006 ml_links->link_info[ix].emlsr_support = ml_emlcap->emlsr_supp;
2007 ml_links->link_info[ix].logical_link_index = idx - 1;
2008 ml_links->link_info[ix].mlo_bridge_peer = link_peer->mlo_bridge_peer;
2009 ml_links->num_partner_links++;
2010 }
2011 mlo_peer_lock_release(ml_peer);
2012 }
2013
2014 qdf_export_symbol(wlan_mlo_peer_get_links_info);
2015
wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer * peer)2016 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer)
2017 {
2018 struct wlan_mlo_peer_context *ml_peer;
2019
2020 ml_peer = peer->mlo_peer_ctx;
2021
2022 if (!ml_peer) {
2023 mlo_err("ml_peer is null");
2024 return WLAN_LINK_ID_INVALID;
2025 }
2026
2027 return wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
2028 }
2029
2030 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id);
2031
wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(struct wlan_mlo_peer_context * ml_peer)2032 uint8_t wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(
2033 struct wlan_mlo_peer_context *ml_peer)
2034 {
2035 struct wlan_mlo_link_peer_entry *peer_entry;
2036 struct wlan_objmgr_peer *link_peer;
2037 struct wlan_objmgr_vdev *link_vdev;
2038 uint8_t i, vdev_link_id;
2039
2040 if (!ml_peer) {
2041 mlo_err("ml_peer is null");
2042 return WLAN_LINK_ID_INVALID;
2043 }
2044 mlo_peer_lock_acquire(ml_peer);
2045
2046 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2047 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2048 mlo_peer_lock_release(ml_peer);
2049 mlo_err("ml_peer is not created and association is not done");
2050 return WLAN_LINK_ID_INVALID;
2051 }
2052
2053 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2054 peer_entry = &ml_peer->peer_list[i];
2055 link_peer = peer_entry->link_peer;
2056 if (!link_peer)
2057 continue;
2058
2059 if (peer_entry->is_primary) {
2060 link_vdev = wlan_peer_get_vdev(link_peer);
2061 if (!link_vdev) {
2062 mlo_peer_lock_release(ml_peer);
2063 mlo_err("link vdev not found");
2064 return WLAN_LINK_ID_INVALID;
2065 }
2066 vdev_link_id = wlan_vdev_get_link_id(link_vdev);
2067 mlo_peer_lock_release(ml_peer);
2068 return vdev_link_id;
2069 }
2070 }
2071 mlo_peer_lock_release(ml_peer);
2072 mlo_err("None of the peer is designated as primary");
2073 return WLAN_LINK_ID_INVALID;
2074 }
2075
2076 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer);
2077
2078 #ifdef WLAN_MLO_MULTI_CHIP
wlan_mlo_peer_get_str_capability(struct wlan_objmgr_peer * peer,uint8_t * str_capability)2079 void wlan_mlo_peer_get_str_capability(struct wlan_objmgr_peer *peer,
2080 uint8_t *str_capability)
2081 {
2082 struct wlan_mlo_peer_context *ml_peer;
2083 uint8_t i;
2084
2085 if (!str_capability)
2086 return;
2087
2088 *str_capability = 1;
2089 if (!peer)
2090 return;
2091 ml_peer = peer->mlo_peer_ctx;
2092 if (!ml_peer)
2093 return;
2094
2095 mlo_peer_lock_acquire(ml_peer);
2096 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2097 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2098 mlo_peer_lock_release(ml_peer);
2099 return;
2100 }
2101
2102 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
2103 if (ml_peer->mlpeer_nstrinfo[i].link_id >= MAX_MLO_LINKS)
2104 continue;
2105 if (ml_peer->mlpeer_nstrinfo[i].nstr_lp_present) {
2106 *str_capability = 0;
2107 break;
2108 }
2109 }
2110 mlo_peer_lock_release(ml_peer);
2111 }
2112
wlan_mlo_peer_get_eml_capability(struct wlan_objmgr_peer * peer,uint8_t * is_emlsr_capable,uint8_t * is_emlmr_capable)2113 void wlan_mlo_peer_get_eml_capability(struct wlan_objmgr_peer *peer,
2114 uint8_t *is_emlsr_capable,
2115 uint8_t *is_emlmr_capable)
2116 {
2117 struct wlan_mlo_peer_context *ml_peer;
2118
2119 if (!is_emlsr_capable || !is_emlmr_capable)
2120 return;
2121
2122 *is_emlsr_capable = 0;
2123 *is_emlmr_capable = 0;
2124 if (!peer)
2125 return;
2126 ml_peer = peer->mlo_peer_ctx;
2127 if (!ml_peer)
2128 return;
2129
2130 mlo_peer_lock_acquire(ml_peer);
2131 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2132 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2133 mlo_peer_lock_release(ml_peer);
2134 return;
2135 }
2136 *is_emlsr_capable = ml_peer->mlpeer_emlcap.emlsr_supp;
2137 *is_emlmr_capable = ml_peer->mlpeer_emlcap.emlmr_supp;
2138 mlo_peer_lock_release(ml_peer);
2139 }
2140 #endif
2141
wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer * peer,struct mlo_partner_info * ml_links)2142 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer,
2143 struct mlo_partner_info *ml_links)
2144 {
2145 struct wlan_mlo_peer_context *ml_peer;
2146 struct wlan_mlo_link_peer_entry *peer_entry;
2147 struct wlan_objmgr_peer *link_peer;
2148 struct wlan_objmgr_vdev *link_vdev;
2149 uint8_t i, ix;
2150
2151 ml_peer = peer->mlo_peer_ctx;
2152 ml_links->num_partner_links = 0;
2153
2154 if (!ml_peer)
2155 return;
2156
2157 mlo_peer_lock_acquire(ml_peer);
2158
2159 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2160 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2161 mlo_peer_lock_release(ml_peer);
2162 return;
2163 }
2164
2165 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2166 peer_entry = &ml_peer->peer_list[i];
2167 link_peer = peer_entry->link_peer;
2168
2169 if (!link_peer)
2170 continue;
2171
2172 if (link_peer == peer)
2173 continue;
2174
2175 link_vdev = wlan_peer_get_vdev(link_peer);
2176 if (!link_vdev)
2177 continue;
2178
2179 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
2180 break;
2181
2182 ix = ml_links->num_partner_links;
2183 ml_links->partner_link_info[ix].link_id = peer_entry->link_ix;
2184 ml_links->partner_link_info[ix].is_bridge =
2185 (wlan_peer_get_peer_type(link_peer) == WLAN_PEER_MLO_BRIDGE);
2186
2187 qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr,
2188 &peer_entry->link_addr);
2189 ml_links->num_partner_links++;
2190 }
2191 mlo_peer_lock_release(ml_peer);
2192 }
2193
2194 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info);
2195
2196 #ifdef UMAC_SUPPORT_MLNAWDS
wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context * ml_peer)2197 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer)
2198 {
2199 bool status = false;
2200
2201 if (!ml_peer)
2202 return status;
2203
2204 mlo_peer_lock_acquire(ml_peer);
2205 if (ml_peer->is_nawds_ml_peer)
2206 status = true;
2207 mlo_peer_lock_release(ml_peer);
2208
2209 return status;
2210 }
2211
2212 qdf_export_symbol(wlan_mlo_peer_is_nawds);
2213 #endif
2214
2215 #ifdef MESH_MODE_SUPPORT
wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context * ml_peer)2216 bool wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context *ml_peer)
2217 {
2218 bool status = false;
2219
2220 if (!ml_peer)
2221 return status;
2222
2223 mlo_peer_lock_acquire(ml_peer);
2224 if (ml_peer->is_mesh_ml_peer)
2225 status = true;
2226 mlo_peer_lock_release(ml_peer);
2227
2228 return status;
2229 }
2230
2231 qdf_export_symbol(wlan_mlo_peer_is_mesh);
2232 #endif
2233
2234 #ifdef UMAC_MLO_AUTH_DEFER
mlo_peer_free_auth_param(struct mlpeer_auth_params * auth_params)2235 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
2236 {
2237 if (auth_params->rs)
2238 qdf_mem_free(auth_params->rs);
2239
2240 if (auth_params->wbuf)
2241 qdf_nbuf_free(auth_params->wbuf);
2242
2243 qdf_mem_free(auth_params);
2244 }
2245
mlo_peer_link_auth_defer(struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * link_mac,struct mlpeer_auth_params * auth_params)2246 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
2247 struct qdf_mac_addr *link_mac,
2248 struct mlpeer_auth_params *auth_params)
2249 {
2250 uint8_t i;
2251 uint8_t free_entries = 0;
2252 struct mlpeer_auth_params *recv_auth;
2253 QDF_STATUS status = QDF_STATUS_E_FAILURE;
2254
2255 if (!ml_peer)
2256 return status;
2257
2258 mlo_peer_lock_acquire(ml_peer);
2259 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2260 recv_auth = ml_peer->pending_auth[i];
2261 if (!recv_auth) {
2262 free_entries++;
2263 continue;
2264 }
2265 /* overwrite the entry with latest entry */
2266 if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) {
2267 mlo_peer_free_auth_param(recv_auth);
2268 ml_peer->pending_auth[i] = auth_params;
2269 mlo_peer_lock_release(ml_peer);
2270
2271 return QDF_STATUS_SUCCESS;
2272 }
2273 }
2274
2275 if (!free_entries) {
2276 mlo_peer_lock_release(ml_peer);
2277 return QDF_STATUS_E_FAILURE;
2278 }
2279
2280 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2281 recv_auth = ml_peer->pending_auth[i];
2282 if (!recv_auth) {
2283 ml_peer->pending_auth[i] = auth_params;
2284 status = QDF_STATUS_SUCCESS;
2285 break;
2286 }
2287 }
2288 mlo_peer_lock_release(ml_peer);
2289
2290 return status;
2291 }
2292
wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer * src_peer)2293 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer)
2294 {
2295 struct wlan_objmgr_vdev *vdev = NULL;
2296 struct wlan_mlo_peer_context *ml_peer;
2297
2298 vdev = wlan_peer_get_vdev(src_peer);
2299 if (!vdev)
2300 return false;
2301
2302 ml_peer = src_peer->mlo_peer_ctx;
2303 if (!wlan_peer_is_mlo(src_peer) || !ml_peer)
2304 return false;
2305
2306 if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) ||
2307 wlan_vdev_mlme_op_flags_get(vdev,
2308 WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) {
2309 /* Single LINK MLO connection */
2310 if (ml_peer->link_peer_cnt == 1)
2311 return false;
2312
2313 /*
2314 * If this link is primary TQM and there is no ongoing migration
2315 * from this link, then issue full disconnect.
2316 */
2317 if ((wlan_mlo_peer_get_primary_peer_link_id(src_peer) !=
2318 wlan_vdev_get_link_id(vdev)) ||
2319 ml_peer->primary_umac_migration_in_progress)
2320 return false;
2321 }
2322
2323 return true;
2324 }
2325
2326 qdf_export_symbol(wlan_mlo_partner_peer_delete_is_allowed);
2327 #endif
2328
wlan_mlo_validate_reassocreq(struct wlan_mlo_peer_context * ml_peer)2329 QDF_STATUS wlan_mlo_validate_reassocreq(struct wlan_mlo_peer_context *ml_peer)
2330 {
2331 uint16_t i;
2332 struct wlan_mlo_link_peer_entry *peer_entry;
2333 QDF_STATUS status = QDF_STATUS_SUCCESS;
2334
2335 if (!ml_peer) {
2336 mlo_err(" ml peer is NULL");
2337 return QDF_STATUS_E_FAILURE;
2338 }
2339
2340 mlo_peer_lock_acquire(ml_peer);
2341
2342 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2343 peer_entry = &ml_peer->peer_list[i];
2344 if (!peer_entry->link_peer)
2345 continue;
2346
2347 /* Check non-assoc link peer Assoc resp buf is valid
2348 * (exclude bridge peer)
2349 */
2350 if (i && !peer_entry->assoc_rsp_buf &&
2351 (wlan_peer_get_peer_type(peer_entry->link_peer) !=
2352 WLAN_PEER_MLO_BRIDGE)) {
2353 status = QDF_STATUS_E_FAILURE;
2354 break;
2355 }
2356 }
2357
2358 mlo_peer_lock_release(ml_peer);
2359
2360 return status;
2361 }
2362
2363 #ifdef WLAN_WSI_STATS_SUPPORT
2364 static uint32_t
wlan_mlo_psoc_get_mlo_grp_idx(struct mlo_mgr_context * mlo_mgr,uint32_t psoc_id)2365 wlan_mlo_psoc_get_mlo_grp_idx(struct mlo_mgr_context *mlo_mgr,
2366 uint32_t psoc_id)
2367 {
2368 struct mlo_wsi_info *wsi_info = NULL;
2369 struct mlo_wsi_psoc_grp *mlo_psoc_grp;
2370 uint8_t grp_id, i;
2371
2372 if (!mlo_mgr)
2373 return MLO_WSI_MAX_MLO_GRPS;
2374
2375 /* Retrieve the WSI link info structure */
2376 wsi_info = mlo_mgr->wsi_info;
2377 if (!wsi_info)
2378 return MLO_WSI_MAX_MLO_GRPS;
2379
2380 for (grp_id = 0; grp_id < MLO_WSI_MAX_MLO_GRPS; grp_id++) {
2381 mlo_psoc_grp = &wsi_info->mlo_psoc_grp[grp_id];
2382 for (i = 0; i < mlo_psoc_grp->num_psoc; i++) {
2383 if (mlo_psoc_grp->psoc_order[i] == psoc_id)
2384 return grp_id;
2385 }
2386 }
2387
2388 return MLO_WSI_MAX_MLO_GRPS;
2389 }
2390
wlan_mlo_wsi_link_info_send_cmd(void)2391 QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void)
2392 {
2393 struct mlo_mgr_context *mlo_mgr = NULL;
2394 struct mlo_wsi_info *wsi_info = NULL;
2395 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops = NULL;
2396 struct wlan_objmgr_psoc *psoc_objmgr = NULL;
2397 struct wlan_objmgr_pdev *pdev = NULL;
2398 QDF_STATUS error = QDF_STATUS_SUCCESS;
2399 int i, j;
2400
2401 /* Retrieve the MLO manager context */
2402 mlo_mgr = wlan_objmgr_get_mlo_ctx();
2403 if (!mlo_mgr)
2404 return QDF_STATUS_E_INVAL;
2405
2406 /* Retrieve the WSI link info structure */
2407 wsi_info = mlo_mgr->wsi_info;
2408 if (!wsi_info)
2409 return QDF_STATUS_E_INVAL;
2410
2411 if (wsi_info->block_wmi_cmd) {
2412 mlo_debug("WMI command is blocked");
2413 return error;
2414 }
2415 /*
2416 * Check each PSOC if the WMI command needs to be sent
2417 * and send it for each PDEV in that PSOC
2418 */
2419 for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
2420 if (!wsi_info->link_stats[i].send_wmi_cmd)
2421 continue;
2422
2423 psoc_objmgr = wlan_objmgr_get_psoc_by_id(i, WLAN_MLO_MGR_ID);
2424 if (!psoc_objmgr) {
2425 mlo_err("Could not get PSOC obj for index %d", i);
2426 continue;
2427 }
2428
2429 mlo_tx_ops = &psoc_objmgr->soc_cb.tx_ops->mlo_ops;
2430 if (!mlo_tx_ops || !mlo_tx_ops->send_wsi_link_info_cmd) {
2431 mlo_err("mlo_tx_ops is null");
2432 wlan_objmgr_psoc_release_ref(psoc_objmgr,
2433 WLAN_MLO_MGR_ID);
2434 return QDF_STATUS_E_NULL_VALUE;
2435 }
2436
2437 for (j = 0; j < psoc_objmgr->soc_objmgr.wlan_pdev_count; j++) {
2438 pdev = psoc_objmgr->soc_objmgr.wlan_pdev_list[j];
2439 if (!pdev)
2440 continue;
2441
2442 if (mlo_tx_ops->send_wsi_link_info_cmd(
2443 pdev, &wsi_info->link_stats[i]) !=
2444 QDF_STATUS_SUCCESS) {
2445 mlo_err("Could not send WMI command for PDEV %d in PSOC %d",
2446 j, i);
2447 error = QDF_STATUS_E_FAILURE;
2448 } else {
2449 wsi_info->link_stats[i].send_wmi_cmd = false;
2450 }
2451 }
2452 wlan_objmgr_psoc_release_ref(psoc_objmgr, WLAN_MLO_MGR_ID);
2453 }
2454
2455 return error;
2456 }
2457
wlan_mlo_psoc_get_ix_in_grp(struct mlo_mgr_context * mlo_mgr,uint32_t grp_id,uint32_t prim_psoc_id)2458 static uint32_t wlan_mlo_psoc_get_ix_in_grp(struct mlo_mgr_context *mlo_mgr,
2459 uint32_t grp_id,
2460 uint32_t prim_psoc_id)
2461 {
2462 uint32_t i;
2463
2464 if (!mlo_mgr) {
2465 mlo_err("NULL mlo_mgr");
2466 return 0xFF;
2467 }
2468
2469 /* Iterate through the PSOC order and find the ID */
2470 for (i = 0; i < mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].num_psoc; i++) {
2471 if (mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].psoc_order[i] ==
2472 prim_psoc_id) {
2473 return i;
2474 }
2475 }
2476
2477 return 0xFF;
2478 }
2479
2480 static uint32_t
wlan_mlo_get_wsi_next_psoc(struct mlo_wsi_psoc_grp * mlo_psoc_grp,uint32_t prim_psoc_id,uint32_t n)2481 wlan_mlo_get_wsi_next_psoc(struct mlo_wsi_psoc_grp *mlo_psoc_grp,
2482 uint32_t prim_psoc_id, uint32_t n)
2483 {
2484 uint32_t i, j;
2485 uint32_t psoc_index = MLO_WSI_PSOC_ID_MAX;
2486
2487 if (!n)
2488 return psoc_index;
2489
2490 for (i = 0; i < mlo_psoc_grp->num_psoc; i++) {
2491 if (mlo_psoc_grp->psoc_order[i] == prim_psoc_id) {
2492 psoc_index = i;
2493 break;
2494 }
2495 }
2496
2497 if (psoc_index == MLO_WSI_PSOC_ID_MAX)
2498 return psoc_index;
2499
2500 for (i = 1; i <= WLAN_OBJMGR_MAX_DEVICES; i++) {
2501 j = (psoc_index + i) % WLAN_OBJMGR_MAX_DEVICES;
2502 if (mlo_psoc_grp->psoc_order[j] != MLO_WSI_PSOC_ID_MAX)
2503 n--;
2504 if (!n)
2505 return mlo_psoc_grp->psoc_order[j];
2506 }
2507
2508 return MLO_WSI_PSOC_ID_MAX;
2509 }
2510
2511 static QDF_STATUS
wlan_mlo_peer_wsi_link_update(struct wlan_mlo_peer_context * ml_peer,bool add)2512 wlan_mlo_peer_wsi_link_update(struct wlan_mlo_peer_context *ml_peer, bool add)
2513 {
2514 struct mlo_mgr_context *mlo_mgr = NULL;
2515 struct mlo_wsi_info *wsi_info = NULL;
2516 struct wlan_mlo_link_peer_entry *peer_entry = NULL;
2517 uint32_t prim_psoc_id = 0xFF;
2518 uint32_t sec_psoc_id[MAX_MLO_LINK_PEERS] = {0xFF};
2519 uint32_t hops, hop_id;
2520 uint32_t prim_grp_idx, sec_grp_idx;
2521 uint32_t prim_psoc_ix_grp, sec_psoc_ix_grp;
2522 uint32_t i, j, n;
2523 struct mlo_wsi_psoc_grp *mlo_psoc_grp;
2524 struct wlan_objmgr_psoc *psoc;
2525
2526 /* Check if ml_peer is valid */
2527 if (!ml_peer) {
2528 mlo_err("ML peer is null");
2529 return QDF_STATUS_E_INVAL;
2530 }
2531
2532 /* Retrieve the MLO manager context */
2533 mlo_mgr = wlan_objmgr_get_mlo_ctx();
2534 if (!mlo_mgr) {
2535 mlo_err("ML MGR is NULL for ML peer" QDF_MAC_ADDR_FMT,
2536 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2537 return QDF_STATUS_E_INVAL;
2538 }
2539
2540 /* Retrieve the WSI link info structure */
2541 wsi_info = mlo_mgr->wsi_info;
2542 if (!wsi_info) {
2543 mlo_err("WSI Info is NULL for ML peer" QDF_MAC_ADDR_FMT,
2544 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2545 return QDF_STATUS_E_INVAL;
2546 }
2547
2548 prim_psoc_id = ml_peer->primary_umac_psoc_id;
2549 /* Populate the primary PSOC ID of the respective group */
2550 prim_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx(mlo_mgr, prim_psoc_id);
2551 if (prim_grp_idx == MLO_WSI_MAX_MLO_GRPS) {
2552 mlo_err("Group index is invalid for ML peer" QDF_MAC_ADDR_FMT,
2553 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2554 return QDF_STATUS_E_INVAL;
2555 }
2556
2557 /* Populate MLO primary and secondary link */
2558 for (i = 0, j = 0; i < MAX_MLO_LINK_PEERS; i++) {
2559 peer_entry = &ml_peer->peer_list[i];
2560 if (!peer_entry->link_peer) {
2561 mlo_debug("link peer is null");
2562 continue;
2563 }
2564
2565 psoc = wlan_peer_get_psoc(peer_entry->link_peer);
2566 if (!mlo_get_wsi_stats_info_support(psoc)) {
2567 mlo_debug("WSI stats support is not enabled on psoc %d",
2568 wlan_psoc_get_id(psoc));
2569 return QDF_STATUS_E_INVAL;
2570 }
2571
2572 /*
2573 * Consider all non-primary peers as secondary links.
2574 * Additionally, consider all active peers as secondary link if
2575 * the TQM is on another PSOC with bridge peer.
2576 */
2577 if (!peer_entry->is_primary) {
2578 sec_psoc_id[j] = wlan_vdev_get_psoc_id(
2579 wlan_peer_get_vdev(
2580 peer_entry->link_peer));
2581
2582 sec_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx
2583 (mlo_mgr,
2584 sec_psoc_id[j]);
2585 if (sec_grp_idx != prim_grp_idx) {
2586 mlo_err("Secondary link is not part of same MLO group as primary link");
2587 continue;
2588 }
2589 j++;
2590 }
2591 }
2592
2593 /*
2594 * Logic for finding ingress and egress stats:
2595 * For a given MLO group, there is a PSOC order
2596 *
2597 * If there is secondary link, Increment the egress count for
2598 * the primary PSOC
2599 * (1) Iterate through each secondary link
2600 * (1.1) Set the WMI command to true for that PSOC
2601 * (1.2) Calculate the number of hops from the secondary link
2602 * to that primary link within the group.
2603 * (1.3) Iterate through a decrement sequence from the hop_count
2604 * (1.3.1) Increment the ingress count for that PSOC index
2605 */
2606 prim_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr, prim_grp_idx,
2607 prim_psoc_id);
2608
2609 wsi_info->link_stats[prim_psoc_id].send_wmi_cmd = true;
2610 mlo_psoc_grp = &wsi_info->mlo_psoc_grp[prim_grp_idx];
2611
2612 if (j) {
2613 wsi_info->link_stats[prim_psoc_id].send_wmi_cmd = true;
2614 if (add)
2615 wsi_info->link_stats[prim_psoc_id].egress_cnt++;
2616 else
2617 wsi_info->link_stats[prim_psoc_id].egress_cnt--;
2618 }
2619
2620 n = 1;
2621 for (i = 0; i < j; i++) {
2622 sec_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr,
2623 prim_grp_idx,
2624 sec_psoc_id[i]);
2625 hops = qdf_min(mlo_psoc_grp->num_psoc -
2626 (prim_psoc_ix_grp - sec_psoc_ix_grp),
2627 (sec_psoc_ix_grp - prim_psoc_ix_grp));
2628
2629
2630 if (hops > n) {
2631 hop_id = wlan_mlo_get_wsi_next_psoc(mlo_psoc_grp,
2632 prim_psoc_id, n);
2633 n++;
2634 if (hop_id == MLO_WSI_PSOC_ID_MAX)
2635 continue;
2636
2637 wsi_info->link_stats[hop_id].send_wmi_cmd = true;
2638 if (add)
2639 wsi_info->link_stats[hop_id].ingress_cnt++;
2640 else
2641 wsi_info->link_stats[hop_id].ingress_cnt--;
2642 }
2643 }
2644
2645 /* Check if WMI bit is set, if yes, then send the command */
2646 if (wlan_mlo_wsi_link_info_send_cmd() != QDF_STATUS_SUCCESS) {
2647 mlo_err("WSI link info not sent for ML peer" QDF_MAC_ADDR_FMT,
2648 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2649 return QDF_STATUS_E_FAILURE;
2650 }
2651
2652 return QDF_STATUS_SUCCESS;
2653 }
2654
wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context * ml_peer)2655 QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer)
2656 {
2657 if (!ml_peer) {
2658 mlo_err("Invalid peer");
2659 return QDF_STATUS_E_INVAL;
2660 }
2661
2662 return wlan_mlo_peer_wsi_link_update(ml_peer, 1);
2663 }
2664
wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context * ml_peer)2665 QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer)
2666 {
2667 if (!ml_peer) {
2668 mlo_err("Invalid peer");
2669 return QDF_STATUS_E_INVAL;
2670 }
2671
2672 return wlan_mlo_peer_wsi_link_update(ml_peer, 0);
2673 }
2674
wlan_mlo_wsi_stats_block_cmd(void)2675 void wlan_mlo_wsi_stats_block_cmd(void)
2676 {
2677 struct mlo_mgr_context *mlo_mgr = NULL;
2678 struct mlo_wsi_info *wsi_info = NULL;
2679
2680 /* Retrieve the MLO manager context */
2681 mlo_mgr = wlan_objmgr_get_mlo_ctx();
2682 if (!mlo_mgr)
2683 return;
2684
2685 /* Retrieve the WSI link info structure */
2686 wsi_info = mlo_mgr->wsi_info;
2687 if (!wsi_info)
2688 return;
2689
2690 wsi_info->block_wmi_cmd++;
2691 }
2692
wlan_mlo_wsi_stats_allow_cmd(void)2693 void wlan_mlo_wsi_stats_allow_cmd(void)
2694 {
2695 struct mlo_mgr_context *mlo_mgr = NULL;
2696 struct mlo_wsi_info *wsi_info = NULL;
2697
2698 /* Retrieve the MLO manager context */
2699 mlo_mgr = wlan_objmgr_get_mlo_ctx();
2700 if (!mlo_mgr)
2701 return;
2702
2703 /* Retrieve the WSI link info structure */
2704 wsi_info = mlo_mgr->wsi_info;
2705 if (!wsi_info)
2706 return;
2707
2708 if (wsi_info->block_wmi_cmd)
2709 wsi_info->block_wmi_cmd--;
2710 }
2711
2712 #else
wlan_mlo_wsi_stats_block_cmd(void)2713 void wlan_mlo_wsi_stats_block_cmd(void)
2714 {
2715 }
2716
wlan_mlo_wsi_stats_allow_cmd(void)2717 void wlan_mlo_wsi_stats_allow_cmd(void)
2718 {
2719 }
2720
wlan_mlo_wsi_link_info_send_cmd(void)2721 QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void)
2722 {
2723 return QDF_STATUS_SUCCESS;
2724 }
2725
wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context * ml_peer)2726 QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer)
2727 {
2728 return QDF_STATUS_SUCCESS;
2729 }
2730
wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context * ml_peer)2731 QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer)
2732 {
2733 return QDF_STATUS_SUCCESS;
2734 }
2735 #endif
2736
wlan_mlo_ap_vdev_add_assoc_entry(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mld_addr)2737 void wlan_mlo_ap_vdev_add_assoc_entry(struct wlan_objmgr_vdev *vdev,
2738 struct qdf_mac_addr *mld_addr)
2739 {
2740 struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
2741 struct wlan_mlo_sta_assoc_pending_list *assoc_list;
2742 struct wlan_mlo_sta_entry *sta_entry = NULL;
2743
2744 if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
2745 return;
2746
2747 assoc_list = &mld_ctx->ap_ctx->assoc_list;
2748
2749 sta_entry = wlan_mlo_ap_vdev_find_assoc_entry(vdev, mld_addr);
2750 if (sta_entry) {
2751 mlo_err("Duplicate entry " QDF_MAC_ADDR_FMT,
2752 QDF_MAC_ADDR_REF(mld_addr->bytes));
2753 return;
2754 }
2755
2756 sta_entry = qdf_mem_malloc(sizeof(*sta_entry));
2757 if (!sta_entry)
2758 return;
2759
2760 qdf_copy_macaddr((struct qdf_mac_addr *)&sta_entry->peer_mld_addr,
2761 (struct qdf_mac_addr *)&mld_addr[0]);
2762
2763 qdf_spin_lock_bh(&assoc_list->list_lock);
2764 qdf_list_insert_back(&assoc_list->peer_list, &sta_entry->mac_node);
2765 qdf_spin_unlock_bh(&assoc_list->list_lock);
2766 }
2767
wlan_mlo_ap_vdev_del_assoc_entry(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mld_addr)2768 void wlan_mlo_ap_vdev_del_assoc_entry(struct wlan_objmgr_vdev *vdev,
2769 struct qdf_mac_addr *mld_addr)
2770 {
2771 struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
2772 struct wlan_mlo_sta_assoc_pending_list *assoc_list;
2773 struct wlan_mlo_sta_entry *sta_entry = NULL;
2774
2775 if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
2776 return;
2777
2778 assoc_list = &mld_ctx->ap_ctx->assoc_list;
2779 sta_entry = wlan_mlo_ap_vdev_find_assoc_entry(vdev, mld_addr);
2780 if (!sta_entry)
2781 return;
2782
2783 qdf_spin_lock_bh(&assoc_list->list_lock);
2784 qdf_list_remove_node(&assoc_list->peer_list, &sta_entry->mac_node);
2785 qdf_spin_unlock_bh(&assoc_list->list_lock);
2786
2787 qdf_mem_free(sta_entry);
2788 }
2789
2790 static inline struct wlan_mlo_sta_entry *
wlan_mlo_assoc_list_peek_head(qdf_list_t * assoc_list)2791 wlan_mlo_assoc_list_peek_head(qdf_list_t *assoc_list)
2792 {
2793 struct wlan_mlo_sta_entry *sta_entry = NULL;
2794 qdf_list_node_t *list_node = NULL;
2795
2796 /* This API is invoked with lock acquired, do not add log prints */
2797 if (qdf_list_peek_front(assoc_list, &list_node) != QDF_STATUS_SUCCESS)
2798 return NULL;
2799
2800 sta_entry = qdf_container_of(list_node,
2801 struct wlan_mlo_sta_entry, mac_node);
2802 return sta_entry;
2803 }
2804
2805 static inline struct wlan_mlo_sta_entry *
wlan_mlo_sta_get_next_sta_entry(qdf_list_t * assoc_list,struct wlan_mlo_sta_entry * sta_entry)2806 wlan_mlo_sta_get_next_sta_entry(qdf_list_t *assoc_list,
2807 struct wlan_mlo_sta_entry *sta_entry)
2808 {
2809 struct wlan_mlo_sta_entry *next_sta_entry = NULL;
2810 qdf_list_node_t *node = &sta_entry->mac_node;
2811 qdf_list_node_t *next_node = NULL;
2812
2813 /* This API is invoked with lock acquired, do not add log prints */
2814 if (!node)
2815 return NULL;
2816
2817 if (qdf_list_peek_next(assoc_list, node, &next_node) !=
2818 QDF_STATUS_SUCCESS)
2819 return NULL;
2820
2821 next_sta_entry = qdf_container_of(next_node,
2822 struct wlan_mlo_sta_entry, mac_node);
2823 return next_sta_entry;
2824 }
2825
2826 struct wlan_mlo_sta_entry *
wlan_mlo_ap_vdev_find_assoc_entry(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mld_addr)2827 wlan_mlo_ap_vdev_find_assoc_entry(struct wlan_objmgr_vdev *vdev,
2828 struct qdf_mac_addr *mld_addr)
2829 {
2830 struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
2831 struct wlan_mlo_sta_assoc_pending_list *assoc_list;
2832 struct wlan_mlo_sta_entry *sta_entry = NULL;
2833 struct wlan_mlo_sta_entry *next_sta_entry = NULL;
2834
2835 if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
2836 return NULL;
2837
2838 assoc_list = &mld_ctx->ap_ctx->assoc_list;
2839 if (qdf_list_empty(&assoc_list->peer_list)) {
2840 mlo_info("list is empty");
2841 return NULL;
2842 }
2843 qdf_spin_lock_bh(&assoc_list->list_lock);
2844
2845 sta_entry = wlan_mlo_assoc_list_peek_head(&assoc_list->peer_list);
2846 while (sta_entry) {
2847 if (qdf_is_macaddr_equal(&sta_entry->peer_mld_addr, mld_addr)) {
2848 qdf_spin_unlock_bh(&assoc_list->list_lock);
2849 return sta_entry;
2850 }
2851
2852 next_sta_entry =
2853 wlan_mlo_sta_get_next_sta_entry(&assoc_list->peer_list,
2854 sta_entry);
2855 sta_entry = next_sta_entry;
2856 }
2857 qdf_spin_unlock_bh(&assoc_list->list_lock);
2858
2859 return NULL;
2860 }
2861
2862