xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_cmn.c (revision d0c05845839e5f2ba5a8dcebe0cd3e4cd4e8dfcf)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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 #ifdef WLAN_MLO_MULTI_CHIP
24 #include "wlan_lmac_if_def.h"
25 #endif
26 #include "wlan_serialization_api.h"
27 #include <target_if_mlo_mgr.h>
28 #include <cdp_txrx_cmn.h>
29 #include <wlan_cfg.h>
30 
31 void mlo_get_link_information(struct qdf_mac_addr *mld_addr,
32 			      struct mlo_link_info *info)
33 {
34 /* Pass the partner link information*/
35 }
36 
37 void is_mlo_all_links_up(struct wlan_mlo_dev_context *mldev)
38 {
39 /* Loop through all the vdev's part of the ML device*/
40 /* STA: Loop through all the associated vdev status. */
41 }
42 
43 struct wlan_objmgr_vdev *mlo_get_vdev_by_link_id(
44 			struct wlan_objmgr_vdev *vdev,
45 			uint8_t link_id)
46 {
47 	struct wlan_mlo_dev_context *dev_ctx;
48 	int i;
49 	struct wlan_objmgr_vdev *partner_vdev = NULL;
50 
51 	if (!vdev || !vdev->mlo_dev_ctx) {
52 		mlo_err("Invalid input");
53 		return partner_vdev;
54 	}
55 
56 	dev_ctx = vdev->mlo_dev_ctx;
57 
58 	mlo_dev_lock_acquire(dev_ctx);
59 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
60 		if (dev_ctx->wlan_vdev_list[i] &&
61 		    wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i]) &&
62 		    dev_ctx->wlan_vdev_list[i]->vdev_mlme.mlo_link_id ==
63 		    link_id) {
64 			if (wlan_objmgr_vdev_try_get_ref(
65 						dev_ctx->wlan_vdev_list[i],
66 						WLAN_MLO_MGR_ID) ==
67 							QDF_STATUS_SUCCESS)
68 				partner_vdev = dev_ctx->wlan_vdev_list[i];
69 
70 			break;
71 		}
72 	}
73 	mlo_dev_lock_release(dev_ctx);
74 
75 	return partner_vdev;
76 }
77 
78 void mlo_release_vdev_ref(struct wlan_objmgr_vdev *vdev)
79 {
80 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
81 }
82 
83 QDF_STATUS mlo_reg_mlme_ext_cb(struct mlo_mgr_context *ctx,
84 			       struct mlo_mlme_ext_ops *ops)
85 {
86 	if (!ctx)
87 		return QDF_STATUS_E_FAILURE;
88 
89 	ctx->mlme_ops = ops;
90 	return QDF_STATUS_SUCCESS;
91 }
92 
93 QDF_STATUS mlo_unreg_mlme_ext_cb(struct mlo_mgr_context *ctx)
94 {
95 	if (!ctx)
96 		return QDF_STATUS_E_FAILURE;
97 
98 	ctx->mlme_ops = NULL;
99 	return QDF_STATUS_SUCCESS;
100 }
101 
102 QDF_STATUS mlo_mlme_clone_sta_security(struct wlan_objmgr_vdev *vdev,
103 				       struct wlan_cm_connect_req *req)
104 {
105 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
106 	struct vdev_mlme_obj *vdev_mlme;
107 	QDF_STATUS status = QDF_STATUS_SUCCESS;
108 
109 	if (!req || !mlo_ctx || !mlo_ctx->mlme_ops ||
110 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
111 		return QDF_STATUS_E_FAILURE;
112 
113 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
114 	if (!vdev_mlme)
115 		return QDF_STATUS_E_FAILURE;
116 
117 	if (mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param) {
118 		status =
119 			mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param(
120 				vdev_mlme, req);
121 	}
122 
123 	return status;
124 }
125 
126 QDF_STATUS mlo_mlme_sta_op_class(struct wlan_objmgr_vdev *vdev,
127 				 uint8_t *ml_ie)
128 {
129 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
130 	struct vdev_mlme_obj *vdev_mlme;
131 	QDF_STATUS status = QDF_STATUS_SUCCESS;
132 
133 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
134 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
135 		return QDF_STATUS_E_FAILURE;
136 
137 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
138 	if (!vdev_mlme)
139 		return QDF_STATUS_E_FAILURE;
140 
141 	if (mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class)
142 		status =
143 			mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class(
144 				vdev_mlme, ml_ie);
145 
146 	return status;
147 }
148 
149 QDF_STATUS mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev *vdev,
150 				      void *ext_data)
151 {
152 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
153 	struct vdev_mlme_obj *vdev_mlme;
154 	QDF_STATUS status;
155 
156 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
157 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req)
158 		return QDF_STATUS_E_FAILURE;
159 
160 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
161 	if (!vdev_mlme)
162 		return QDF_STATUS_E_FAILURE;
163 
164 	status =
165 		mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req(vdev_mlme,
166 								  ext_data);
167 	return status;
168 }
169 
170 QDF_STATUS mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev *vdev,
171 				     void *ext_data)
172 {
173 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
174 	struct vdev_mlme_obj *vdev_mlme;
175 	QDF_STATUS status;
176 
177 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
178 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev)
179 		return QDF_STATUS_E_FAILURE;
180 
181 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
182 	if (!vdev_mlme)
183 		return QDF_STATUS_E_FAILURE;
184 
185 	status =
186 		mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev(vdev_mlme,
187 								 ext_data);
188 	return status;
189 }
190 
191 void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev,
192 			  struct wlan_mlo_peer_context *ml_peer,
193 			  struct qdf_mac_addr *addr,
194 			  qdf_nbuf_t frm_buf)
195 {
196 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
197 
198 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
199 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create)
200 		return;
201 
202 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create(vdev, ml_peer,
203 						    addr, frm_buf);
204 }
205 
206 void mlo_mlme_peer_assoc(struct wlan_objmgr_peer *peer)
207 {
208 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
209 
210 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
211 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc)
212 		return;
213 
214 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc(peer);
215 }
216 
217 void mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer *peer)
218 {
219 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
220 
221 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
222 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail)
223 		return;
224 
225 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail(peer);
226 }
227 
228 void mlo_mlme_peer_delete(struct wlan_objmgr_peer *peer)
229 {
230 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
231 
232 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
233 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete)
234 		return;
235 
236 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete(peer);
237 }
238 
239 void mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer *peer)
240 {
241 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
242 
243 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
244 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp)
245 		return;
246 
247 	mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp(peer);
248 }
249 
250 qdf_nbuf_t mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer *peer,
251 				       uint8_t link_ix)
252 {
253 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
254 
255 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
256 	    !mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req)
257 		return NULL;
258 
259 	return mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req(peer, link_ix);
260 }
261 
262 void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer)
263 {
264 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
265 
266 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
267 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_deauth)
268 		return;
269 
270 	mlo_ctx->mlme_ops->mlo_mlme_ext_deauth(peer);
271 }
272 
273 #ifdef UMAC_MLO_AUTH_DEFER
274 void mlo_mlme_peer_process_auth(struct mlpeer_auth_params *auth_param)
275 {
276 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
277 
278 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
279 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth)
280 		return;
281 
282 	mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth(auth_param);
283 }
284 #endif
285 
286 uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *ml_dev,
287 			     struct wlan_objmgr_vdev *vdev)
288 {
289 	uint8_t i;
290 
291 	mlo_dev_lock_acquire(ml_dev);
292 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
293 		if (vdev == ml_dev->wlan_vdev_list[i]) {
294 			mlo_dev_lock_release(ml_dev);
295 			return i;
296 		}
297 	}
298 	mlo_dev_lock_release(ml_dev);
299 
300 	return (uint8_t)-1;
301 }
302 
303 #ifdef WLAN_MLO_MULTI_CHIP
304 int8_t wlan_mlo_get_max_num_links(void)
305 {
306 	struct mlo_mgr_context *mlo_ctx;
307 
308 	mlo_ctx = wlan_objmgr_get_mlo_ctx();
309 	if (!mlo_ctx)
310 		return WLAN_MLO_INVALID_NUM_LINKS;
311 
312 	return mlo_ctx->setup_info.tot_socs * WLAN_MAX_MLO_LINKS_PER_SOC;
313 }
314 
315 int8_t wlan_mlo_get_num_active_links(void)
316 {
317 	struct mlo_mgr_context *mlo_ctx;
318 
319 	mlo_ctx = wlan_objmgr_get_mlo_ctx();
320 	if (!mlo_ctx)
321 		return WLAN_MLO_INVALID_NUM_LINKS;
322 
323 	return mlo_ctx->setup_info.tot_links;
324 }
325 
326 uint16_t wlan_mlo_get_valid_link_bitmap(void)
327 {
328 	struct mlo_mgr_context *mlo_ctx;
329 
330 	mlo_ctx = wlan_objmgr_get_mlo_ctx();
331 	if (!mlo_ctx)
332 		return 0;
333 
334 	return mlo_ctx->setup_info.valid_link_bitmap;
335 }
336 
337 uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev)
338 {
339 	struct wlan_objmgr_psoc *psoc;
340 	struct wlan_lmac_if_tx_ops *tx_ops;
341 	uint16_t hw_link_id = INVALID_HW_LINK_ID;
342 
343 	psoc = wlan_pdev_get_psoc(pdev);
344 	if (psoc) {
345 		tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
346 		if (tx_ops && tx_ops->mops.get_hw_link_id)
347 			hw_link_id = tx_ops->mops.get_hw_link_id(pdev);
348 	}
349 
350 	return hw_link_id;
351 }
352 
353 qdf_export_symbol(wlan_mlo_get_pdev_hw_link_id);
354 
355 static void wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc *psoc,
356 				       void *obj, void *arg)
357 {
358 	struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
359 	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj;
360 	uint16_t hw_link_id;
361 
362 	if (itr->pdev)
363 		return;
364 
365 	hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
366 	if (hw_link_id == itr->hw_link_id) {
367 		if (wlan_objmgr_pdev_try_get_ref(pdev, itr->dbgid) ==
368 							QDF_STATUS_SUCCESS)
369 			itr->pdev = pdev;
370 	}
371 }
372 
373 static void wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc *psoc,
374 				     void *arg,
375 				     uint8_t index)
376 {
377 	struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg;
378 
379 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
380 				     wlan_pdev_hw_link_iterator,
381 				     arg, false, itr->dbgid);
382 }
383 
384 struct wlan_objmgr_pdev *
385 wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id,
386 				wlan_objmgr_ref_dbgid refdbgid)
387 {
388 	struct hw_link_id_iterator itr;
389 
390 	itr.hw_link_id = hw_link_id;
391 	itr.pdev = NULL;
392 	itr.dbgid = refdbgid;
393 
394 	wlan_objmgr_iterate_psoc_list(wlan_mlo_find_hw_link_id,
395 				      &itr, refdbgid);
396 
397 	return itr.pdev;
398 }
399 
400 qdf_export_symbol(wlan_mlo_get_pdev_by_hw_link_id);
401 #endif /*WLAN_MLO_MULTI_CHIP*/
402 
403 void mlo_get_ml_vdev_list(struct wlan_objmgr_vdev *vdev,
404 			  uint16_t *vdev_count,
405 			  struct wlan_objmgr_vdev **wlan_vdev_list)
406 {
407 	struct wlan_mlo_dev_context *dev_ctx;
408 	int i;
409 	QDF_STATUS status;
410 
411 	*vdev_count = 0;
412 
413 	if (!vdev || !vdev->mlo_dev_ctx) {
414 		mlo_err("Invalid input");
415 		return;
416 	}
417 
418 	dev_ctx = vdev->mlo_dev_ctx;
419 
420 	mlo_dev_lock_acquire(dev_ctx);
421 	*vdev_count = 0;
422 	for (i = 0; i < QDF_ARRAY_SIZE(dev_ctx->wlan_vdev_list); i++) {
423 		if (dev_ctx->wlan_vdev_list[i] &&
424 		    wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i])) {
425 			status = wlan_objmgr_vdev_try_get_ref(
426 						dev_ctx->wlan_vdev_list[i],
427 						WLAN_MLO_MGR_ID);
428 			if (QDF_IS_STATUS_ERROR(status))
429 				break;
430 			wlan_vdev_list[*vdev_count] =
431 				dev_ctx->wlan_vdev_list[i];
432 			(*vdev_count) += 1;
433 		}
434 	}
435 	mlo_dev_lock_release(dev_ctx);
436 }
437 
438 /**
439  * mlo_link_set_active() - send MLO link set active command
440  * @psoc: PSOC object
441  * @param: MLO link set active params
442  *
443  * Return: QDF_STATUS
444  */
445 static QDF_STATUS
446 mlo_link_set_active(struct wlan_objmgr_psoc *psoc,
447 		    struct mlo_link_set_active_param *param)
448 {
449 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
450 
451 	if (!psoc) {
452 		mlo_err("psoc is null");
453 		return QDF_STATUS_E_NULL_VALUE;
454 	}
455 
456 	mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
457 	if (!mlo_tx_ops) {
458 		mlo_err("tx_ops is null!");
459 		return QDF_STATUS_E_NULL_VALUE;
460 	}
461 
462 	if (!mlo_tx_ops->link_set_active) {
463 		mlo_err("link_set_active function is null!");
464 		return QDF_STATUS_E_NULL_VALUE;
465 	}
466 
467 	return mlo_tx_ops->link_set_active(psoc, param);
468 }
469 
470 /**
471  * mlo_release_ser_link_set_active_cmd() - relases serialization command for
472  *  forcing MLO link active/inactive
473  * @vdev: Object manager vdev
474  *
475  * Return: None
476  */
477 static void
478 mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev *vdev)
479 {
480 	struct wlan_serialization_queued_cmd_info cmd = {0};
481 
482 	cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK;
483 	cmd.requestor = WLAN_UMAC_COMP_MLO_MGR;
484 	cmd.cmd_id = 0;
485 	cmd.vdev = vdev;
486 
487 	mlo_debug("release serialization command");
488 	wlan_serialization_remove_cmd(&cmd);
489 }
490 
491 /**
492  * mlo_link_set_active_resp_vdev_handler() - vdev handler for mlo link set
493  * active response event.
494  * @psoc: psoc object
495  * @obj: vdev object
496  * @arg: mlo link set active response
497  *
498  * Return: None
499  */
500 static void
501 mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc *psoc,
502 				      void *obj, void *arg)
503 {
504 	struct mlo_link_set_active_req *req;
505 	struct wlan_objmgr_vdev *vdev = obj;
506 	struct mlo_link_set_active_resp *event = arg;
507 
508 	req = wlan_serialization_get_active_cmd(wlan_vdev_get_psoc(vdev),
509 						wlan_vdev_get_id(vdev),
510 						WLAN_SER_CMD_SET_MLO_LINK);
511 	if (!req)
512 		return;
513 
514 	if (req->ctx.set_mlo_link_cb)
515 		req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, event);
516 
517 	mlo_release_ser_link_set_active_cmd(vdev);
518 }
519 
520 QDF_STATUS
521 mlo_process_link_set_active_resp(struct wlan_objmgr_psoc *psoc,
522 				 struct mlo_link_set_active_resp *event)
523 {
524 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
525 				     mlo_link_set_active_resp_vdev_handler,
526 				     event, true, WLAN_MLO_MGR_ID);
527 	return QDF_STATUS_SUCCESS;
528 }
529 
530 /**
531  * mlo_ser_set_link_cb() - Serialization callback function
532  * @cmd: Serialization command info
533  * @reason: Serialization reason for callback execution
534  *
535  * Return: Status of callback execution
536  */
537 static QDF_STATUS
538 mlo_ser_set_link_cb(struct wlan_serialization_command *cmd,
539 		    enum wlan_serialization_cb_reason reason)
540 {
541 	QDF_STATUS status = QDF_STATUS_SUCCESS;
542 	struct wlan_objmgr_vdev *vdev;
543 	struct wlan_objmgr_psoc *psoc;
544 	struct mlo_link_set_active_req *req;
545 	struct mlo_mgr_context *mlo_ctx;
546 
547 	if (!cmd || !cmd->vdev)
548 		return QDF_STATUS_E_FAILURE;
549 
550 	mlo_ctx = wlan_objmgr_get_mlo_ctx();
551 	if (!mlo_ctx)
552 		return QDF_STATUS_E_FAILURE;
553 
554 	psoc = wlan_vdev_get_psoc(cmd->vdev);
555 	if (!psoc) {
556 		mlo_err("psoc is NULL, reason: %d", reason);
557 		return QDF_STATUS_E_NULL_VALUE;
558 	}
559 
560 	req = cmd->umac_cmd;
561 	if (!req)
562 		return QDF_STATUS_E_INVAL;
563 
564 	vdev = cmd->vdev;
565 	switch (reason) {
566 	case WLAN_SER_CB_ACTIVATE_CMD:
567 		status = mlo_link_set_active(psoc, &req->param);
568 		break;
569 	case WLAN_SER_CB_CANCEL_CMD:
570 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
571 		mlo_err("vdev %d command not execute: %d",
572 			wlan_vdev_get_id(vdev), reason);
573 		if (req->ctx.set_mlo_link_cb)
574 			req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, NULL);
575 		break;
576 	case WLAN_SER_CB_RELEASE_MEM_CMD:
577 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
578 		qdf_mem_free(req);
579 		break;
580 	default:
581 		QDF_ASSERT(0);
582 		status = QDF_STATUS_E_INVAL;
583 		break;
584 	}
585 
586 	return status;
587 }
588 
589 #define MLO_SER_CMD_TIMEOUT_MS 5000
590 QDF_STATUS mlo_ser_set_link_req(struct mlo_link_set_active_req *req)
591 {
592 	struct wlan_serialization_command cmd = {0, };
593 	enum wlan_serialization_status ser_cmd_status;
594 	QDF_STATUS status;
595 	struct wlan_objmgr_vdev *vdev;
596 
597 	if (!req)
598 		return QDF_STATUS_E_INVAL;
599 
600 	vdev = req->ctx.vdev;
601 	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLO_MGR_ID);
602 	if (QDF_IS_STATUS_ERROR(status)) {
603 		mlo_err("vdev %d unable to get reference",
604 			wlan_vdev_get_id(vdev));
605 		return status;
606 	}
607 
608 	cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK;
609 	cmd.cmd_id = 0;
610 	cmd.cmd_cb = mlo_ser_set_link_cb;
611 	cmd.source = WLAN_UMAC_COMP_MLO_MGR;
612 	cmd.is_high_priority = false;
613 	cmd.cmd_timeout_duration = MLO_SER_CMD_TIMEOUT_MS;
614 	cmd.vdev = vdev;
615 	cmd.is_blocking = true;
616 	cmd.umac_cmd = (void *)req;
617 
618 	ser_cmd_status = wlan_serialization_request(&cmd);
619 	switch (ser_cmd_status) {
620 	case WLAN_SER_CMD_PENDING:
621 		/* command moved to pending list.Do nothing */
622 		break;
623 	case WLAN_SER_CMD_ACTIVE:
624 		/* command moved to active list. Do nothing */
625 		break;
626 	default:
627 		mlo_err("vdev %d ser cmd status %d",
628 			wlan_vdev_get_id(vdev), ser_cmd_status);
629 		status = QDF_STATUS_E_FAILURE;
630 	}
631 
632 	if (QDF_IS_STATUS_SUCCESS(status))
633 		return status;
634 
635 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
636 
637 	return status;
638 }
639 
640 void mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev *vdev,
641 				   struct csa_offload_params *csa_param)
642 {
643 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
644 
645 	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
646 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param)
647 		return;
648 
649 	mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param(vdev, csa_param);
650 }
651 
652 QDF_STATUS
653 mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc *psoc,
654 			    struct mlo_stats_vdev_params *info,
655 			    uint8_t vdev_id)
656 {
657 	struct wlan_objmgr_vdev *ml_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0};
658 	struct wlan_objmgr_vdev *vdev;
659 	int i;
660 	uint16_t ml_vdev_cnt = 0;
661 
662 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
663 						    WLAN_MLO_MGR_ID);
664 	if (!vdev) {
665 		mlo_err("vdev object is NULL for vdev %d", vdev_id);
666 		return QDF_STATUS_E_INVAL;
667 	}
668 
669 	mlo_get_ml_vdev_list(vdev, &ml_vdev_cnt, ml_vdev_list);
670 	for (i = 0; i < ml_vdev_cnt; i++) {
671 		info->ml_vdev_id[i] = wlan_vdev_get_id(ml_vdev_list[i]);
672 		mlo_release_vdev_ref(ml_vdev_list[i]);
673 	}
674 	info->ml_vdev_count = ml_vdev_cnt;
675 	mlo_release_vdev_ref(vdev);
676 
677 	return QDF_STATUS_SUCCESS;
678 }
679