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(¶ms->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(¶ms->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(¶ms, t2lm);
787
788 target_if_fill_timer(¶ms, 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, ¶ms, 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, ¶ms);
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, ¶ms);
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(¶ms.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, ¶ms);
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