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
target_if_mlo_link_set_active_resp_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)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
target_if_mlo_link_removal_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)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
target_if_extract_mlo_link_removal_info_mgmt_rx(wmi_unified_t wmi_handle,void * evt_buf,struct mgmt_rx_event_params * rx_event)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
target_if_send_mlo_link_switch_cnf_cmd(struct wlan_objmgr_psoc * psoc,struct wlan_mlo_link_switch_cnf * params)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
target_if_mlo_link_state_switch_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)221 target_if_mlo_link_state_switch_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 	struct mlo_link_switch_state_info evt_params;
228 	QDF_STATUS status;
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 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
242 	if (!wmi_handle) {
243 		target_if_err("wmi_handle is null");
244 		return -EINVAL;
245 	}
246 
247 	mlo_rx_ops = target_if_mlo_get_rx_ops(psoc);
248 	if (!mlo_rx_ops || !mlo_rx_ops->mlo_link_state_switch_event_handler) {
249 		target_if_err("callback not registered");
250 		return -EINVAL;
251 	}
252 
253 	status = wmi_extract_mlo_link_state_switch_evt(wmi_handle, data,
254 						       datalen,
255 						       &evt_params);
256 	if (QDF_IS_STATUS_ERROR(status)) {
257 		target_if_err("Unable to extract link state switch params");
258 		goto exit;
259 	}
260 
261 	status = mlo_rx_ops->mlo_link_state_switch_event_handler(psoc,
262 								 &evt_params);
263 exit:
264 	return qdf_status_to_os_return(status);
265 }
266 
267 static int
target_if_mlo_link_switch_request_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)268 target_if_mlo_link_switch_request_event_handler(ol_scn_t scn, uint8_t *data,
269 						uint32_t datalen)
270 {
271 	struct wlan_objmgr_psoc *psoc;
272 	struct wmi_unified *wmi_handle;
273 	struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops;
274 	QDF_STATUS status;
275 	struct wlan_mlo_link_switch_req req = {0};
276 
277 	if (!scn || !data) {
278 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
279 		return -EINVAL;
280 	}
281 
282 	psoc = target_if_get_psoc_from_scn_hdl(scn);
283 	if (!psoc) {
284 		target_if_err("null psoc");
285 		return -EINVAL;
286 	}
287 
288 	mlo_rx_ops = target_if_mlo_get_rx_ops(psoc);
289 	if (!mlo_rx_ops || !mlo_rx_ops->mlo_link_switch_request_handler) {
290 		target_if_err("callback not registered");
291 		return -EINVAL;
292 	}
293 
294 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
295 	if (!wmi_handle) {
296 		target_if_err("wmi_handle is null");
297 		return -EINVAL;
298 	}
299 
300 	status = wmi_extract_mlo_link_switch_request_evt(wmi_handle, data,
301 							 &req);
302 
303 	if (QDF_IS_STATUS_ERROR(status)) {
304 		target_if_err("Unable to extract fixed param, ret = %d",
305 			      status);
306 		goto exit;
307 	}
308 
309 	status = mlo_rx_ops->mlo_link_switch_request_handler(psoc, &req);
310 
311 exit:
312 	return status;
313 }
314 
315 static inline void
target_if_mlo_register_link_switch_cnf_handler(struct wlan_lmac_if_mlo_tx_ops * mlo_tx_ops)316 target_if_mlo_register_link_switch_cnf_handler(struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
317 {
318 	mlo_tx_ops->send_mlo_link_switch_cnf_cmd =
319 			target_if_send_mlo_link_switch_cnf_cmd;
320 }
321 
322 static QDF_STATUS
target_if_mlo_register_link_switch_event_handler(struct wmi_unified * wmi_handle)323 target_if_mlo_register_link_switch_event_handler(struct wmi_unified *wmi_handle)
324 {
325 	QDF_STATUS status;
326 
327 	status = wmi_unified_register_event_handler(
328 			wmi_handle,
329 			wmi_mlo_link_switch_request_eventid,
330 			target_if_mlo_link_switch_request_event_handler,
331 			WMI_RX_SERIALIZER_CTX);
332 	if (QDF_IS_STATUS_ERROR(status))
333 		target_if_err("Register event:%d failed",
334 			      wmi_mlo_link_switch_request_eventid);
335 
336 	status = wmi_unified_register_event_handler(
337 			wmi_handle, wmi_mlo_link_state_switch_eventid,
338 			target_if_mlo_link_state_switch_event_handler,
339 			WMI_RX_SERIALIZER_CTX);
340 	if (QDF_IS_STATUS_ERROR(status))
341 		target_if_err("Register event:%d failed",
342 			      wmi_mlo_link_state_switch_eventid);
343 
344 	return status;
345 }
346 
347 static inline void
target_if_mlo_unregister_link_switch_event_handler(struct wmi_unified * wmi_handle)348 target_if_mlo_unregister_link_switch_event_handler(struct wmi_unified *wmi_handle)
349 {
350 	wmi_unified_unregister_event(wmi_handle,
351 				     wmi_mlo_link_switch_request_eventid);
352 }
353 #else
354 static inline QDF_STATUS
target_if_mlo_register_link_switch_event_handler(struct wmi_unified * wmi_handle)355 target_if_mlo_register_link_switch_event_handler(struct wmi_unified *wmi_handle)
356 {
357 	return QDF_STATUS_E_NOSUPPORT;
358 }
359 
360 static inline void
target_if_mlo_unregister_link_switch_event_handler(struct wmi_unified * wmi_handle)361 target_if_mlo_unregister_link_switch_event_handler(struct wmi_unified *wmi_handle)
362 {
363 }
364 
365 static inline QDF_STATUS
target_if_send_mlo_link_switch_cnf_cmd(struct wlan_objmgr_psoc * psoc,struct wlan_mlo_link_switch_cnf * params)366 target_if_send_mlo_link_switch_cnf_cmd(struct wlan_objmgr_psoc *psoc,
367 				       struct wlan_mlo_link_switch_cnf *params)
368 {
369 	return QDF_STATUS_SUCCESS;
370 }
371 
372 static inline void
target_if_mlo_register_link_switch_cnf_handler(struct wlan_lmac_if_mlo_tx_ops * mlo_tx_ops)373 target_if_mlo_register_link_switch_cnf_handler(struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
374 {
375 }
376 
377 static inline int
target_if_mlo_link_switch_request_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)378 target_if_mlo_link_switch_request_event_handler(ol_scn_t scn, uint8_t *data,
379 						uint32_t datalen)
380 {
381 	return 0;
382 }
383 #endif
384 
385 /**
386  * target_if_mlo_link_disable_request_event_handler() - Handler for MLO
387  * link disable request event sent by the FW
388  * @scn: scn handle
389  * @data: data buffer for event
390  * @datalen: data length
391  *
392  * Return: 0 on success, else error on failure
393  */
394 static int
target_if_mlo_link_disable_request_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)395 target_if_mlo_link_disable_request_event_handler(ol_scn_t scn, uint8_t *data,
396 						 uint32_t datalen)
397 {
398 	struct wlan_objmgr_psoc *psoc;
399 	struct wmi_unified *wmi_handle;
400 	struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops;
401 	QDF_STATUS status;
402 	struct mlo_link_disable_request_evt_params evt_params;
403 
404 	if (!scn || !data) {
405 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
406 		return -EINVAL;
407 	}
408 
409 	psoc = target_if_get_psoc_from_scn_hdl(scn);
410 	if (!psoc) {
411 		target_if_err("null psoc");
412 		return -EINVAL;
413 	}
414 
415 	mlo_rx_ops = target_if_mlo_get_rx_ops(psoc);
416 	if (!mlo_rx_ops || !mlo_rx_ops->mlo_link_disable_request_handler) {
417 		target_if_err("callback not registered");
418 		return -EINVAL;
419 	}
420 
421 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
422 	if (!wmi_handle) {
423 		target_if_err("wmi_handle is null");
424 		return -EINVAL;
425 	}
426 
427 	status = wmi_extract_mlo_link_disable_request_evt(wmi_handle, data,
428 							  &evt_params);
429 	if (QDF_IS_STATUS_ERROR(status)) {
430 		target_if_err("Unable to extract fixed param, ret = %d",
431 			      status);
432 		goto exit;
433 	}
434 
435 	status = mlo_rx_ops->mlo_link_disable_request_handler(psoc,
436 							      &evt_params);
437 exit:
438 	return qdf_status_to_os_return(status);
439 }
440 
441 /**
442  * target_if_mlo_register_event_handler() - function to register handler for
443  *  mlo related wmi event from firmware.
444  * @psoc: psoc pointer
445  *
446  * Return: QDF_STATUS
447  */
448 static QDF_STATUS
target_if_mlo_register_event_handler(struct wlan_objmgr_psoc * psoc)449 target_if_mlo_register_event_handler(struct wlan_objmgr_psoc *psoc)
450 {
451 	QDF_STATUS status;
452 	struct wmi_unified *wmi_handle;
453 
454 	if (!psoc) {
455 		target_if_err("PSOC is NULL!");
456 		return QDF_STATUS_E_NULL_VALUE;
457 	}
458 
459 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
460 	if (!wmi_handle) {
461 		target_if_err("wmi_handle is null");
462 		return QDF_STATUS_E_INVAL;
463 	}
464 
465 	status = wmi_unified_register_event(
466 			wmi_handle,
467 			wmi_mlo_link_removal_eventid,
468 			target_if_mlo_link_removal_event_handler);
469 	if (QDF_IS_STATUS_ERROR(status))
470 		target_if_err("Couldn't register handler for Link removal WMI event %d",
471 			      status);
472 
473 	status = wmi_unified_register_event_handler(
474 			wmi_handle,
475 			wmi_mlo_link_set_active_resp_eventid,
476 			target_if_mlo_link_set_active_resp_handler,
477 			WMI_RX_SERIALIZER_CTX);
478 	if (QDF_IS_STATUS_ERROR(status)) {
479 		target_if_err("Register mlo link set active resp cb errcode %d",
480 			      status);
481 		if (status == QDF_STATUS_E_NOSUPPORT)
482 			status = QDF_STATUS_SUCCESS;
483 	}
484 
485 	target_if_mlo_register_vdev_tid_to_link_map_event(wmi_handle);
486 	target_if_mlo_register_mlo_link_state_info_event(wmi_handle);
487 
488 	status = wmi_unified_register_event_handler(wmi_handle,
489 			wmi_mlo_link_disable_request_eventid,
490 			target_if_mlo_link_disable_request_event_handler,
491 			WMI_RX_SERIALIZER_CTX);
492 	if (QDF_IS_STATUS_ERROR(status)) {
493 		target_if_err("Couldn't register handler for link disable request WMI event %d",
494 			      status);
495 		if (status == QDF_STATUS_E_NOSUPPORT)
496 			status = QDF_STATUS_SUCCESS;
497 	}
498 
499 	status = target_if_mlo_register_link_switch_event_handler(wmi_handle);
500 	if (QDF_IS_STATUS_ERROR(status)) {
501 		target_if_err("Couldn't register handler for link switch WMI event %d",
502 			      status);
503 		if (status == QDF_STATUS_E_NOSUPPORT)
504 			status = QDF_STATUS_SUCCESS;
505 	}
506 
507 	return status;
508 }
509 
510 /**
511  * target_if_mlo_unregister_event_handler() - function to unregister handler for
512  *  mlo related wmi event from firmware.
513  * @psoc: psoc pointer
514  *
515  * Return: QDF_STATUS
516  */
517 static QDF_STATUS
target_if_mlo_unregister_event_handler(struct wlan_objmgr_psoc * psoc)518 target_if_mlo_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
519 {
520 	struct wmi_unified *wmi_handle;
521 
522 	if (!psoc) {
523 		target_if_err("PSOC is NULL!");
524 		return QDF_STATUS_E_INVAL;
525 	}
526 
527 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
528 	if (!wmi_handle) {
529 		target_if_err("wmi_handle is null");
530 		return QDF_STATUS_E_INVAL;
531 	}
532 
533 	wmi_unified_unregister_event_handler(wmi_handle,
534 		wmi_mlo_link_set_active_resp_eventid);
535 
536 	wmi_unified_unregister_event(wmi_handle,
537 				     wmi_mlo_link_removal_eventid);
538 
539 	target_if_mlo_unregister_vdev_tid_to_link_map_event(wmi_handle);
540 	target_if_mlo_unregister_mlo_link_state_info_event(wmi_handle);
541 
542 	wmi_unified_unregister_event(wmi_handle,
543 				     wmi_mlo_link_disable_request_eventid);
544 
545 	target_if_mlo_unregister_link_switch_event_handler(wmi_handle);
546 
547 	return QDF_STATUS_SUCCESS;
548 }
549 
550 /**
551  * target_if_mlo_link_set_active() - Send WMI command for set mlo link active
552  * @psoc: psoc pointer
553  * @param: parameter for setting mlo link active
554  *
555  * Return: QDF_STATUS
556  */
557 static QDF_STATUS
target_if_mlo_link_set_active(struct wlan_objmgr_psoc * psoc,struct mlo_link_set_active_param * param)558 target_if_mlo_link_set_active(struct wlan_objmgr_psoc *psoc,
559 			      struct mlo_link_set_active_param *param)
560 {
561 	QDF_STATUS ret;
562 	struct wmi_unified *wmi_handle;
563 
564 	if (!psoc) {
565 		target_if_err("null psoc");
566 		return QDF_STATUS_E_FAILURE;
567 	}
568 
569 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
570 	if (!wmi_handle) {
571 		target_if_err("null handle");
572 		return QDF_STATUS_E_FAILURE;
573 	}
574 
575 	ret = wmi_send_mlo_link_set_active_cmd(wmi_handle, param);
576 	if (QDF_IS_STATUS_ERROR(ret))
577 		target_if_err("wmi mlo link set active send failed: %d", ret);
578 
579 	return ret;
580 }
581 
target_if_mlo_vdev_tid_to_link_map_event_handler(ol_scn_t scn,uint8_t * event_buff,uint32_t len)582 static int target_if_mlo_vdev_tid_to_link_map_event_handler(
583 		ol_scn_t scn, uint8_t *event_buff, uint32_t len)
584 {
585 	struct wlan_objmgr_psoc *psoc;
586 	struct mlo_vdev_host_tid_to_link_map_resp event = {0};
587 	struct wmi_unified *wmi_handle;
588 	struct wlan_lmac_if_mlo_rx_ops *rx_ops;
589 	QDF_STATUS status;
590 
591 	if (!event_buff) {
592 		mlme_err("Received NULL event ptr from FW");
593 		return -EINVAL;
594 	}
595 
596 	psoc = target_if_get_psoc_from_scn_hdl(scn);
597 	if (!psoc) {
598 		mlme_err("PSOC is NULL");
599 		return -EINVAL;
600 	}
601 
602 	rx_ops = target_if_mlo_get_rx_ops(psoc);
603 	if (!rx_ops || !rx_ops->process_mlo_vdev_tid_to_link_map_event) {
604 		target_if_err("callback not registered");
605 		return -EINVAL;
606 	}
607 
608 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
609 	if (!wmi_handle) {
610 		mlme_err("wmi_handle is null");
611 		return -EINVAL;
612 	}
613 
614 	if (wmi_extract_mlo_vdev_tid_to_link_map_event(wmi_handle, event_buff,
615 						       &event)) {
616 		mlme_err("Failed to extract TID-to-link mapping event");
617 		return -EINVAL;
618 	}
619 
620 	status = rx_ops->process_mlo_vdev_tid_to_link_map_event(psoc, &event);
621 
622 	return qdf_status_to_os_return(status);
623 }
624 
target_if_mlo_register_vdev_tid_to_link_map_event(struct wmi_unified * wmi_handle)625 void target_if_mlo_register_vdev_tid_to_link_map_event(
626 		struct wmi_unified *wmi_handle)
627 {
628 	wmi_unified_register_event_handler(
629 			wmi_handle, wmi_mlo_ap_vdev_tid_to_link_map_eventid,
630 			target_if_mlo_vdev_tid_to_link_map_event_handler,
631 			WMI_RX_EXECUTION_CTX);
632 }
633 
target_if_mlo_unregister_vdev_tid_to_link_map_event(struct wmi_unified * wmi_handle)634 void target_if_mlo_unregister_vdev_tid_to_link_map_event(
635 		struct wmi_unified *wmi_handle)
636 {
637 	wmi_unified_unregister_event_handler(
638 			wmi_handle, wmi_mlo_ap_vdev_tid_to_link_map_eventid);
639 }
640 
target_if_mlo_link_state_info_event_handler(ol_scn_t scn,uint8_t * event_buff,uint32_t len)641 static int target_if_mlo_link_state_info_event_handler(
642 		ol_scn_t scn, uint8_t *event_buff, uint32_t len)
643 {
644 	struct wlan_objmgr_psoc *psoc;
645 	struct wmi_unified *wmi_handle;
646 	QDF_STATUS status;
647 	struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops;
648 	struct ml_link_state_info_event event = {0};
649 
650 	if (!event_buff) {
651 		target_if_err("Received NULL event ptr from FW");
652 		return -EINVAL;
653 	}
654 
655 	psoc = target_if_get_psoc_from_scn_hdl(scn);
656 	if (!psoc) {
657 		target_if_err("PSOC is NULL");
658 		return -EINVAL;
659 	}
660 
661 	mlo_rx_ops = target_if_mlo_get_rx_ops(psoc);
662 	if (!mlo_rx_ops || !mlo_rx_ops->process_mlo_link_state_info_event) {
663 		target_if_err("callback not registered");
664 		return -EINVAL;
665 	}
666 
667 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
668 	if (!wmi_handle) {
669 		target_if_err("wmi_handle is null");
670 		return -EINVAL;
671 	}
672 
673 	if (wmi_extract_mlo_link_state_info_event(wmi_handle, event_buff,
674 						  &event)) {
675 		target_if_err("Failed to extract link status event");
676 		return -EINVAL;
677 	}
678 
679 	status = mlo_rx_ops->process_mlo_link_state_info_event(psoc, &event);
680 	return qdf_status_to_os_return(status);
681 }
682 
target_if_mlo_register_mlo_link_state_info_event(struct wmi_unified * wmi_handle)683 void target_if_mlo_register_mlo_link_state_info_event(
684 		struct wmi_unified *wmi_handle)
685 {
686 	wmi_unified_register_event_handler(
687 		wmi_handle, wmi_mlo_link_state_info_eventid,
688 		target_if_mlo_link_state_info_event_handler,
689 		WMI_RX_EXECUTION_CTX);
690 }
691 
target_if_mlo_unregister_mlo_link_state_info_event(struct wmi_unified * wmi_handle)692 void  target_if_mlo_unregister_mlo_link_state_info_event(
693 		struct wmi_unified *wmi_handle)
694 {
695 	wmi_unified_unregister_event_handler(
696 			wmi_handle,
697 			wmi_mlo_link_state_info_eventid);
698 }
699 
700 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
701 /**
702  * target_if_fill_provisioned_links() - API to fill the provisioned links
703  * @params: Pointer to T2LM params structure
704  * @t2lm: Pointer to T2LM info structure
705  *
706  * Return: none
707  */
target_if_fill_provisioned_links(struct wmi_host_tid_to_link_map_params * params,struct wlan_t2lm_info * t2lm)708 static inline void target_if_fill_provisioned_links(
709 		struct wmi_host_tid_to_link_map_params *params,
710 		struct wlan_t2lm_info *t2lm)
711 {
712 	qdf_mem_copy(&params->t2lm_info[params->num_dir].t2lm_provisioned_links,
713 		     &t2lm->ieee_link_map_tid,
714 		     sizeof(uint16_t) * T2LM_MAX_NUM_TIDS);
715 }
716 
717 /**
718  * target_if_fill_timer() - API to fill the t2lm timer values
719  * @params: Pointer to T2LM params structure
720  * @t2lm: Pointer to T2LM info structure
721  *
722  * Return: none
723  */
724 static inline void
target_if_fill_timer(struct wmi_host_tid_to_link_map_params * params,struct wlan_t2lm_info * t2lm)725 target_if_fill_timer(struct wmi_host_tid_to_link_map_params *params,
726 		     struct wlan_t2lm_info *t2lm)
727 {
728 	if (t2lm->mapping_switch_time_present)
729 		params->mapping_switch_time = t2lm->mapping_switch_time;
730 
731 	if (t2lm->expected_duration_present)
732 		params->expected_duration = t2lm->expected_duration;
733 }
734 
735 #else
target_if_fill_provisioned_links(struct wmi_host_tid_to_link_map_params * params,struct wlan_t2lm_info * t2lm)736 static inline void target_if_fill_provisioned_links(
737 		struct wmi_host_tid_to_link_map_params *params,
738 		struct wlan_t2lm_info *t2lm)
739 {
740 	qdf_mem_copy(&params->t2lm_info[params->num_dir].t2lm_provisioned_links,
741 		     &t2lm->hw_link_map_tid,
742 		     sizeof(uint16_t) * T2LM_MAX_NUM_TIDS);
743 }
744 
745 static inline void
target_if_fill_timer(struct wmi_host_tid_to_link_map_params * params,struct wlan_t2lm_info * t2lm)746 target_if_fill_timer(struct wmi_host_tid_to_link_map_params *params,
747 		     struct wlan_t2lm_info *t2lm)
748 {
749 }
750 #endif
751 
752 static QDF_STATUS
target_if_mlo_send_tid_to_link_mapping(struct wlan_objmgr_vdev * vdev,struct wlan_t2lm_info * t2lm)753 target_if_mlo_send_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev,
754 				       struct wlan_t2lm_info *t2lm)
755 {
756 	struct wmi_unified *wmi_handle = NULL;
757 	struct wmi_host_tid_to_link_map_params params = {0};
758 	struct wlan_objmgr_pdev *pdev = NULL;
759 	int tid = 0;
760 	QDF_STATUS status;
761 
762 	pdev = wlan_vdev_get_pdev(vdev);
763 	if (!pdev) {
764 		t2lm_err("null pdev");
765 		return QDF_STATUS_E_NULL_VALUE;
766 	}
767 
768 	wmi_handle = lmac_get_pdev_wmi_handle(pdev);
769 	if (!wmi_handle) {
770 		t2lm_err("null wmi handle");
771 		return QDF_STATUS_E_NULL_VALUE;
772 	}
773 
774 	params.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
775 	qdf_mem_copy(params.peer_macaddr, vdev->vdev_objmgr.bss_peer->macaddr,
776 		     QDF_MAC_ADDR_SIZE);
777 
778 	t2lm_debug("Fill T2LM WMI info for peer: " QDF_MAC_ADDR_FMT " pdev_id:%d",
779 		   QDF_MAC_ADDR_REF(params.peer_macaddr), params.pdev_id);
780 
781 	params.t2lm_info[params.num_dir].direction = t2lm->direction;
782 	params.t2lm_info[params.num_dir].default_link_mapping =
783 		t2lm->default_link_mapping;
784 
785 	if (!params.t2lm_info[params.num_dir].default_link_mapping)
786 		target_if_fill_provisioned_links(&params, t2lm);
787 
788 	target_if_fill_timer(&params, t2lm);
789 	t2lm_debug("mapping_switch_time_present %d MST %d",
790 		   t2lm->mapping_switch_time_present,
791 		   params.mapping_switch_time);
792 	t2lm_debug("expected_switch_time_present %d EDT %d",
793 		   t2lm->expected_duration_present,
794 		   params.expected_duration);
795 
796 	t2lm_debug("num_dir:%d direction:%d default_link_mapping:%d",
797 		   params.num_dir, params.t2lm_info[params.num_dir].direction,
798 		   params.t2lm_info[params.num_dir].default_link_mapping);
799 
800 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
801 		t2lm_debug("tid:%d hw_link_map:%x ieee_link_map:%x", tid,
802 			   params.t2lm_info[params.num_dir].t2lm_provisioned_links[tid],
803 			   t2lm->ieee_link_map_tid[tid]);
804 	}
805 
806 	params.num_dir++;
807 
808 	status = wmi_send_mlo_peer_tid_to_link_map_cmd(wmi_handle, &params, true);
809 	if (QDF_IS_STATUS_ERROR(status)) {
810 		t2lm_err("Failed to send T2LM WMI command for pdev_id:%d peer_mac: " QDF_MAC_ADDR_FMT,
811 			 params.pdev_id,
812 			 QDF_MAC_ADDR_REF(params.peer_macaddr));
813 		return status;
814 	}
815 
816 	return status;
817 }
818 
819 static QDF_STATUS
target_if_request_ml_link_state_info(struct wlan_objmgr_psoc * psoc,struct mlo_link_state_cmd_params * cmd)820 target_if_request_ml_link_state_info(struct wlan_objmgr_psoc *psoc,
821 				     struct mlo_link_state_cmd_params *cmd)
822 {
823 	struct wmi_unified *wmi_handle = NULL;
824 	struct wmi_host_link_state_params params = {0};
825 	QDF_STATUS status;
826 
827 	if (!psoc) {
828 		target_if_err("null pdev");
829 		return QDF_STATUS_E_NULL_VALUE;
830 	}
831 
832 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
833 	if (!wmi_handle) {
834 		target_if_err("null wmi handle");
835 		return QDF_STATUS_E_NULL_VALUE;
836 	}
837 
838 	if (!cmd) {
839 		target_if_err("cmd is null");
840 		return QDF_STATUS_E_NULL_VALUE;
841 	}
842 
843 	params.vdev_id = cmd->vdev_id;
844 	qdf_mem_copy(params.mld_mac, cmd->mld_mac,
845 		     QDF_MAC_ADDR_SIZE);
846 
847 	status = wmi_send_mlo_link_state_request_cmd(wmi_handle, &params);
848 	return status;
849 }
850 
851 #ifdef WLAN_WSI_STATS_SUPPORT
852 static QDF_STATUS
target_if_mlo_send_wsi_link_info_cmd(struct wlan_objmgr_pdev * pdev,struct mlo_wsi_link_stats * param)853 target_if_mlo_send_wsi_link_info_cmd(struct wlan_objmgr_pdev *pdev,
854 				     struct mlo_wsi_link_stats *param)
855 {
856 	struct wmi_unified *wmi_handle;
857 	struct wmi_wsi_stats_info_params params = {0};
858 
859 	if (!pdev) {
860 		target_if_err("null pdev");
861 		return QDF_STATUS_E_NULL_VALUE;
862 	}
863 	wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
864 	if (!wmi_handle) {
865 		target_if_err("null handle");
866 		return QDF_STATUS_E_FAILURE;
867 	}
868 
869 	params.pdev_id = pdev->pdev_objmgr.wlan_pdev_id;
870 	params.wsi_ingress_load_info = param->ingress_cnt;
871 	params.wsi_egress_load_info = param->egress_cnt;
872 
873 	target_if_debug("pdev id %d, ingress %d, egress %d", params.pdev_id,
874 			params.wsi_ingress_load_info,
875 			params.wsi_egress_load_info);
876 
877 	return wmi_unified_config_wsi_stats_info_cmd_send(wmi_handle, &params);
878 }
879 #else
880 static QDF_STATUS
target_if_mlo_send_wsi_link_info_cmd(struct wlan_objmgr_pdev * pdev,struct mlo_wsi_link_stats * param)881 target_if_mlo_send_wsi_link_info_cmd(struct wlan_objmgr_pdev *pdev,
882 				     struct mlo_wsi_link_stats *param)
883 {
884 	return QDF_STATUS_SUCCESS;
885 }
886 #endif
887 static QDF_STATUS
target_if_send_link_set_bss_params_cmd(struct wlan_objmgr_psoc * psoc,struct mlo_link_bss_params * cmd)888 target_if_send_link_set_bss_params_cmd(struct wlan_objmgr_psoc *psoc,
889 				       struct mlo_link_bss_params *cmd)
890 {
891 	QDF_STATUS status;
892 	struct wmi_unified *wmi_handle = NULL;
893 	struct wmi_host_link_bss_params params = {0};
894 
895 	if (!psoc) {
896 		target_if_err("null pdev");
897 		return QDF_STATUS_E_NULL_VALUE;
898 	}
899 
900 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
901 	if (!wmi_handle) {
902 		target_if_err("null wmi handle");
903 		return QDF_STATUS_E_NULL_VALUE;
904 	}
905 	if (!cmd) {
906 		target_if_err("cmd is null");
907 		return QDF_STATUS_E_NULL_VALUE;
908 	}
909 	params.link_id = cmd->link_id;
910 	qdf_mem_copy(&params.ap_mld_mac[0], &cmd->ap_mld_mac[0],
911 		     QDF_MAC_ADDR_SIZE);
912 
913 	params.chan.ch_freq = cmd->chan->ch_freq;
914 	params.chan.ch_cfreq1 = cmd->chan->ch_cfreq1;
915 	params.chan.ch_cfreq2 = cmd->chan->ch_cfreq2;
916 	params.chan.ch_phymode  = cmd->chan->ch_phymode;
917 
918 	status = wmi_send_link_set_bss_params_cmd(wmi_handle, &params);
919 
920 	return status;
921 }
922 
target_if_mlo_send_link_removal_cmd(struct wlan_objmgr_psoc * psoc,const struct mlo_link_removal_cmd_params * param)923 QDF_STATUS target_if_mlo_send_link_removal_cmd(
924 		struct wlan_objmgr_psoc *psoc,
925 		const struct mlo_link_removal_cmd_params *param)
926 {
927 	struct wmi_unified *wmi_handle;
928 
929 	if (!psoc) {
930 		target_if_err("null psoc");
931 		return QDF_STATUS_E_NULL_VALUE;
932 	}
933 
934 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
935 	if (!wmi_handle) {
936 		target_if_err("null handle");
937 		return QDF_STATUS_E_FAILURE;
938 	}
939 
940 	return wmi_send_mlo_link_removal_cmd(wmi_handle, param);
941 }
942 
target_if_mlo_send_vdev_pause(struct wlan_objmgr_psoc * psoc,struct mlo_vdev_pause * info)943 QDF_STATUS target_if_mlo_send_vdev_pause(struct wlan_objmgr_psoc *psoc,
944 					 struct mlo_vdev_pause *info)
945 {
946 	struct wmi_unified *wmi_handle;
947 
948 	if (!psoc) {
949 		target_if_err("null psoc");
950 		return QDF_STATUS_E_NULL_VALUE;
951 	}
952 
953 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
954 	if (!wmi_handle) {
955 		target_if_err("null handle");
956 		return QDF_STATUS_E_FAILURE;
957 	}
958 
959 	return wmi_send_mlo_vdev_pause(wmi_handle, info);
960 }
961 
962 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
target_if_mlo_send_peer_ptqm_migrate_cmd(struct wlan_objmgr_vdev * vdev,struct peer_ptqm_migrate_params * param)963 static QDF_STATUS target_if_mlo_send_peer_ptqm_migrate_cmd(
964 					struct wlan_objmgr_vdev *vdev,
965 					struct peer_ptqm_migrate_params *param)
966 {
967 	struct wlan_objmgr_pdev *pdev = NULL;
968 	struct wmi_unified *wmi_handle;
969 	QDF_STATUS status;
970 
971 	if (!vdev || !param) {
972 		target_if_err("Invalid input");
973 		return QDF_STATUS_E_INVAL;
974 	}
975 
976 	pdev = wlan_vdev_get_pdev(vdev);
977 	if (!pdev) {
978 		target_if_err("null pdev");
979 		return QDF_STATUS_E_NULL_VALUE;
980 	}
981 
982 	wmi_handle = lmac_get_pdev_wmi_handle(pdev);
983 	if (!wmi_handle) {
984 		target_if_err("Failed to get WMI handle!");
985 		return QDF_STATUS_E_INVAL;
986 	}
987 
988 	status = wmi_unified_peer_ptqm_migrate_send(wmi_handle, param);
989 	if (QDF_IS_STATUS_ERROR(status))
990 		target_if_err("Failed to send peer ptqm migration WMI");
991 
992 	return status;
993 }
994 
target_if_mlo_register_peer_ptqm_migrate_send(struct wlan_lmac_if_mlo_tx_ops * mlo_tx_ops)995 static void target_if_mlo_register_peer_ptqm_migrate_send(
996 		struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
997 {
998 	mlo_tx_ops->peer_ptqm_migrate_send =
999 				target_if_mlo_send_peer_ptqm_migrate_cmd;
1000 }
1001 #else
target_if_mlo_register_peer_ptqm_migrate_send(struct wlan_lmac_if_mlo_tx_ops * mlo_tx_ops)1002 static void target_if_mlo_register_peer_ptqm_migrate_send(
1003 		struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
1004 {
1005 }
1006 #endif
1007 
1008 /**
1009  * target_if_mlo_register_tx_ops() - lmac handler to register mlo tx ops
1010  *  callback functions
1011  * @tx_ops: wlan_lmac_if_tx_ops object
1012  *
1013  * Return: QDF_STATUS
1014  */
1015 QDF_STATUS
target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)1016 target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
1017 {
1018 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
1019 
1020 	if (!tx_ops) {
1021 		target_if_err("lmac tx ops is NULL!");
1022 		return QDF_STATUS_E_INVAL;
1023 	}
1024 
1025 	mlo_tx_ops = &tx_ops->mlo_ops;
1026 	if (!mlo_tx_ops) {
1027 		target_if_err("lmac tx ops is NULL!");
1028 		return QDF_STATUS_E_FAILURE;
1029 	}
1030 
1031 	mlo_tx_ops->register_events =
1032 		target_if_mlo_register_event_handler;
1033 	mlo_tx_ops->unregister_events =
1034 		target_if_mlo_unregister_event_handler;
1035 	mlo_tx_ops->link_set_active = target_if_mlo_link_set_active;
1036 	mlo_tx_ops->send_tid_to_link_mapping =
1037 		target_if_mlo_send_tid_to_link_mapping;
1038 	mlo_tx_ops->send_link_removal_cmd = target_if_mlo_send_link_removal_cmd;
1039 	mlo_tx_ops->request_link_state_info_cmd =
1040 		target_if_request_ml_link_state_info;
1041 	mlo_tx_ops->send_link_set_bss_params_cmd =
1042 		target_if_send_link_set_bss_params_cmd;
1043 	mlo_tx_ops->send_vdev_pause = target_if_mlo_send_vdev_pause;
1044 
1045 	target_if_mlo_register_link_switch_cnf_handler(mlo_tx_ops);
1046 
1047 	mlo_tx_ops->send_wsi_link_info_cmd =
1048 		target_if_mlo_send_wsi_link_info_cmd;
1049 
1050 	target_if_mlo_register_peer_ptqm_migrate_send(mlo_tx_ops);
1051 	return QDF_STATUS_SUCCESS;
1052 }
1053 
1054