xref: /wlan-dirver/qca-wifi-host-cmn/target_if/mlo_mgr/src/target_if_mlo_mgr.c (revision fb436899e24ed79fc745209e906f95145a787017)
1 /*
2  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: target_if_mlo_mgr.c
19  *
20  * This file provide definition for APIs registered through lmac Tx Ops
21  */
22 
23 #include <wmi_unified_11be_api.h>
24 #include <init_deinit_lmac.h>
25 #include "target_if_mlo_mgr.h"
26 #include <wlan_objmgr_peer_obj.h>
27 #include <wlan_mlo_t2lm.h>
28 
29 /**
30  * target_if_mlo_link_set_active_resp_handler() - function to handle mlo link
31  *  set active response from firmware.
32  * @scn: scn handle
33  * @data: data buffer for event
34  * @datalen: data length
35  *
36  * Return: 0 on success, else error on failure
37  */
38 static int
39 target_if_mlo_link_set_active_resp_handler(ol_scn_t scn, uint8_t *data,
40 					   uint32_t datalen)
41 {
42 	QDF_STATUS status;
43 	struct wlan_objmgr_psoc *psoc;
44 	struct wmi_unified *wmi_handle;
45 	struct wlan_lmac_if_mlo_rx_ops *rx_ops;
46 	struct mlo_link_set_active_resp resp;
47 
48 	if (!scn || !data) {
49 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
50 		return -EINVAL;
51 	}
52 
53 	psoc = target_if_get_psoc_from_scn_hdl(scn);
54 	if (!psoc) {
55 		target_if_err("null psoc");
56 		return -EINVAL;
57 	}
58 
59 	rx_ops = target_if_mlo_get_rx_ops(psoc);
60 	if (!rx_ops || !rx_ops->process_link_set_active_resp) {
61 		target_if_err("callback not registered");
62 		return -EINVAL;
63 	}
64 
65 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
66 	if (!wmi_handle) {
67 		target_if_err("wmi_handle is null");
68 		return -EINVAL;
69 	}
70 	qdf_mem_zero(&resp, sizeof(resp));
71 	if (wmi_extract_mlo_link_set_active_resp(wmi_handle, data, &resp) !=
72 	    QDF_STATUS_SUCCESS) {
73 		target_if_err("Unable to extract mlo link set active resp");
74 		return -EINVAL;
75 	}
76 
77 	status = rx_ops->process_link_set_active_resp(psoc, &resp);
78 
79 	return qdf_status_to_os_return(status);
80 }
81 
82 /**
83  * target_if_mlo_link_removal_event_handler() - Handler for MLO link removal
84  * event sent by the FW
85  * @scn: scn handle
86  * @data: data buffer for event
87  * @datalen: data length
88  *
89  * Return: 0 on success, else error on failure
90  */
91 static int
92 target_if_mlo_link_removal_event_handler(ol_scn_t scn, uint8_t *data,
93 					 uint32_t datalen)
94 {
95 	struct wlan_objmgr_psoc *psoc;
96 	struct wmi_unified *wmi_handle;
97 	struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops;
98 	QDF_STATUS status;
99 	struct mlo_link_removal_evt_params evt_params;
100 
101 	if (!scn || !data) {
102 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
103 		return -EINVAL;
104 	}
105 
106 	psoc = target_if_get_psoc_from_scn_hdl(scn);
107 	if (!psoc) {
108 		target_if_err("null psoc");
109 		return -EINVAL;
110 	}
111 
112 	mlo_rx_ops = target_if_mlo_get_rx_ops(psoc);
113 	if (!mlo_rx_ops || !mlo_rx_ops->mlo_link_removal_handler) {
114 		target_if_err("callback not registered");
115 		return -EINVAL;
116 	}
117 
118 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
119 	if (!wmi_handle) {
120 		target_if_err("wmi_handle is null");
121 		return -EINVAL;
122 	}
123 
124 	status = wmi_extract_mlo_link_removal_evt_fixed_param(wmi_handle, data,
125 							      &evt_params);
126 	if (QDF_IS_STATUS_ERROR(status)) {
127 		target_if_err("Unable to extract fixed param, ret = %d",
128 			      status);
129 		goto exit;
130 	}
131 
132 	status = wmi_extract_mlo_link_removal_tbtt_update(
133 			wmi_handle, data, &evt_params.tbtt_info);
134 	if (QDF_IS_STATUS_ERROR(status)) {
135 		target_if_err("Unable to extract TBTT update TLV, ret = %d",
136 			      status);
137 		goto exit;
138 	}
139 
140 	status = mlo_rx_ops->mlo_link_removal_handler(psoc, &evt_params);
141 exit:
142 	return qdf_status_to_os_return(status);
143 }
144 
145 QDF_STATUS
146 target_if_extract_mlo_link_removal_info_mgmt_rx(
147 		wmi_unified_t wmi_handle,
148 		void *evt_buf,
149 		struct mgmt_rx_event_params *rx_event)
150 {
151 	QDF_STATUS status;
152 	struct mgmt_rx_mlo_link_removal_info *link_removal_info;
153 
154 	if (!rx_event) {
155 		target_if_err("Invalid rx_event");
156 		return QDF_STATUS_E_NULL_VALUE;
157 	}
158 
159 	rx_event->link_removal_info = NULL;
160 	if (!rx_event->num_link_removal_info) {
161 		/**
162 		 * This is not an error. Only probe request frames will contain
163 		 * Link removal TLVs, that too only till the link removal TBTT
164 		 * countdown completion.
165 		 */
166 		target_if_debug("Link removal TLVs are not present");
167 		return QDF_STATUS_SUCCESS;
168 	}
169 
170 	link_removal_info = qdf_mem_malloc(rx_event->num_link_removal_info *
171 					   sizeof(*link_removal_info));
172 	if (!link_removal_info) {
173 		target_if_err("Couldn't allocate memory for link_removal_info");
174 		rx_event->num_link_removal_info = 0;
175 		return QDF_STATUS_E_NOMEM;
176 	}
177 
178 	status = wmi_extract_mgmt_rx_mlo_link_removal_info(
179 					wmi_handle, evt_buf,
180 					link_removal_info,
181 					rx_event->num_link_removal_info);
182 	if (QDF_IS_STATUS_ERROR(status)) {
183 		target_if_err("Unable to extract link removal TLVs");
184 		rx_event->num_link_removal_info = 0;
185 		qdf_mem_free(link_removal_info);
186 		return status;
187 	}
188 
189 	rx_event->link_removal_info = link_removal_info;
190 
191 	return QDF_STATUS_SUCCESS;
192 }
193 
194 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
195 static QDF_STATUS
196 target_if_send_mlo_link_switch_cnf_cmd(struct wlan_objmgr_psoc *psoc,
197 				       struct wlan_mlo_link_switch_cnf *params)
198 {
199 	struct wmi_unified *wmi_handle = NULL;
200 
201 	if (!psoc) {
202 		target_if_err("null pdev");
203 		return QDF_STATUS_E_NULL_VALUE;
204 	}
205 
206 	if (!params) {
207 		target_if_err("params is null");
208 		return QDF_STATUS_E_NULL_VALUE;
209 	}
210 
211 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
212 	if (!wmi_handle) {
213 		target_if_err("null wmi handle");
214 		return QDF_STATUS_E_NULL_VALUE;
215 	}
216 
217 	return wmi_send_mlo_link_switch_req_cnf_cmd(wmi_handle, params);
218 }
219 
220 static int
221 target_if_mlo_link_switch_request_event_handler(ol_scn_t scn, uint8_t *data,
222 						uint32_t datalen)
223 {
224 	struct wlan_objmgr_psoc *psoc;
225 	struct wmi_unified *wmi_handle;
226 	struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops;
227 	QDF_STATUS status;
228 	struct wlan_mlo_link_switch_req req = {0};
229 
230 	if (!scn || !data) {
231 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
232 		return -EINVAL;
233 	}
234 
235 	psoc = target_if_get_psoc_from_scn_hdl(scn);
236 	if (!psoc) {
237 		target_if_err("null psoc");
238 		return -EINVAL;
239 	}
240 
241 	mlo_rx_ops = target_if_mlo_get_rx_ops(psoc);
242 	if (!mlo_rx_ops || !mlo_rx_ops->mlo_link_switch_request_handler) {
243 		target_if_err("callback not registered");
244 		return -EINVAL;
245 	}
246 
247 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
248 	if (!wmi_handle) {
249 		target_if_err("wmi_handle is null");
250 		return -EINVAL;
251 	}
252 
253 	status = wmi_extract_mlo_link_switch_request_evt(wmi_handle, data,
254 							 &req);
255 
256 	if (QDF_IS_STATUS_ERROR(status)) {
257 		target_if_err("Unable to extract fixed param, ret = %d",
258 			      status);
259 		goto exit;
260 	}
261 
262 	status = mlo_rx_ops->mlo_link_switch_request_handler(psoc, &req);
263 
264 exit:
265 	return status;
266 }
267 
268 static inline void
269 target_if_mlo_register_link_switch_cnf_handler(struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
270 {
271 	mlo_tx_ops->send_mlo_link_switch_cnf_cmd =
272 			target_if_send_mlo_link_switch_cnf_cmd;
273 }
274 
275 static QDF_STATUS
276 target_if_mlo_register_link_switch_event_handler(struct wmi_unified *wmi_handle)
277 {
278 	QDF_STATUS status;
279 
280 	status = wmi_unified_register_event_handler(
281 			wmi_handle,
282 			wmi_mlo_link_switch_request_eventid,
283 			target_if_mlo_link_switch_request_event_handler,
284 			WMI_RX_SERIALIZER_CTX);
285 
286 	return status;
287 }
288 
289 static inline void
290 target_if_mlo_unregister_link_switch_event_handler(struct wmi_unified *wmi_handle)
291 {
292 	wmi_unified_unregister_event(wmi_handle,
293 				     wmi_mlo_link_switch_request_eventid);
294 }
295 #else
296 static inline QDF_STATUS
297 target_if_mlo_register_link_switch_event_handler(struct wmi_unified *wmi_handle)
298 {
299 	return QDF_STATUS_E_NOSUPPORT;
300 }
301 
302 static inline void
303 target_if_mlo_unregister_link_switch_event_handler(struct wmi_unified *wmi_handle)
304 {
305 }
306 
307 static inline QDF_STATUS
308 target_if_send_mlo_link_switch_cnf_cmd(struct wlan_objmgr_psoc *psoc,
309 				       struct wlan_mlo_link_switch_cnf *params)
310 {
311 	return QDF_STATUS_SUCCESS;
312 }
313 
314 static inline void
315 target_if_mlo_register_link_switch_cnf_handler(struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
316 {
317 }
318 
319 static inline int
320 target_if_mlo_link_switch_request_event_handler(ol_scn_t scn, uint8_t *data,
321 						uint32_t datalen)
322 {
323 	return 0;
324 }
325 #endif
326 
327 /**
328  * target_if_mlo_link_disable_request_event_handler() - Handler for MLO
329  * link disable request event sent by the FW
330  * @scn: scn handle
331  * @data: data buffer for event
332  * @datalen: data length
333  *
334  * Return: 0 on success, else error on failure
335  */
336 static int
337 target_if_mlo_link_disable_request_event_handler(ol_scn_t scn, uint8_t *data,
338 						 uint32_t datalen)
339 {
340 	struct wlan_objmgr_psoc *psoc;
341 	struct wmi_unified *wmi_handle;
342 	struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops;
343 	QDF_STATUS status;
344 	struct mlo_link_disable_request_evt_params evt_params;
345 
346 	if (!scn || !data) {
347 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
348 		return -EINVAL;
349 	}
350 
351 	psoc = target_if_get_psoc_from_scn_hdl(scn);
352 	if (!psoc) {
353 		target_if_err("null psoc");
354 		return -EINVAL;
355 	}
356 
357 	mlo_rx_ops = target_if_mlo_get_rx_ops(psoc);
358 	if (!mlo_rx_ops || !mlo_rx_ops->mlo_link_disable_request_handler) {
359 		target_if_err("callback not registered");
360 		return -EINVAL;
361 	}
362 
363 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
364 	if (!wmi_handle) {
365 		target_if_err("wmi_handle is null");
366 		return -EINVAL;
367 	}
368 
369 	status = wmi_extract_mlo_link_disable_request_evt(wmi_handle, data,
370 							  &evt_params);
371 	if (QDF_IS_STATUS_ERROR(status)) {
372 		target_if_err("Unable to extract fixed param, ret = %d",
373 			      status);
374 		goto exit;
375 	}
376 
377 	status = mlo_rx_ops->mlo_link_disable_request_handler(psoc,
378 							      &evt_params);
379 exit:
380 	return qdf_status_to_os_return(status);
381 }
382 
383 /**
384  * target_if_mlo_register_event_handler() - function to register handler for
385  *  mlo related wmi event from firmware.
386  * @psoc: psoc pointer
387  *
388  * Return: QDF_STATUS
389  */
390 static QDF_STATUS
391 target_if_mlo_register_event_handler(struct wlan_objmgr_psoc *psoc)
392 {
393 	QDF_STATUS status;
394 	struct wmi_unified *wmi_handle;
395 
396 	if (!psoc) {
397 		target_if_err("PSOC is NULL!");
398 		return QDF_STATUS_E_NULL_VALUE;
399 	}
400 
401 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
402 	if (!wmi_handle) {
403 		target_if_err("wmi_handle is null");
404 		return QDF_STATUS_E_INVAL;
405 	}
406 
407 	status = wmi_unified_register_event(
408 			wmi_handle,
409 			wmi_mlo_link_removal_eventid,
410 			target_if_mlo_link_removal_event_handler);
411 	if (QDF_IS_STATUS_ERROR(status))
412 		target_if_err("Couldn't register handler for Link removal WMI event %d",
413 			      status);
414 
415 	status = wmi_unified_register_event_handler(
416 			wmi_handle,
417 			wmi_mlo_link_set_active_resp_eventid,
418 			target_if_mlo_link_set_active_resp_handler,
419 			WMI_RX_SERIALIZER_CTX);
420 	if (QDF_IS_STATUS_ERROR(status)) {
421 		target_if_err("Register mlo link set active resp cb errcode %d",
422 			      status);
423 		if (status == QDF_STATUS_E_NOSUPPORT)
424 			status = QDF_STATUS_SUCCESS;
425 	}
426 
427 	target_if_mlo_register_vdev_tid_to_link_map_event(wmi_handle);
428 	target_if_mlo_register_mlo_link_state_info_event(wmi_handle);
429 
430 	status = wmi_unified_register_event_handler(wmi_handle,
431 			wmi_mlo_link_disable_request_eventid,
432 			target_if_mlo_link_disable_request_event_handler,
433 			WMI_RX_SERIALIZER_CTX);
434 	if (QDF_IS_STATUS_ERROR(status)) {
435 		target_if_err("Couldn't register handler for link disable request WMI event %d",
436 			      status);
437 		if (status == QDF_STATUS_E_NOSUPPORT)
438 			status = QDF_STATUS_SUCCESS;
439 	}
440 
441 	status = target_if_mlo_register_link_switch_event_handler(wmi_handle);
442 	if (QDF_IS_STATUS_ERROR(status)) {
443 		target_if_err("Couldn't register handler for link switch WMI event %d",
444 			      status);
445 		if (status == QDF_STATUS_E_NOSUPPORT)
446 			status = QDF_STATUS_SUCCESS;
447 	}
448 
449 	return status;
450 }
451 
452 /**
453  * target_if_mlo_unregister_event_handler() - function to unregister handler for
454  *  mlo related wmi event from firmware.
455  * @psoc: psoc pointer
456  *
457  * Return: QDF_STATUS
458  */
459 static QDF_STATUS
460 target_if_mlo_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
461 {
462 	struct wmi_unified *wmi_handle;
463 
464 	if (!psoc) {
465 		target_if_err("PSOC is NULL!");
466 		return QDF_STATUS_E_INVAL;
467 	}
468 
469 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
470 	if (!wmi_handle) {
471 		target_if_err("wmi_handle is null");
472 		return QDF_STATUS_E_INVAL;
473 	}
474 
475 	wmi_unified_unregister_event_handler(wmi_handle,
476 		wmi_mlo_link_set_active_resp_eventid);
477 
478 	wmi_unified_unregister_event(wmi_handle,
479 				     wmi_mlo_link_removal_eventid);
480 
481 	target_if_mlo_unregister_vdev_tid_to_link_map_event(wmi_handle);
482 	target_if_mlo_unregister_mlo_link_state_info_event(wmi_handle);
483 
484 	wmi_unified_unregister_event(wmi_handle,
485 				     wmi_mlo_link_disable_request_eventid);
486 
487 	target_if_mlo_unregister_link_switch_event_handler(wmi_handle);
488 
489 	return QDF_STATUS_SUCCESS;
490 }
491 
492 /**
493  * target_if_mlo_link_set_active() - Send WMI command for set mlo link active
494  * @psoc: psoc pointer
495  * @param: parameter for setting mlo link active
496  *
497  * Return: QDF_STATUS
498  */
499 static QDF_STATUS
500 target_if_mlo_link_set_active(struct wlan_objmgr_psoc *psoc,
501 			      struct mlo_link_set_active_param *param)
502 {
503 	QDF_STATUS ret;
504 	struct wmi_unified *wmi_handle;
505 
506 	if (!psoc) {
507 		target_if_err("null psoc");
508 		return QDF_STATUS_E_FAILURE;
509 	}
510 
511 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
512 	if (!wmi_handle) {
513 		target_if_err("null handle");
514 		return QDF_STATUS_E_FAILURE;
515 	}
516 
517 	ret = wmi_send_mlo_link_set_active_cmd(wmi_handle, param);
518 	if (QDF_IS_STATUS_ERROR(ret))
519 		target_if_err("wmi mlo link set active send failed: %d", ret);
520 
521 	return ret;
522 }
523 
524 static int target_if_mlo_vdev_tid_to_link_map_event_handler(
525 		ol_scn_t scn, uint8_t *event_buff, uint32_t len)
526 {
527 	struct wlan_objmgr_psoc *psoc;
528 	struct mlo_vdev_host_tid_to_link_map_resp event = {0};
529 	struct wmi_unified *wmi_handle;
530 	struct wlan_lmac_if_mlo_rx_ops *rx_ops;
531 	QDF_STATUS status;
532 
533 	if (!event_buff) {
534 		mlme_err("Received NULL event ptr from FW");
535 		return -EINVAL;
536 	}
537 
538 	psoc = target_if_get_psoc_from_scn_hdl(scn);
539 	if (!psoc) {
540 		mlme_err("PSOC is NULL");
541 		return -EINVAL;
542 	}
543 
544 	rx_ops = target_if_mlo_get_rx_ops(psoc);
545 	if (!rx_ops || !rx_ops->process_mlo_vdev_tid_to_link_map_event) {
546 		target_if_err("callback not registered");
547 		return -EINVAL;
548 	}
549 
550 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
551 	if (!wmi_handle) {
552 		mlme_err("wmi_handle is null");
553 		return -EINVAL;
554 	}
555 
556 	if (wmi_extract_mlo_vdev_tid_to_link_map_event(wmi_handle, event_buff,
557 						       &event)) {
558 		mlme_err("Failed to extract TID-to-link mapping event");
559 		return -EINVAL;
560 	}
561 
562 	status = rx_ops->process_mlo_vdev_tid_to_link_map_event(psoc, &event);
563 
564 	return qdf_status_to_os_return(status);
565 }
566 
567 void target_if_mlo_register_vdev_tid_to_link_map_event(
568 		struct wmi_unified *wmi_handle)
569 {
570 	wmi_unified_register_event_handler(
571 			wmi_handle, wmi_mlo_ap_vdev_tid_to_link_map_eventid,
572 			target_if_mlo_vdev_tid_to_link_map_event_handler,
573 			WMI_RX_EXECUTION_CTX);
574 }
575 
576 void target_if_mlo_unregister_vdev_tid_to_link_map_event(
577 		struct wmi_unified *wmi_handle)
578 {
579 	wmi_unified_unregister_event_handler(
580 			wmi_handle, wmi_mlo_ap_vdev_tid_to_link_map_eventid);
581 }
582 
583 static int target_if_mlo_link_state_info_event_handler(
584 		ol_scn_t scn, uint8_t *event_buff, uint32_t len)
585 {
586 	struct wlan_objmgr_psoc *psoc;
587 	struct wmi_unified *wmi_handle;
588 	QDF_STATUS status;
589 	struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops;
590 	struct ml_link_state_info_event event = {0};
591 
592 	if (!event_buff) {
593 		target_if_err("Received NULL event ptr from FW");
594 		return -EINVAL;
595 	}
596 
597 	psoc = target_if_get_psoc_from_scn_hdl(scn);
598 	if (!psoc) {
599 		target_if_err("PSOC is NULL");
600 		return -EINVAL;
601 	}
602 
603 	mlo_rx_ops = target_if_mlo_get_rx_ops(psoc);
604 	if (!mlo_rx_ops || !mlo_rx_ops->process_mlo_link_state_info_event) {
605 		target_if_err("callback not registered");
606 		return -EINVAL;
607 	}
608 
609 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
610 	if (!wmi_handle) {
611 		target_if_err("wmi_handle is null");
612 		return -EINVAL;
613 	}
614 
615 	if (wmi_extract_mlo_link_state_info_event(wmi_handle, event_buff,
616 						  &event)) {
617 		target_if_err("Failed to extract link status event");
618 		return -EINVAL;
619 	}
620 
621 	status = mlo_rx_ops->process_mlo_link_state_info_event(psoc, &event);
622 	return qdf_status_to_os_return(status);
623 }
624 
625 void target_if_mlo_register_mlo_link_state_info_event(
626 		struct wmi_unified *wmi_handle)
627 {
628 	wmi_unified_register_event_handler(
629 		wmi_handle, wmi_mlo_link_state_info_eventid,
630 		target_if_mlo_link_state_info_event_handler,
631 		WMI_RX_EXECUTION_CTX);
632 }
633 
634 void  target_if_mlo_unregister_mlo_link_state_info_event(
635 		struct wmi_unified *wmi_handle)
636 {
637 	wmi_unified_unregister_event_handler(
638 			wmi_handle,
639 			wmi_mlo_link_state_info_eventid);
640 }
641 
642 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
643 /**
644  * target_if_fill_provisioned_links() - API to fill the provisioned links
645  * @params: Pointer to T2LM params structure
646  * @t2lm: Pointer to T2LM info structure
647  *
648  * Return: none
649  */
650 static inline void target_if_fill_provisioned_links(
651 		struct wmi_host_tid_to_link_map_params *params,
652 		struct wlan_t2lm_info *t2lm)
653 {
654 	qdf_mem_copy(&params->t2lm_info[params->num_dir].t2lm_provisioned_links,
655 		     &t2lm->ieee_link_map_tid,
656 		     sizeof(uint16_t) * T2LM_MAX_NUM_TIDS);
657 }
658 #else
659 static inline void target_if_fill_provisioned_links(
660 		struct wmi_host_tid_to_link_map_params *params,
661 		struct wlan_t2lm_info *t2lm)
662 {
663 	qdf_mem_copy(&params->t2lm_info[params->num_dir].t2lm_provisioned_links,
664 		     &t2lm->hw_link_map_tid,
665 		     sizeof(uint16_t) * T2LM_MAX_NUM_TIDS);
666 }
667 #endif
668 
669 static QDF_STATUS
670 target_if_mlo_send_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev,
671 				       struct wlan_t2lm_info *t2lm)
672 {
673 	struct wmi_unified *wmi_handle = NULL;
674 	struct wmi_host_tid_to_link_map_params params = {0};
675 	struct wlan_objmgr_pdev *pdev = NULL;
676 	int tid = 0;
677 	QDF_STATUS status;
678 
679 	pdev = wlan_vdev_get_pdev(vdev);
680 	if (!pdev) {
681 		t2lm_err("null pdev");
682 		return QDF_STATUS_E_NULL_VALUE;
683 	}
684 
685 	wmi_handle = lmac_get_pdev_wmi_handle(pdev);
686 	if (!wmi_handle) {
687 		t2lm_err("null wmi handle");
688 		return QDF_STATUS_E_NULL_VALUE;
689 	}
690 
691 	params.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
692 	qdf_mem_copy(params.peer_macaddr, vdev->vdev_objmgr.bss_peer->macaddr,
693 		     QDF_MAC_ADDR_SIZE);
694 
695 	t2lm_debug("Fill T2LM WMI info for peer: " QDF_MAC_ADDR_FMT " pdev_id:%d",
696 		   QDF_MAC_ADDR_REF(params.peer_macaddr), params.pdev_id);
697 
698 	params.t2lm_info[params.num_dir].direction = t2lm->direction;
699 	params.t2lm_info[params.num_dir].default_link_mapping =
700 		t2lm->default_link_mapping;
701 
702 	if (!params.t2lm_info[params.num_dir].default_link_mapping)
703 		target_if_fill_provisioned_links(&params, t2lm);
704 
705 	t2lm_debug("num_dir:%d direction:%d default_link_mapping:%d",
706 		   params.num_dir, params.t2lm_info[params.num_dir].direction,
707 		   params.t2lm_info[params.num_dir].default_link_mapping);
708 
709 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
710 		t2lm_debug("tid:%d hw_link_map:%x ieee_link_map:%x", tid,
711 			   params.t2lm_info[params.num_dir].t2lm_provisioned_links[tid],
712 			   t2lm->ieee_link_map_tid[tid]);
713 	}
714 
715 	params.num_dir++;
716 
717 	status = wmi_send_mlo_peer_tid_to_link_map_cmd(wmi_handle, &params, true);
718 	if (QDF_IS_STATUS_ERROR(status)) {
719 		t2lm_err("Failed to send T2LM WMI command for pdev_id:%d peer_mac: " QDF_MAC_ADDR_FMT,
720 			 params.pdev_id,
721 			 QDF_MAC_ADDR_REF(params.peer_macaddr));
722 		return status;
723 	}
724 
725 	return status;
726 }
727 
728 static QDF_STATUS
729 target_if_request_ml_link_state_info(struct wlan_objmgr_psoc *psoc,
730 				     struct mlo_link_state_cmd_params *cmd)
731 {
732 	struct wmi_unified *wmi_handle = NULL;
733 	struct wmi_host_link_state_params params = {0};
734 	QDF_STATUS status;
735 
736 	if (!psoc) {
737 		target_if_err("null pdev");
738 		return QDF_STATUS_E_NULL_VALUE;
739 	}
740 
741 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
742 	if (!wmi_handle) {
743 		target_if_err("null wmi handle");
744 		return QDF_STATUS_E_NULL_VALUE;
745 	}
746 
747 	if (!cmd) {
748 		target_if_err("cmd is null");
749 		return QDF_STATUS_E_NULL_VALUE;
750 	}
751 
752 	params.vdev_id = cmd->vdev_id;
753 	qdf_mem_copy(params.mld_mac, cmd->mld_mac,
754 		     QDF_MAC_ADDR_SIZE);
755 
756 	status = wmi_send_mlo_link_state_request_cmd(wmi_handle, &params);
757 	return status;
758 }
759 
760 QDF_STATUS target_if_mlo_send_link_removal_cmd(
761 		struct wlan_objmgr_psoc *psoc,
762 		const struct mlo_link_removal_cmd_params *param)
763 {
764 	struct wmi_unified *wmi_handle;
765 
766 	if (!psoc) {
767 		target_if_err("null psoc");
768 		return QDF_STATUS_E_NULL_VALUE;
769 	}
770 
771 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
772 	if (!wmi_handle) {
773 		target_if_err("null handle");
774 		return QDF_STATUS_E_FAILURE;
775 	}
776 
777 	return wmi_send_mlo_link_removal_cmd(wmi_handle, param);
778 }
779 
780 QDF_STATUS target_if_mlo_send_vdev_pause(struct wlan_objmgr_psoc *psoc,
781 					 struct mlo_vdev_pause *info)
782 {
783 	struct wmi_unified *wmi_handle;
784 
785 	if (!psoc) {
786 		target_if_err("null psoc");
787 		return QDF_STATUS_E_NULL_VALUE;
788 	}
789 
790 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
791 	if (!wmi_handle) {
792 		target_if_err("null handle");
793 		return QDF_STATUS_E_FAILURE;
794 	}
795 
796 	return wmi_send_mlo_vdev_pause(wmi_handle, info);
797 }
798 
799 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
800 static QDF_STATUS target_if_mlo_send_peer_ptqm_migrate_cmd(
801 					struct wlan_objmgr_vdev *vdev,
802 					struct peer_ptqm_migrate_params *param)
803 {
804 	struct wlan_objmgr_pdev *pdev = NULL;
805 	struct wmi_unified *wmi_handle;
806 	QDF_STATUS status;
807 
808 	if (!vdev || !param) {
809 		target_if_err("Invalid input");
810 		return QDF_STATUS_E_INVAL;
811 	}
812 
813 	pdev = wlan_vdev_get_pdev(vdev);
814 	if (!pdev) {
815 		target_if_err("null pdev");
816 		return QDF_STATUS_E_NULL_VALUE;
817 	}
818 
819 	wmi_handle = lmac_get_pdev_wmi_handle(pdev);
820 	if (!wmi_handle) {
821 		target_if_err("Failed to get WMI handle!");
822 		return QDF_STATUS_E_INVAL;
823 	}
824 
825 	status = wmi_unified_peer_ptqm_migrate_send(wmi_handle, param);
826 	if (QDF_IS_STATUS_ERROR(status))
827 		target_if_err("Failed to send peer ptqm migration WMI");
828 
829 	return status;
830 }
831 
832 static void target_if_mlo_register_peer_ptqm_migrate_send(
833 		struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
834 {
835 	mlo_tx_ops->peer_ptqm_migrate_send =
836 				target_if_mlo_send_peer_ptqm_migrate_cmd;
837 }
838 #else
839 static void target_if_mlo_register_peer_ptqm_migrate_send(
840 		struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
841 {
842 }
843 #endif
844 
845 /**
846  * target_if_mlo_register_tx_ops() - lmac handler to register mlo tx ops
847  *  callback functions
848  * @tx_ops: wlan_lmac_if_tx_ops object
849  *
850  * Return: QDF_STATUS
851  */
852 QDF_STATUS
853 target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
854 {
855 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
856 
857 	if (!tx_ops) {
858 		target_if_err("lmac tx ops is NULL!");
859 		return QDF_STATUS_E_INVAL;
860 	}
861 
862 	mlo_tx_ops = &tx_ops->mlo_ops;
863 	if (!mlo_tx_ops) {
864 		target_if_err("lmac tx ops is NULL!");
865 		return QDF_STATUS_E_FAILURE;
866 	}
867 
868 	mlo_tx_ops->register_events =
869 		target_if_mlo_register_event_handler;
870 	mlo_tx_ops->unregister_events =
871 		target_if_mlo_unregister_event_handler;
872 	mlo_tx_ops->link_set_active = target_if_mlo_link_set_active;
873 	mlo_tx_ops->send_tid_to_link_mapping =
874 		target_if_mlo_send_tid_to_link_mapping;
875 	mlo_tx_ops->send_link_removal_cmd = target_if_mlo_send_link_removal_cmd;
876 	mlo_tx_ops->request_link_state_info_cmd =
877 		target_if_request_ml_link_state_info;
878 	mlo_tx_ops->send_vdev_pause = target_if_mlo_send_vdev_pause;
879 
880 	target_if_mlo_register_link_switch_cnf_handler(mlo_tx_ops);
881 
882 	target_if_mlo_register_peer_ptqm_migrate_send(mlo_tx_ops);
883 	return QDF_STATUS_SUCCESS;
884 }
885 
886