1 /*
2 * Copyright (c) 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 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 /*
19 * DOC: contains MLO manager ap related functionality
20 */
21 #include "wlan_mlo_mgr_cmn.h"
22 #include "wlan_mlo_mgr_main.h"
23 #include "wlan_mlo_mgr_sta.h"
24 #ifdef WLAN_MLO_MULTI_CHIP
25 #include "wlan_lmac_if_def.h"
26 #endif
27 #include "wlan_serialization_api.h"
28 #include <target_if_mlo_mgr.h>
29 #include <cdp_txrx_cmn.h>
30 #include <wlan_cfg.h>
31 #include "wlan_utility.h"
32
mlo_get_link_information(struct qdf_mac_addr * mld_addr,struct mlo_link_info * info)33 void mlo_get_link_information(struct qdf_mac_addr *mld_addr,
34 struct mlo_link_info *info)
35 {
36 /* Pass the partner link information*/
37 }
38
is_mlo_all_links_up(struct wlan_mlo_dev_context * mldev)39 void is_mlo_all_links_up(struct wlan_mlo_dev_context *mldev)
40 {
41 /* Loop through all the vdev's part of the ML device*/
42 /* STA: Loop through all the associated vdev status. */
43 }
44
mlo_get_vdev_by_link_id(struct wlan_objmgr_vdev * vdev,uint8_t link_id,wlan_objmgr_ref_dbgid id)45 struct wlan_objmgr_vdev *mlo_get_vdev_by_link_id(struct wlan_objmgr_vdev *vdev,
46 uint8_t link_id,
47 wlan_objmgr_ref_dbgid id)
48 {
49 struct wlan_mlo_dev_context *dev_ctx;
50 int i;
51 struct wlan_objmgr_vdev *partner_vdev = NULL;
52
53 if (!vdev || !vdev->mlo_dev_ctx) {
54 mlo_err("Invalid input");
55 return partner_vdev;
56 }
57
58 dev_ctx = vdev->mlo_dev_ctx;
59
60 mlo_dev_lock_acquire(dev_ctx);
61 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
62 if (dev_ctx->wlan_vdev_list[i] &&
63 wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i]) &&
64 dev_ctx->wlan_vdev_list[i]->vdev_mlme.mlo_link_id ==
65 link_id) {
66 if (wlan_objmgr_vdev_try_get_ref(
67 dev_ctx->wlan_vdev_list[i],
68 id) == QDF_STATUS_SUCCESS)
69 partner_vdev = dev_ctx->wlan_vdev_list[i];
70
71 break;
72 }
73 }
74 mlo_dev_lock_release(dev_ctx);
75
76 return partner_vdev;
77 }
78
mlo_release_vdev_ref(struct wlan_objmgr_vdev * vdev)79 void mlo_release_vdev_ref(struct wlan_objmgr_vdev *vdev)
80 {
81 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
82 }
83
mlo_reg_mlme_ext_cb(struct mlo_mgr_context * ctx,struct mlo_mlme_ext_ops * ops)84 QDF_STATUS mlo_reg_mlme_ext_cb(struct mlo_mgr_context *ctx,
85 struct mlo_mlme_ext_ops *ops)
86 {
87 if (!ctx)
88 return QDF_STATUS_E_FAILURE;
89
90 ctx->mlme_ops = ops;
91 return QDF_STATUS_SUCCESS;
92 }
93
mlo_unreg_mlme_ext_cb(struct mlo_mgr_context * ctx)94 QDF_STATUS mlo_unreg_mlme_ext_cb(struct mlo_mgr_context *ctx)
95 {
96 if (!ctx)
97 return QDF_STATUS_E_FAILURE;
98
99 ctx->mlme_ops = NULL;
100 return QDF_STATUS_SUCCESS;
101 }
102
103 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
wlan_mlo_mgr_register_osif_ext_ops(struct mlo_mgr_context * mlo_ctx,struct mlo_osif_ext_ops * ops)104 QDF_STATUS wlan_mlo_mgr_register_osif_ext_ops(struct mlo_mgr_context *mlo_ctx,
105 struct mlo_osif_ext_ops *ops)
106 {
107 if (!ops || !mlo_ctx)
108 return QDF_STATUS_E_FAILURE;
109
110 mlo_ctx->osif_ops = ops;
111 return QDF_STATUS_SUCCESS;
112 }
113
wlan_mlo_mgr_unregister_osif_ext_ops(struct mlo_mgr_context * mlo_ctx)114 QDF_STATUS wlan_mlo_mgr_unregister_osif_ext_ops(struct mlo_mgr_context *mlo_ctx)
115 {
116 if (!mlo_ctx)
117 return QDF_STATUS_E_FAILURE;
118
119 mlo_ctx->osif_ops = NULL;
120 return QDF_STATUS_SUCCESS;
121 }
122 #endif
123
mlo_mlme_clone_sta_security(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * req)124 QDF_STATUS mlo_mlme_clone_sta_security(struct wlan_objmgr_vdev *vdev,
125 struct wlan_cm_connect_req *req)
126 {
127 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
128 struct vdev_mlme_obj *vdev_mlme;
129 QDF_STATUS status = QDF_STATUS_SUCCESS;
130
131 if (!req || !mlo_ctx || !mlo_ctx->mlme_ops ||
132 !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
133 return QDF_STATUS_E_FAILURE;
134
135 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
136 if (!vdev_mlme)
137 return QDF_STATUS_E_FAILURE;
138
139 if (mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param) {
140 status =
141 mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param(
142 vdev_mlme, req);
143 }
144
145 return status;
146 }
147
mlo_mlme_sta_op_class(struct wlan_objmgr_vdev * vdev,uint8_t * ml_ie)148 QDF_STATUS mlo_mlme_sta_op_class(struct wlan_objmgr_vdev *vdev,
149 uint8_t *ml_ie)
150 {
151 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
152 struct vdev_mlme_obj *vdev_mlme;
153 QDF_STATUS status = QDF_STATUS_SUCCESS;
154
155 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
156 !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
157 return QDF_STATUS_E_FAILURE;
158
159 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
160 if (!vdev_mlme)
161 return QDF_STATUS_E_FAILURE;
162
163 if (mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class)
164 status =
165 mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class(
166 vdev_mlme, ml_ie);
167
168 return status;
169 }
170
mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev * vdev,void * ext_data)171 QDF_STATUS mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev *vdev,
172 void *ext_data)
173 {
174 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
175 struct vdev_mlme_obj *vdev_mlme;
176 QDF_STATUS status;
177
178 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
179 !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
180 return QDF_STATUS_E_FAILURE;
181
182 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
183 if (!vdev_mlme)
184 return QDF_STATUS_E_FAILURE;
185
186 status =
187 mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req(vdev_mlme,
188 ext_data);
189 return status;
190 }
191
mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev * vdev,void * ext_data)192 QDF_STATUS mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev *vdev,
193 void *ext_data)
194 {
195 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
196 struct vdev_mlme_obj *vdev_mlme;
197 QDF_STATUS status;
198
199 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
200 !mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev)
201 return QDF_STATUS_E_FAILURE;
202
203 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
204 if (!vdev_mlme)
205 return QDF_STATUS_E_FAILURE;
206
207 status =
208 mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev(vdev_mlme,
209 ext_data);
210 return status;
211 }
212
mlo_mlme_peer_create(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * addr,qdf_nbuf_t frm_buf)213 void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev,
214 struct wlan_mlo_peer_context *ml_peer,
215 struct qdf_mac_addr *addr,
216 qdf_nbuf_t frm_buf)
217 {
218 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
219
220 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
221 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create)
222 return;
223
224 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create(vdev, ml_peer,
225 addr, frm_buf);
226 }
227
mlo_mlme_bridge_peer_create(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * addr,qdf_nbuf_t frm_buf)228 void mlo_mlme_bridge_peer_create(struct wlan_objmgr_vdev *vdev,
229 struct wlan_mlo_peer_context *ml_peer,
230 struct qdf_mac_addr *addr,
231 qdf_nbuf_t frm_buf)
232 {
233 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
234
235 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
236 !mlo_ctx->mlme_ops->mlo_mlme_ext_bridge_peer_create)
237 return;
238
239 mlo_ctx->mlme_ops->mlo_mlme_ext_bridge_peer_create(vdev, ml_peer,
240 addr, frm_buf);
241 }
242
mlo_mlme_peer_assoc(struct wlan_objmgr_peer * peer)243 void mlo_mlme_peer_assoc(struct wlan_objmgr_peer *peer)
244 {
245 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
246
247 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
248 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc)
249 return;
250
251 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc(peer);
252 }
253
mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer * peer)254 void mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer *peer)
255 {
256 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
257
258 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
259 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail)
260 return;
261
262 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail(peer);
263 }
264
mlo_mlme_peer_delete(struct wlan_objmgr_peer * peer)265 void mlo_mlme_peer_delete(struct wlan_objmgr_peer *peer)
266 {
267 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
268
269 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
270 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete)
271 return;
272
273 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete(peer);
274 }
275
mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer * peer)276 void mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer *peer)
277 {
278 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
279
280 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
281 !mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp)
282 return;
283
284 mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp(peer);
285 }
286
mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer * peer,uint8_t link_ix)287 qdf_nbuf_t mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer *peer,
288 uint8_t link_ix)
289 {
290 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
291
292 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
293 !mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req)
294 return NULL;
295
296 return mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req(peer, link_ix);
297 }
298
mlo_mlme_peer_deauth(struct wlan_objmgr_peer * peer,uint8_t is_disassoc)299 void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer, uint8_t is_disassoc)
300 {
301 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
302
303 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
304 !mlo_ctx->mlme_ops->mlo_mlme_ext_deauth)
305 return;
306
307 mlo_ctx->mlme_ops->mlo_mlme_ext_deauth(peer, is_disassoc);
308 }
309
310 #ifdef UMAC_MLO_AUTH_DEFER
mlo_mlme_peer_process_auth(struct mlpeer_auth_params * auth_param)311 void mlo_mlme_peer_process_auth(struct mlpeer_auth_params *auth_param)
312 {
313 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
314
315 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
316 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth)
317 return;
318
319 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth(auth_param);
320 }
321 #endif
322
mlo_mlme_peer_reassoc(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * addr,qdf_nbuf_t frm_buf)323 void mlo_mlme_peer_reassoc(struct wlan_objmgr_vdev *vdev,
324 struct wlan_mlo_peer_context *ml_peer,
325 struct qdf_mac_addr *addr,
326 qdf_nbuf_t frm_buf)
327 {
328 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
329
330 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
331 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_reassoc)
332 return;
333
334 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_reassoc(vdev, ml_peer, addr,
335 frm_buf);
336 }
337
mlo_get_link_vdev_ix(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev)338 uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *ml_dev,
339 struct wlan_objmgr_vdev *vdev)
340 {
341 uint8_t i;
342
343 mlo_dev_lock_acquire(ml_dev);
344 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
345 if (vdev == ml_dev->wlan_vdev_list[i]) {
346 mlo_dev_lock_release(ml_dev);
347 return i;
348 }
349 }
350 mlo_dev_lock_release(ml_dev);
351
352 return (uint8_t)-1;
353 }
354
355 #ifdef WLAN_MLO_MULTI_CHIP
wlan_mlo_get_max_num_links(uint8_t grp_id)356 int8_t wlan_mlo_get_max_num_links(uint8_t grp_id)
357 {
358 struct mlo_mgr_context *mlo_ctx;
359
360 mlo_ctx = wlan_objmgr_get_mlo_ctx();
361 if (!mlo_ctx)
362 return WLAN_MLO_INVALID_NUM_LINKS;
363
364 if (grp_id >= mlo_ctx->total_grp) {
365 mlo_err("Invalid grp id %d, total no of groups %d",
366 grp_id, mlo_ctx->total_grp);
367 return WLAN_MLO_INVALID_NUM_LINKS;
368 }
369
370 return (mlo_ctx->setup_info[grp_id].tot_socs *
371 WLAN_MAX_MLO_LINKS_PER_SOC);
372 }
373
wlan_mlo_get_num_active_links(uint8_t grp_id)374 int8_t wlan_mlo_get_num_active_links(uint8_t grp_id)
375 {
376 struct mlo_mgr_context *mlo_ctx;
377
378 mlo_ctx = wlan_objmgr_get_mlo_ctx();
379
380 if (!mlo_ctx)
381 return WLAN_MLO_INVALID_NUM_LINKS;
382
383 if (grp_id >= mlo_ctx->total_grp) {
384 qdf_err("Invalid grp id %d, total no of groups %d",
385 grp_id, mlo_ctx->total_grp);
386 return WLAN_MLO_INVALID_NUM_LINKS;
387 }
388
389 return mlo_ctx->setup_info[grp_id].tot_links;
390 }
391
wlan_mlo_get_valid_link_bitmap(uint8_t grp_id)392 uint16_t wlan_mlo_get_valid_link_bitmap(uint8_t grp_id)
393 {
394 struct mlo_mgr_context *mlo_ctx;
395
396 mlo_ctx = wlan_objmgr_get_mlo_ctx();
397 if (!mlo_ctx)
398 return 0;
399
400 if (grp_id >= mlo_ctx->total_grp) {
401 qdf_err("Invalid grp id %d, total no of groups %d",
402 grp_id, mlo_ctx->total_grp);
403 return 0;
404 }
405
406 return mlo_ctx->setup_info[grp_id].valid_link_bitmap;
407 }
408
wlan_mlo_get_psoc_mlo_chip_id(struct wlan_objmgr_psoc * psoc)409 uint8_t wlan_mlo_get_psoc_mlo_chip_id(struct wlan_objmgr_psoc *psoc)
410 {
411 struct wlan_lmac_if_tx_ops *tx_ops;
412 uint8_t mlo_chip_id = WLAN_MLO_CHIP_ID_INVALID;
413
414 if (!psoc) {
415 qdf_err("PSOC is NULL");
416 return mlo_chip_id;
417 }
418
419 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
420 if (tx_ops && tx_ops->mops.get_psoc_mlo_chip_id)
421 mlo_chip_id = tx_ops->mops.get_psoc_mlo_chip_id(psoc);
422
423 return mlo_chip_id;
424 }
425
426 qdf_export_symbol(wlan_mlo_get_psoc_mlo_chip_id);
427
wlan_mlo_get_psoc_group_id(struct wlan_objmgr_psoc * psoc)428 uint8_t wlan_mlo_get_psoc_group_id(struct wlan_objmgr_psoc *psoc)
429 {
430 struct wlan_lmac_if_tx_ops *tx_ops;
431 uint8_t ml_grp_id = WLAN_MLO_GROUP_INVALID;
432
433 if (!psoc) {
434 qdf_err("PSOC is NULL");
435 return -EINVAL;
436 }
437
438 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
439 if (tx_ops && tx_ops->mops.get_psoc_mlo_group_id)
440 ml_grp_id = tx_ops->mops.get_psoc_mlo_group_id(psoc);
441
442 return ml_grp_id;
443 }
444
445 qdf_export_symbol(wlan_mlo_get_psoc_group_id);
446
wlan_mlo_get_psoc_capable(struct wlan_objmgr_psoc * psoc)447 bool wlan_mlo_get_psoc_capable(struct wlan_objmgr_psoc *psoc)
448 {
449 struct target_psoc_info *tgt_hdl;
450
451 if (!psoc) {
452 qdf_err("PSOC is NULL");
453 return false;
454 }
455
456 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
457 if (!tgt_hdl) {
458 target_if_err("target_psoc_info is null");
459 return false;
460 }
461
462 if ((tgt_hdl->tif_ops) &&
463 (tgt_hdl->tif_ops->mlo_capable))
464 return tgt_hdl->tif_ops->mlo_capable(psoc);
465
466 return false;
467 }
468
wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev * pdev)469 uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev)
470 {
471 struct wlan_objmgr_psoc *psoc;
472 struct wlan_lmac_if_tx_ops *tx_ops;
473 uint16_t hw_link_id = INVALID_HW_LINK_ID;
474
475 psoc = wlan_pdev_get_psoc(pdev);
476 if (psoc) {
477 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
478 if (tx_ops && tx_ops->mops.get_hw_link_id)
479 hw_link_id = tx_ops->mops.get_hw_link_id(pdev);
480 }
481
482 return hw_link_id;
483 }
484
485 qdf_export_symbol(wlan_mlo_get_pdev_hw_link_id);
486
wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)487 static void wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc *psoc,
488 void *obj, void *arg)
489 {
490 struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
491 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj;
492 uint16_t hw_link_id;
493 uint8_t ml_grp_id;
494
495 if (itr->pdev)
496 return;
497
498 ml_grp_id = wlan_mlo_get_psoc_group_id(psoc);
499 if (ml_grp_id > WLAN_MAX_MLO_GROUPS)
500 return;
501
502 if (ml_grp_id != itr->mlo_grp_id)
503 return;
504
505 hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
506 if (hw_link_id == itr->hw_link_id) {
507 if (wlan_objmgr_pdev_try_get_ref(pdev, itr->dbgid) ==
508 QDF_STATUS_SUCCESS)
509 itr->pdev = pdev;
510 }
511 }
512
wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc * psoc,void * arg,uint8_t index)513 static void wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc *psoc,
514 void *arg,
515 uint8_t index)
516 {
517 struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
518
519 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
520 wlan_pdev_hw_link_iterator,
521 arg, false, itr->dbgid);
522 }
523
524 struct wlan_objmgr_pdev *
wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id,uint8_t ml_grp_id,wlan_objmgr_ref_dbgid refdbgid)525 wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id, uint8_t ml_grp_id,
526 wlan_objmgr_ref_dbgid refdbgid)
527 {
528 struct hw_link_id_iterator itr;
529
530 itr.hw_link_id = hw_link_id;
531 itr.pdev = NULL;
532 itr.mlo_grp_id = ml_grp_id;
533 itr.dbgid = refdbgid;
534
535 wlan_objmgr_iterate_psoc_list(wlan_mlo_find_hw_link_id,
536 &itr, refdbgid);
537
538 return itr.pdev;
539 }
540
541 qdf_export_symbol(wlan_mlo_get_pdev_by_hw_link_id);
542 #endif /*WLAN_MLO_MULTI_CHIP*/
543
mlo_get_ml_vdev_list(struct wlan_objmgr_vdev * vdev,uint16_t * vdev_count,struct wlan_objmgr_vdev ** wlan_vdev_list)544 void mlo_get_ml_vdev_list(struct wlan_objmgr_vdev *vdev,
545 uint16_t *vdev_count,
546 struct wlan_objmgr_vdev **wlan_vdev_list)
547 {
548 struct wlan_mlo_dev_context *dev_ctx;
549 int i;
550 QDF_STATUS status;
551
552 *vdev_count = 0;
553
554 if (!vdev || !vdev->mlo_dev_ctx) {
555 mlo_err("Invalid input");
556 return;
557 }
558
559 dev_ctx = vdev->mlo_dev_ctx;
560
561 mlo_dev_lock_acquire(dev_ctx);
562 *vdev_count = 0;
563 for (i = 0; i < QDF_ARRAY_SIZE(dev_ctx->wlan_vdev_list); i++) {
564 if (dev_ctx->wlan_vdev_list[i] &&
565 wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i])) {
566 status = wlan_objmgr_vdev_try_get_ref(
567 dev_ctx->wlan_vdev_list[i],
568 WLAN_MLO_MGR_ID);
569 if (QDF_IS_STATUS_ERROR(status))
570 break;
571 wlan_vdev_list[*vdev_count] =
572 dev_ctx->wlan_vdev_list[i];
573 (*vdev_count) += 1;
574 }
575 }
576 mlo_dev_lock_release(dev_ctx);
577 }
578
579 /**
580 * mlo_link_set_active() - send MLO link set active command
581 * @psoc: PSOC object
582 * @req: MLO link set active request
583 *
584 * Return: QDF_STATUS
585 */
586 static QDF_STATUS
mlo_link_set_active(struct wlan_objmgr_psoc * psoc,struct mlo_link_set_active_req * req)587 mlo_link_set_active(struct wlan_objmgr_psoc *psoc,
588 struct mlo_link_set_active_req *req)
589 {
590 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
591 struct mlo_link_set_active_param *param = &req->param;
592 QDF_STATUS status;
593 struct mlo_link_set_active_resp rsp_evt;
594
595 if (!psoc) {
596 mlo_err("psoc is null");
597 return QDF_STATUS_E_NULL_VALUE;
598 }
599
600 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
601 if (!mlo_tx_ops) {
602 mlo_err("tx_ops is null!");
603 return QDF_STATUS_E_NULL_VALUE;
604 }
605
606 if (!mlo_tx_ops->link_set_active) {
607 mlo_err("link_set_active function is null!");
608 return QDF_STATUS_E_NULL_VALUE;
609 }
610
611 if (req->ctx.validate_set_mlo_link_cb) {
612 status = req->ctx.validate_set_mlo_link_cb(psoc, param);
613 if (QDF_IS_STATUS_ERROR(status)) {
614 qdf_mem_zero(&rsp_evt, sizeof(rsp_evt));
615 rsp_evt.status = status;
616 if (req->ctx.set_mlo_link_cb)
617 req->ctx.set_mlo_link_cb(req->ctx.vdev,
618 req->ctx.cb_arg,
619 &rsp_evt);
620 return status;
621 }
622 }
623
624 return mlo_tx_ops->link_set_active(psoc, param);
625 }
626
627 /**
628 * mlo_release_ser_link_set_active_cmd() - releases serialization command for
629 * forcing MLO link active/inactive
630 * @vdev: Object manager vdev
631 *
632 * Return: None
633 */
634 static void
mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev * vdev)635 mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev *vdev)
636 {
637 struct wlan_serialization_queued_cmd_info cmd = {0};
638
639 cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK;
640 cmd.requestor = WLAN_UMAC_COMP_MLO_MGR;
641 cmd.cmd_id = 0;
642 cmd.vdev = vdev;
643
644 mlo_debug("release serialization command");
645 wlan_serialization_remove_cmd(&cmd);
646 }
647
648 /**
649 * mlo_link_set_active_resp_vdev_handler() - vdev handler for mlo link set
650 * active response event.
651 * @psoc: psoc object
652 * @obj: vdev object
653 * @arg: mlo link set active response
654 *
655 * Return: None
656 */
657 static void
mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)658 mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc *psoc,
659 void *obj, void *arg)
660 {
661 struct mlo_link_set_active_req *req;
662 struct wlan_objmgr_vdev *vdev = obj;
663 struct mlo_link_set_active_resp *event = arg;
664
665 if (event->evt_handled)
666 return;
667 req = wlan_serialization_get_active_cmd(wlan_vdev_get_psoc(vdev),
668 wlan_vdev_get_id(vdev),
669 WLAN_SER_CMD_SET_MLO_LINK);
670 if (!req)
671 return;
672
673 if (req->ctx.set_mlo_link_cb)
674 req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, event);
675
676 mlo_release_ser_link_set_active_cmd(vdev);
677 event->evt_handled = true;
678 }
679
680 QDF_STATUS
mlo_process_link_set_active_resp(struct wlan_objmgr_psoc * psoc,struct mlo_link_set_active_resp * event)681 mlo_process_link_set_active_resp(struct wlan_objmgr_psoc *psoc,
682 struct mlo_link_set_active_resp *event)
683 {
684 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
685 mlo_link_set_active_resp_vdev_handler,
686 event, true, WLAN_MLO_MGR_ID);
687 if (!event->evt_handled)
688 mlo_debug("link set resp evt not handled");
689
690 return QDF_STATUS_SUCCESS;
691 }
692
693 /**
694 * mlo_ser_set_link_cb() - Serialization callback function
695 * @cmd: Serialization command info
696 * @reason: Serialization reason for callback execution
697 *
698 * Return: Status of callback execution
699 */
700 static QDF_STATUS
mlo_ser_set_link_cb(struct wlan_serialization_command * cmd,enum wlan_serialization_cb_reason reason)701 mlo_ser_set_link_cb(struct wlan_serialization_command *cmd,
702 enum wlan_serialization_cb_reason reason)
703 {
704 QDF_STATUS status = QDF_STATUS_SUCCESS;
705 struct wlan_objmgr_vdev *vdev;
706 struct wlan_objmgr_psoc *psoc;
707 struct mlo_link_set_active_req *req;
708 struct mlo_mgr_context *mlo_ctx;
709
710 if (!cmd || !cmd->vdev)
711 return QDF_STATUS_E_FAILURE;
712
713 mlo_ctx = wlan_objmgr_get_mlo_ctx();
714 if (!mlo_ctx)
715 return QDF_STATUS_E_FAILURE;
716
717 psoc = wlan_vdev_get_psoc(cmd->vdev);
718 if (!psoc) {
719 mlo_err("psoc is NULL, reason: %d", reason);
720 return QDF_STATUS_E_NULL_VALUE;
721 }
722
723 req = cmd->umac_cmd;
724 if (!req)
725 return QDF_STATUS_E_INVAL;
726
727 vdev = cmd->vdev;
728 switch (reason) {
729 case WLAN_SER_CB_ACTIVATE_CMD:
730 status = mlo_link_set_active(psoc, req);
731 break;
732 case WLAN_SER_CB_CANCEL_CMD:
733 case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
734 mlo_err("vdev %d command not execute: %d",
735 wlan_vdev_get_id(vdev), reason);
736 if (req->ctx.set_mlo_link_cb)
737 req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, NULL);
738 break;
739 case WLAN_SER_CB_RELEASE_MEM_CMD:
740 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
741 qdf_mem_free(req);
742 break;
743 default:
744 QDF_ASSERT(0);
745 status = QDF_STATUS_E_INVAL;
746 break;
747 }
748
749 return status;
750 }
751
752 #define MLO_SER_CMD_TIMEOUT_MS 5000
mlo_ser_set_link_req(struct mlo_link_set_active_req * req)753 QDF_STATUS mlo_ser_set_link_req(struct mlo_link_set_active_req *req)
754 {
755 struct wlan_serialization_command cmd = {0, };
756 enum wlan_serialization_status ser_cmd_status;
757 QDF_STATUS status;
758 struct wlan_objmgr_vdev *vdev;
759
760 if (!req)
761 return QDF_STATUS_E_INVAL;
762
763 vdev = req->ctx.vdev;
764 status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLO_MGR_ID);
765 if (QDF_IS_STATUS_ERROR(status)) {
766 mlo_err("vdev %d unable to get reference",
767 wlan_vdev_get_id(vdev));
768 return status;
769 }
770
771 cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK;
772 cmd.cmd_id = 0;
773 cmd.cmd_cb = mlo_ser_set_link_cb;
774 cmd.source = WLAN_UMAC_COMP_MLO_MGR;
775 cmd.is_high_priority = false;
776 cmd.cmd_timeout_duration = MLO_SER_CMD_TIMEOUT_MS;
777 cmd.vdev = vdev;
778 cmd.is_blocking = true;
779 cmd.umac_cmd = (void *)req;
780
781 ser_cmd_status = wlan_serialization_request(&cmd);
782 switch (ser_cmd_status) {
783 case WLAN_SER_CMD_PENDING:
784 /* command moved to pending list.Do nothing */
785 break;
786 case WLAN_SER_CMD_ACTIVE:
787 /* command moved to active list. Do nothing */
788 break;
789 default:
790 mlo_err("vdev %d ser cmd status %d",
791 wlan_vdev_get_id(vdev), ser_cmd_status);
792 status = QDF_STATUS_E_FAILURE;
793 }
794
795 if (QDF_IS_STATUS_SUCCESS(status))
796 return status;
797
798 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
799
800 return status;
801 }
802
mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev * vdev,struct csa_offload_params * csa_param)803 void mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev *vdev,
804 struct csa_offload_params *csa_param)
805 {
806 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
807
808 if (!mlo_ctx || !mlo_ctx->mlme_ops ||
809 !mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param)
810 return;
811
812 mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param(vdev, csa_param);
813 }
814
815 QDF_STATUS
mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc * psoc,struct mlo_stats_vdev_params * info,uint8_t vdev_id)816 mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc *psoc,
817 struct mlo_stats_vdev_params *info,
818 uint8_t vdev_id)
819 {
820 struct wlan_objmgr_vdev *ml_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0};
821 struct wlan_objmgr_vdev *vdev;
822 int i;
823 uint16_t ml_vdev_cnt = 0;
824
825 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
826 WLAN_MLO_MGR_ID);
827 if (!vdev) {
828 mlo_err("vdev object is NULL for vdev %d", vdev_id);
829 return QDF_STATUS_E_INVAL;
830 }
831
832 mlo_get_ml_vdev_list(vdev, &ml_vdev_cnt, ml_vdev_list);
833 for (i = 0; i < ml_vdev_cnt; i++) {
834 info->ml_vdev_id[i] = wlan_vdev_get_id(ml_vdev_list[i]);
835 mlo_release_vdev_ref(ml_vdev_list[i]);
836 }
837 info->ml_vdev_count = ml_vdev_cnt;
838 mlo_release_vdev_ref(vdev);
839
840 return QDF_STATUS_SUCCESS;
841 }
842
ml_extract_link_state(struct wlan_objmgr_psoc * psoc,struct ml_link_state_info_event * event)843 static void ml_extract_link_state(struct wlan_objmgr_psoc *psoc,
844 struct ml_link_state_info_event *event)
845 {
846 QDF_STATUS status;
847 get_ml_link_state_cb resp_cb = NULL;
848 void *context = NULL;
849 uint8_t vdev_id;
850
851 vdev_id = event->vdev_id;
852
853 status = mlo_get_link_state_context(psoc,
854 &resp_cb, &context, vdev_id);
855
856 if (QDF_IS_STATUS_ERROR(status))
857 return;
858
859 if (resp_cb)
860 resp_cb(event, context);
861 }
862
863 QDF_STATUS
wlan_handle_ml_link_state_info_event(struct wlan_objmgr_psoc * psoc,struct ml_link_state_info_event * event)864 wlan_handle_ml_link_state_info_event(struct wlan_objmgr_psoc *psoc,
865 struct ml_link_state_info_event *event)
866 {
867 if (!event)
868 return QDF_STATUS_E_NULL_VALUE;
869
870 ml_extract_link_state(psoc, event);
871
872 return QDF_STATUS_SUCCESS;
873 }
874
ml_get_link_state_req_cb(struct scheduler_msg * msg)875 static QDF_STATUS ml_get_link_state_req_cb(struct scheduler_msg *msg)
876 {
877 struct wlan_objmgr_vdev *vdev = msg->bodyptr;
878 struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
879 struct mlo_link_state_cmd_params cmd = {0};
880 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
881 struct wlan_objmgr_psoc *psoc;
882 int status = 0;
883
884 if (!vdev) {
885 mlo_err("null input vdev");
886 return QDF_STATUS_E_INVAL;
887 }
888
889 psoc = wlan_vdev_get_psoc(vdev);
890
891 if (!psoc) {
892 mlo_err("null psoc");
893 return QDF_STATUS_E_NULL_VALUE;
894 }
895
896 mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
897
898 if (!mlo_tx_ops) {
899 mlo_err("tx_ops is null!");
900 return QDF_STATUS_E_NULL_VALUE;
901 }
902
903 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
904 mlo_err("vdev is not MLO vdev");
905 return status;
906 }
907
908 mlo_dev_ctx = vdev->mlo_dev_ctx;
909 cmd.vdev_id = vdev->vdev_objmgr.vdev_id;
910 qdf_mem_copy(&cmd.mld_mac[0], &mlo_dev_ctx->mld_addr,
911 QDF_MAC_ADDR_SIZE);
912
913 if (!mlo_tx_ops->request_link_state_info_cmd) {
914 mlo_err("handler is not registered");
915 return QDF_STATUS_E_NULL_VALUE;
916 }
917
918 status = mlo_tx_ops->request_link_state_info_cmd(psoc, &cmd);
919
920 if (QDF_IS_STATUS_ERROR(status))
921 mlo_err("failed to send ml link info command to FW");
922
923 return QDF_STATUS_SUCCESS;
924 }
925
926 QDF_STATUS
mlo_get_link_state_register_resp_cb(struct wlan_objmgr_vdev * vdev,struct ml_link_state_cmd_info * req)927 mlo_get_link_state_register_resp_cb(struct wlan_objmgr_vdev *vdev,
928 struct ml_link_state_cmd_info *req)
929 {
930 struct wlan_mlo_dev_context *mlo_ctx;
931 struct wlan_mlo_sta *sta_ctx = NULL;
932
933 if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
934 return QDF_STATUS_E_NULL_VALUE;
935 mlo_ctx = vdev->mlo_dev_ctx;
936
937 if (!mlo_ctx) {
938 mlo_err("null mlo_dev_ctx");
939 return QDF_STATUS_E_NULL_VALUE;
940 }
941
942 sta_ctx = mlo_ctx->sta_ctx;
943
944 if (!sta_ctx)
945 return QDF_STATUS_E_INVAL;
946
947 mlo_dev_lock_acquire(mlo_ctx);
948
949 sta_ctx->ml_link_state.ml_link_state_resp_cb =
950 req->ml_link_state_resp_cb;
951 sta_ctx->ml_link_state.ml_link_state_req_context =
952 req->request_cookie;
953 mlo_dev_lock_release(mlo_ctx);
954
955 return QDF_STATUS_SUCCESS;
956 }
957
ml_get_link_state_req_flush_cb(struct scheduler_msg * msg)958 static QDF_STATUS ml_get_link_state_req_flush_cb(struct scheduler_msg *msg)
959 {
960 mlo_debug("ml_get_link_state_req flush callback");
961 return QDF_STATUS_SUCCESS;
962 }
963
ml_post_get_link_state_msg(struct wlan_objmgr_vdev * vdev)964 QDF_STATUS ml_post_get_link_state_msg(struct wlan_objmgr_vdev *vdev)
965 {
966 struct scheduler_msg msg = {0};
967 QDF_STATUS qdf_status = 0;
968
969 msg.bodyptr = vdev;
970 msg.callback = ml_get_link_state_req_cb;
971 msg.flush_callback = ml_get_link_state_req_flush_cb;
972
973 qdf_status = scheduler_post_message(
974 QDF_MODULE_ID_OS_IF,
975 QDF_MODULE_ID_MLME,
976 QDF_MODULE_ID_OS_IF,
977 &msg);
978 return qdf_status;
979 }
980
981 bool
wlan_mlo_is_csa_allow(struct wlan_objmgr_vdev * vdev,uint16_t csa_freq)982 wlan_mlo_is_csa_allow(struct wlan_objmgr_vdev *vdev, uint16_t csa_freq)
983 {
984 struct wlan_channel *chan;
985 struct wlan_objmgr_vdev *ml_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0};
986 uint16_t ml_vdev_cnt = 0;
987 struct wlan_objmgr_vdev *t_vdev;
988 int i;
989 bool is_allow = true;
990
991 if (!vdev) {
992 mlo_err("vdev is NULL");
993 return false;
994 }
995
996 if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
997 return true;
998
999 mlo_get_ml_vdev_list(vdev, &ml_vdev_cnt, ml_vdev_list);
1000 for (i = 0; i < ml_vdev_cnt; i++) {
1001 t_vdev = ml_vdev_list[i];
1002 if (t_vdev == vdev)
1003 goto next;
1004 chan = wlan_vdev_get_active_channel(t_vdev);
1005 if (!chan)
1006 goto next;
1007
1008 if (csa_freq == chan->ch_freq) {
1009 mlo_err("vdev %d will SCC with vdev %d on freq %d",
1010 wlan_vdev_get_id(vdev),
1011 wlan_vdev_get_id(t_vdev), csa_freq);
1012 is_allow = false;
1013 }
1014 next:
1015 mlo_release_vdev_ref(t_vdev);
1016 }
1017
1018 return is_allow;
1019 }
1020
1021