xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_11be_tlv.c (revision 8cfe6b10058a04cafb17eed051f2ddf11bee8931)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <osdep.h>
19 #include "wmi.h"
20 #include "wmi_unified_priv.h"
21 #include "wmi_unified_api.h"
22 #ifdef WLAN_MLO_MULTI_CHIP
23 #include "wmi_unified_11be_setup_api.h"
24 #endif
25 #include "wmi_unified_11be_tlv.h"
26 
27 size_t vdev_create_mlo_params_size(struct vdev_create_params *param)
28 {
29 	if (qdf_is_macaddr_zero((struct qdf_mac_addr *)param->mlo_mac))
30 		return WMI_TLV_HDR_SIZE;
31 
32 	return sizeof(wmi_vdev_create_mlo_params) + WMI_TLV_HDR_SIZE;
33 }
34 
35 uint8_t *vdev_create_add_mlo_params(uint8_t *buf_ptr,
36 				    struct vdev_create_params *param)
37 {
38 	wmi_vdev_create_mlo_params *mlo_params;
39 
40 	if (qdf_is_macaddr_zero((struct qdf_mac_addr *)param->mlo_mac)) {
41 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
42 		return buf_ptr + WMI_TLV_HDR_SIZE;
43 	}
44 
45 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
46 		       sizeof(wmi_vdev_create_mlo_params));
47 	buf_ptr += sizeof(uint32_t);
48 
49 	mlo_params = (wmi_vdev_create_mlo_params *)buf_ptr;
50 	WMITLV_SET_HDR(&mlo_params->tlv_header,
51 		       WMITLV_TAG_STRUC_wmi_vdev_create_mlo_params,
52 		       WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_create_mlo_params));
53 
54 	WMI_CHAR_ARRAY_TO_MAC_ADDR(param->mlo_mac, &mlo_params->mld_macaddr);
55 
56 	wmi_debug("MLD Addr = "QDF_MAC_ADDR_FMT,
57 		  QDF_MAC_ADDR_REF(param->mlo_mac));
58 	return buf_ptr + sizeof(wmi_vdev_create_mlo_params);
59 }
60 
61 size_t vdev_start_mlo_params_size(struct vdev_start_params *req)
62 {
63 	size_t vdev_start_mlo_size;
64 
65 	vdev_start_mlo_size = sizeof(wmi_vdev_start_mlo_params) +
66 			      WMI_TLV_HDR_SIZE +
67 			      (req->mlo_partner.num_links *
68 			      sizeof(wmi_partner_link_params)) +
69 			      WMI_TLV_HDR_SIZE;
70 
71 	return vdev_start_mlo_size;
72 }
73 
74 #ifdef WLAN_MCAST_MLO
75 static void vdev_start_add_mlo_mcast_params(uint32_t *mlo_flags,
76 					    struct vdev_start_params *req)
77 {
78 	WMI_MLO_FLAGS_SET_MCAST_VDEV(*mlo_flags,
79 				     req->mlo_flags.mlo_mcast_vdev);
80 }
81 #else
82 #define vdev_start_add_mlo_mcast_params(mlo_flags, req)
83 #endif
84 
85 uint8_t *vdev_start_add_mlo_params(uint8_t *buf_ptr,
86 				   struct vdev_start_params *req)
87 {
88 	wmi_vdev_start_mlo_params *mlo_params;
89 
90 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
91 		       sizeof(wmi_vdev_start_mlo_params));
92 	buf_ptr += sizeof(uint32_t);
93 
94 	mlo_params = (wmi_vdev_start_mlo_params *)buf_ptr;
95 	WMITLV_SET_HDR(&mlo_params->tlv_header,
96 		       WMITLV_TAG_STRUC_wmi_vdev_start_mlo_params,
97 		       WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_start_mlo_params));
98 
99 	mlo_params->mlo_flags.mlo_flags = 0;
100 	WMI_MLO_FLAGS_SET_ENABLED(mlo_params->mlo_flags.mlo_flags,
101 				  req->mlo_flags.mlo_enabled);
102 	WMI_MLO_FLAGS_SET_ASSOC_LINK(mlo_params->mlo_flags.mlo_flags,
103 				     req->mlo_flags.mlo_assoc_link);
104 	WMI_MLO_FLAGS_SET_LINK_ADD(mlo_params->mlo_flags.mlo_flags,
105 				   req->mlo_flags.mlo_link_add);
106 	mlo_params->mlo_flags.emlsr_support = req->mlo_flags.emlsr_support;
107 
108 	vdev_start_add_mlo_mcast_params(&mlo_params->mlo_flags.mlo_flags,
109 					req);
110 
111 	return buf_ptr + sizeof(wmi_vdev_start_mlo_params);
112 }
113 
114 uint8_t *vdev_start_add_ml_partner_links(uint8_t *buf_ptr,
115 					 struct vdev_start_params *req)
116 {
117 	wmi_partner_link_params *ml_partner_link;
118 	struct mlo_vdev_start_partner_links *req_partner;
119 	uint8_t i;
120 
121 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
122 		      (req->mlo_partner.num_links *
123 		      sizeof(wmi_partner_link_params)));
124 	buf_ptr += sizeof(uint32_t);
125 
126 	req_partner = &req->mlo_partner;
127 	ml_partner_link = (wmi_partner_link_params *)buf_ptr;
128 	for (i = 0; i < req->mlo_partner.num_links; i++) {
129 		WMITLV_SET_HDR(&ml_partner_link->tlv_header,
130 			       WMITLV_TAG_STRUC_wmi_partner_link_params,
131 			       WMITLV_GET_STRUCT_TLVLEN(wmi_partner_link_params));
132 		ml_partner_link->vdev_id = req_partner->partner_info[i].vdev_id;
133 		ml_partner_link->hw_link_id =
134 				req_partner->partner_info[i].hw_mld_link_id;
135 		WMI_CHAR_ARRAY_TO_MAC_ADDR(req_partner->partner_info[i].mac_addr,
136 					   &ml_partner_link->vdev_macaddr);
137 		ml_partner_link++;
138 	}
139 
140 	return buf_ptr +
141 		(req->mlo_partner.num_links *
142 		 sizeof(wmi_partner_link_params));
143 }
144 
145 size_t bcn_tmpl_mlo_param_size(struct beacon_tmpl_params *param)
146 {
147 	return WMI_TLV_HDR_SIZE;
148 }
149 
150 uint8_t *bcn_tmpl_add_ml_partner_links(uint8_t *buf_ptr,
151 				       struct beacon_tmpl_params *param)
152 {
153 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
154 	return buf_ptr + WMI_TLV_HDR_SIZE;
155 }
156 
157 size_t bcn_tmpl_ml_info_size(struct beacon_tmpl_params *param)
158 {
159 	return (WMI_TLV_HDR_SIZE + sizeof(wmi_bcn_tmpl_ml_info));
160 }
161 
162 uint8_t *bcn_tmpl_add_ml_info(uint8_t *buf_ptr,
163 			      struct beacon_tmpl_params *param)
164 {
165 	wmi_bcn_tmpl_ml_info *ml_info;
166 
167 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
168 		       sizeof(wmi_bcn_tmpl_ml_info));
169 	buf_ptr += WMI_TLV_HDR_SIZE;
170 
171 	ml_info = (wmi_bcn_tmpl_ml_info *)buf_ptr;
172 
173 	WMITLV_SET_HDR(&ml_info->tlv_header,
174 		       WMITLV_TAG_STRUC_wmi_bcn_tmpl_ml_info,
175 		       WMITLV_GET_STRUCT_TLVLEN(wmi_bcn_tmpl_ml_info));
176 
177 	ml_info->hw_link_id = param->cu_ml_info.hw_link_id;
178 	ml_info->cu_vdev_map_cat1_lo = param->cu_ml_info.cu_vdev_map_cat1_lo;
179 	ml_info->cu_vdev_map_cat1_hi = param->cu_ml_info.cu_vdev_map_cat1_hi;
180 	ml_info->cu_vdev_map_cat2_lo = param->cu_ml_info.cu_vdev_map_cat2_lo;
181 	ml_info->cu_vdev_map_cat2_hi = param->cu_ml_info.cu_vdev_map_cat2_hi;
182 
183 	return buf_ptr + sizeof(wmi_bcn_tmpl_ml_info);
184 }
185 
186 size_t prb_resp_tmpl_ml_info_size(struct wmi_probe_resp_params *param)
187 {
188 	return (WMI_TLV_HDR_SIZE + sizeof(wmi_prb_resp_tmpl_ml_info));
189 }
190 
191 uint8_t *prb_resp_tmpl_add_ml_info(uint8_t *buf_ptr,
192 				   struct wmi_probe_resp_params *param)
193 {
194 	wmi_prb_resp_tmpl_ml_info *ml_info;
195 
196 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
197 		       sizeof(wmi_prb_resp_tmpl_ml_info));
198 	buf_ptr += WMI_TLV_HDR_SIZE;
199 
200 	ml_info = (wmi_prb_resp_tmpl_ml_info *)buf_ptr;
201 
202 	WMITLV_SET_HDR(&ml_info->tlv_header,
203 		       WMITLV_TAG_STRUC_wmi_prb_resp_tmpl_ml_info,
204 		       WMITLV_GET_STRUCT_TLVLEN(wmi_prb_resp_tmpl_ml_info));
205 
206 	ml_info->hw_link_id = param->cu_ml_info.hw_link_id;
207 	ml_info->cu_vdev_map_cat1_lo = param->cu_ml_info.cu_vdev_map_cat1_lo;
208 	ml_info->cu_vdev_map_cat1_hi = param->cu_ml_info.cu_vdev_map_cat1_hi;
209 	ml_info->cu_vdev_map_cat2_lo = param->cu_ml_info.cu_vdev_map_cat2_lo;
210 	ml_info->cu_vdev_map_cat2_hi = param->cu_ml_info.cu_vdev_map_cat2_hi;
211 
212 	return buf_ptr + sizeof(wmi_prb_resp_tmpl_ml_info);
213 }
214 
215 size_t peer_create_mlo_params_size(struct peer_create_params *req)
216 {
217 	return sizeof(wmi_peer_create_mlo_params) + WMI_TLV_HDR_SIZE;
218 }
219 
220 uint8_t *peer_create_add_mlo_params(uint8_t *buf_ptr,
221 				    struct peer_create_params *req)
222 {
223 	wmi_peer_create_mlo_params *mlo_params;
224 
225 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
226 		       sizeof(wmi_peer_create_mlo_params));
227 	buf_ptr += sizeof(uint32_t);
228 
229 	mlo_params = (wmi_peer_create_mlo_params *)buf_ptr;
230 	WMITLV_SET_HDR(&mlo_params->tlv_header,
231 		       WMITLV_TAG_STRUC_wmi_peer_create_mlo_params,
232 		       WMITLV_GET_STRUCT_TLVLEN(wmi_peer_create_mlo_params));
233 
234 	mlo_params->mlo_flags.mlo_flags = 0;
235 	WMI_MLO_FLAGS_SET_ENABLED(mlo_params->mlo_flags.mlo_flags,
236 				  req->mlo_enabled);
237 
238 	return buf_ptr + sizeof(wmi_peer_create_mlo_params);
239 }
240 
241 size_t peer_assoc_mlo_params_size(struct peer_assoc_params *req)
242 {
243 	size_t peer_assoc_mlo_size = sizeof(wmi_peer_assoc_mlo_params) +
244 			WMI_TLV_HDR_SIZE +
245 			(req->ml_links.num_links *
246 			sizeof(wmi_peer_assoc_mlo_partner_link_params)) +
247 			WMI_TLV_HDR_SIZE;
248 
249 	return peer_assoc_mlo_size;
250 }
251 
252 uint8_t *peer_assoc_add_mlo_params(uint8_t *buf_ptr,
253 				   struct peer_assoc_params *req)
254 {
255 	wmi_peer_assoc_mlo_params *mlo_params;
256 
257 	/* Add WMI peer assoc mlo params */
258 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
259 		       sizeof(wmi_peer_assoc_mlo_params));
260 	buf_ptr += sizeof(uint32_t);
261 
262 	mlo_params = (wmi_peer_assoc_mlo_params *)buf_ptr;
263 	WMITLV_SET_HDR(&mlo_params->tlv_header,
264 		       WMITLV_TAG_STRUC_wmi_peer_assoc_mlo_params,
265 		       WMITLV_GET_STRUCT_TLVLEN(wmi_peer_assoc_mlo_params));
266 
267 	mlo_params->mlo_flags.mlo_flags = 0;
268 	WMI_MLO_FLAGS_SET_ENABLED(mlo_params->mlo_flags.mlo_flags,
269 				  req->mlo_params.mlo_enabled);
270 	WMI_MLO_FLAGS_SET_ASSOC_LINK(mlo_params->mlo_flags.mlo_flags,
271 				     req->mlo_params.mlo_assoc_link);
272 	WMI_MLO_FLAGS_SET_PRIMARY_UMAC(mlo_params->mlo_flags.mlo_flags,
273 				       req->mlo_params.mlo_primary_umac);
274 	WMI_MLO_FLAGS_SET_LINK_INDEX_VALID(mlo_params->mlo_flags.mlo_flags,
275 					   req->mlo_params.mlo_logical_link_index_valid);
276 	WMI_MLO_FLAGS_SET_PEER_ID_VALID(mlo_params->mlo_flags.mlo_flags,
277 					req->mlo_params.mlo_peer_id_valid);
278 	mlo_params->mlo_flags.emlsr_support = req->mlo_params.emlsr_support;
279 
280 	mlo_params->mlo_flags.mlo_force_link_inactive =
281 			req->mlo_params.mlo_force_link_inactive;
282 
283 	WMI_CHAR_ARRAY_TO_MAC_ADDR(req->mlo_params.mld_mac,
284 				   &mlo_params->mld_macaddr);
285 	mlo_params->logical_link_index = req->mlo_params.logical_link_index;
286 	mlo_params->mld_peer_id = req->mlo_params.ml_peer_id;
287 
288 	mlo_params->ieee_link_id = req->mlo_params.ieee_link_id;
289 	mlo_params->emlsr_trans_timeout_us = req->mlo_params.trans_timeout_us;
290 	mlo_params->emlsr_trans_delay_us = req->mlo_params.emlsr_trans_delay_us;
291 	mlo_params->emlsr_padding_delay_us = req->mlo_params.emlsr_pad_delay_us;
292 
293 	mlo_params->msd_dur_us = req->mlo_params.medium_sync_duration;
294 	mlo_params->msd_ofdm_ed_thr =
295 			req->mlo_params.medium_sync_ofdm_ed_thresh;
296 	mlo_params->msd_max_num_txops =
297 			req->mlo_params.medium_sync_max_txop_num;
298 
299 	return buf_ptr + sizeof(wmi_peer_assoc_mlo_params);
300 }
301 
302 uint8_t *peer_assoc_add_ml_partner_links(uint8_t *buf_ptr,
303 					 struct peer_assoc_params *req)
304 {
305 	wmi_peer_assoc_mlo_partner_link_params *ml_partner_link;
306 	struct ml_partner_info *partner_info;
307 	uint8_t i;
308 
309 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
310 		       (req->ml_links.num_links *
311 		       sizeof(wmi_peer_assoc_mlo_partner_link_params)));
312 	buf_ptr += sizeof(uint32_t);
313 
314 	ml_partner_link = (wmi_peer_assoc_mlo_partner_link_params *)buf_ptr;
315 	partner_info = req->ml_links.partner_info;
316 	for (i = 0; i < req->ml_links.num_links; i++) {
317 		WMITLV_SET_HDR(&ml_partner_link->tlv_header,
318 			       WMITLV_TAG_STRUC_wmi_peer_assoc_mlo_partner_link_params,
319 			       WMITLV_GET_STRUCT_TLVLEN(wmi_peer_assoc_mlo_partner_link_params));
320 		ml_partner_link->vdev_id = partner_info[i].vdev_id;
321 		ml_partner_link->hw_mld_link_id = partner_info[i].hw_mld_link_id;
322 		ml_partner_link++;
323 	}
324 
325 	return buf_ptr +
326 	       (req->ml_links.num_links *
327 		sizeof(wmi_peer_assoc_mlo_partner_link_params));
328 }
329 
330 size_t peer_delete_mlo_params_size(struct peer_delete_cmd_params *req)
331 {
332 	if (!req->hw_link_id_bitmap)
333 		return WMI_TLV_HDR_SIZE;
334 
335 	return sizeof(wmi_peer_delete_mlo_params) + WMI_TLV_HDR_SIZE;
336 }
337 
338 uint8_t *peer_delete_add_mlo_params(uint8_t *buf_ptr,
339 				    struct peer_delete_cmd_params *req)
340 {
341 	wmi_peer_delete_mlo_params *mlo_params;
342 
343 	if (!req->hw_link_id_bitmap) {
344 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
345 		return buf_ptr + WMI_TLV_HDR_SIZE;
346 	}
347 
348 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
349 		       sizeof(wmi_peer_delete_mlo_params));
350 	buf_ptr += sizeof(uint32_t);
351 
352 	mlo_params = (wmi_peer_delete_mlo_params *)buf_ptr;
353 	WMITLV_SET_HDR(&mlo_params->tlv_header,
354 		       WMITLV_TAG_STRUC_wmi_peer_delete_mlo_params,
355 		       WMITLV_GET_STRUCT_TLVLEN(wmi_peer_delete_mlo_params));
356 	mlo_params->mlo_hw_link_id_bitmap = req->hw_link_id_bitmap;
357 	return buf_ptr + sizeof(wmi_peer_delete_mlo_params);
358 }
359 
360 /**
361  * force_mode_host_to_fw() - translate force mode for MLO link set active
362  *  command
363  * @host_mode: force mode defined by host
364  * @fw_mode: buffer to store force mode defined by FW
365  *
366  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL otherwise
367  */
368 static inline QDF_STATUS
369 force_mode_host_to_fw(enum mlo_link_force_mode host_mode,
370 		      WMI_MLO_LINK_FORCE_MODE *fw_mode)
371 {
372 	switch (host_mode) {
373 	case MLO_LINK_FORCE_MODE_ACTIVE:
374 		*fw_mode = WMI_MLO_LINK_FORCE_ACTIVE;
375 		break;
376 	case MLO_LINK_FORCE_MODE_INACTIVE:
377 		*fw_mode = WMI_MLO_LINK_FORCE_INACTIVE;
378 		break;
379 	case MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE:
380 		*fw_mode = WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE;
381 		break;
382 	case MLO_LINK_FORCE_MODE_ACTIVE_NUM:
383 		*fw_mode = WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM;
384 		break;
385 	case MLO_LINK_FORCE_MODE_INACTIVE_NUM:
386 		*fw_mode = WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM;
387 		break;
388 	case MLO_LINK_FORCE_MODE_NO_FORCE:
389 		*fw_mode = WMI_MLO_LINK_NO_FORCE;
390 		break;
391 	default:
392 		wmi_err("Invalid force mode: %d", host_mode);
393 		return QDF_STATUS_E_INVAL;
394 	}
395 
396 	return QDF_STATUS_SUCCESS;
397 }
398 
399 /**
400  * force_reason_host_to_fw() - translate force reason for MLO link set active
401  *  command
402  * @host_reason: force reason defined by host
403  * @fw_reason: buffer to store force reason defined by FW
404  *
405  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL otherwise
406  */
407 static inline QDF_STATUS
408 force_reason_host_to_fw(enum mlo_link_force_reason host_reason,
409 			WMI_MLO_LINK_FORCE_REASON *fw_reason)
410 {
411 	switch (host_reason) {
412 	case MLO_LINK_FORCE_REASON_CONNECT:
413 		*fw_reason = WMI_MLO_LINK_FORCE_REASON_NEW_CONNECT;
414 		break;
415 	case MLO_LINK_FORCE_REASON_DISCONNECT:
416 		*fw_reason =  WMI_MLO_LINK_FORCE_REASON_NEW_DISCONNECT;
417 		break;
418 	case MLO_LINK_FORCE_REASON_LINK_REMOVAL:
419 		*fw_reason =  WMI_MLO_LINK_FORCE_REASON_LINK_REMOVAL;
420 		break;
421 	default:
422 		wmi_err("Invalid force reason: %d", host_reason);
423 		return QDF_STATUS_E_INVAL;
424 	}
425 
426 	return QDF_STATUS_SUCCESS;
427 }
428 
429 /**
430  * send_mlo_link_set_active_cmd_tlv() - send mlo link set active command
431  * @wmi_handle: wmi handle
432  * @param: Pointer to mlo link set active param
433  *
434  * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error
435  */
436 static QDF_STATUS
437 send_mlo_link_set_active_cmd_tlv(wmi_unified_t wmi_handle,
438 				 struct mlo_link_set_active_param *param)
439 {
440 	QDF_STATUS status;
441 	wmi_mlo_link_set_active_cmd_fixed_param *cmd;
442 	wmi_mlo_set_active_link_number_param *link_num_param;
443 	uint32_t *vdev_bitmap;
444 	uint32_t num_link_num_param = 0, num_vdev_bitmap = 0, tlv_len;
445 	uint32_t num_inactive_vdev_bitmap = 0;
446 	wmi_buf_t buf;
447 	uint8_t *buf_ptr;
448 	uint32_t len;
449 	int i;
450 	WMITLV_TAG_ID tag_id;
451 	WMI_MLO_LINK_FORCE_MODE force_mode;
452 	WMI_MLO_LINK_FORCE_REASON force_reason;
453 
454 	if (!param->num_vdev_bitmap && !param->num_link_entry) {
455 		wmi_err("No entry is provided vdev bit map %d link entry %d",
456 			param->num_vdev_bitmap,
457 			param->num_link_entry);
458 		return QDF_STATUS_E_INVAL;
459 	}
460 
461 	status = force_mode_host_to_fw(param->force_mode, &force_mode);
462 	if (QDF_IS_STATUS_ERROR(status))
463 		return QDF_STATUS_E_INVAL;
464 
465 	status = force_reason_host_to_fw(param->reason, &force_reason);
466 	if (QDF_IS_STATUS_ERROR(status))
467 		return QDF_STATUS_E_INVAL;
468 
469 	switch (force_mode) {
470 	case WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM:
471 	case WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM:
472 		num_link_num_param = param->num_link_entry;
473 		fallthrough;
474 	case WMI_MLO_LINK_FORCE_ACTIVE:
475 	case WMI_MLO_LINK_FORCE_INACTIVE:
476 	case WMI_MLO_LINK_NO_FORCE:
477 		num_vdev_bitmap = param->num_vdev_bitmap;
478 		break;
479 	case WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE:
480 		num_vdev_bitmap = param->num_vdev_bitmap;
481 		num_inactive_vdev_bitmap = param->num_inactive_vdev_bitmap;
482 		break;
483 	default:
484 		wmi_err("Invalid force reason: %d", force_mode);
485 		return QDF_STATUS_E_INVAL;
486 	}
487 
488 	len = sizeof(*cmd) +
489 	      WMI_TLV_HDR_SIZE + sizeof(*link_num_param) * num_link_num_param +
490 	      WMI_TLV_HDR_SIZE + sizeof(*vdev_bitmap) * num_vdev_bitmap;
491 	if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE)
492 		len += WMI_TLV_HDR_SIZE +
493 		sizeof(*vdev_bitmap) * num_inactive_vdev_bitmap;
494 
495 	buf = wmi_buf_alloc(wmi_handle, len);
496 	if (!buf)
497 		return QDF_STATUS_E_NOMEM;
498 
499 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
500 	cmd = (wmi_mlo_link_set_active_cmd_fixed_param *)buf_ptr;
501 	tlv_len = WMITLV_GET_STRUCT_TLVLEN
502 			(wmi_mlo_link_set_active_cmd_fixed_param);
503 
504 	tag_id = WMITLV_TAG_STRUC_wmi_mlo_link_set_active_cmd_fixed_param;
505 	WMITLV_SET_HDR(&cmd->tlv_header, tag_id, tlv_len);
506 	cmd->force_mode = force_mode;
507 	cmd->reason = force_reason;
508 	wmi_debug("mode %d reason %d num_link_num_param %d num_vdev_bitmap %d inactive %d",
509 		  cmd->force_mode, cmd->reason, num_link_num_param,
510 		  num_vdev_bitmap, num_inactive_vdev_bitmap);
511 	buf_ptr += sizeof(*cmd);
512 
513 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
514 		       sizeof(*link_num_param) * num_link_num_param);
515 	buf_ptr += WMI_TLV_HDR_SIZE;
516 
517 	if (num_link_num_param) {
518 		link_num_param =
519 			(wmi_mlo_set_active_link_number_param *)buf_ptr;
520 		tlv_len = WMITLV_GET_STRUCT_TLVLEN
521 				(wmi_mlo_set_active_link_number_param);
522 		for (i = 0; i < num_link_num_param; i++) {
523 			WMITLV_SET_HDR(&link_num_param->tlv_header, 0, tlv_len);
524 			link_num_param->num_of_link =
525 				param->link_num[i].num_of_link;
526 			link_num_param->vdev_type =
527 				param->link_num[i].vdev_type;
528 			link_num_param->vdev_subtype =
529 				param->link_num[i].vdev_subtype;
530 			link_num_param->home_freq =
531 				param->link_num[i].home_freq;
532 			wmi_debug("entry[%d]: num_of_link %d vdev type %d subtype %d freq %d",
533 				  i, link_num_param->num_of_link,
534 				  link_num_param->vdev_type,
535 				  link_num_param->vdev_subtype,
536 				  link_num_param->home_freq);
537 			link_num_param++;
538 		}
539 
540 		buf_ptr += sizeof(*link_num_param) * num_link_num_param;
541 	}
542 
543 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
544 		       sizeof(*vdev_bitmap) * num_vdev_bitmap);
545 	buf_ptr += WMI_TLV_HDR_SIZE;
546 
547 	if (num_vdev_bitmap) {
548 		vdev_bitmap = (A_UINT32 *)(buf_ptr);
549 		for (i = 0; i < num_vdev_bitmap; i++) {
550 			vdev_bitmap[i] = param->vdev_bitmap[i];
551 			wmi_debug("entry[%d]: vdev_id_bitmap 0x%x ",
552 				  i, vdev_bitmap[i]);
553 		}
554 
555 		buf_ptr += sizeof(*vdev_bitmap) * num_vdev_bitmap;
556 	}
557 	if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE) {
558 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
559 			       sizeof(*vdev_bitmap) *
560 			       num_inactive_vdev_bitmap);
561 		buf_ptr += WMI_TLV_HDR_SIZE;
562 
563 		if (num_inactive_vdev_bitmap) {
564 			vdev_bitmap = (A_UINT32 *)(buf_ptr);
565 			for (i = 0; i < num_inactive_vdev_bitmap; i++) {
566 				vdev_bitmap[i] =
567 					param->inactive_vdev_bitmap[i];
568 				wmi_debug("entry[%d]: inactive_vdev_id_bitmap 0x%x ",
569 					  i, vdev_bitmap[i]);
570 			}
571 
572 			buf_ptr += sizeof(*vdev_bitmap) *
573 				num_inactive_vdev_bitmap;
574 		}
575 	}
576 
577 	wmi_mtrace(WMI_MLO_LINK_SET_ACTIVE_CMDID, 0, cmd->force_mode);
578 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
579 				      WMI_MLO_LINK_SET_ACTIVE_CMDID);
580 	if (QDF_IS_STATUS_ERROR(status)) {
581 		wmi_err("Failed to send MLO link set active command to FW: %d",
582 			status);
583 		wmi_buf_free(buf);
584 	}
585 
586 	return status;
587 }
588 
589 /**
590  * extract_mlo_link_set_active_resp_tlv() - extract mlo link set active resp
591  *  from event
592  * @wmi_handle: wmi handle
593  * @evt_buf: pointer to event buffer
594  * @resp: Pointer to hold mlo link set active resp
595  *
596  * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error
597  */
598 static QDF_STATUS
599 extract_mlo_link_set_active_resp_tlv(wmi_unified_t wmi_handle, void *evt_buf,
600 				     struct mlo_link_set_active_resp *resp)
601 {
602 	wmi_mlo_link_set_active_resp_event_fixed_param *evt;
603 	WMI_MLO_LINK_SET_ACTIVE_RESP_EVENTID_param_tlvs *param_buf;
604 	uint32_t entry_num, *bitmap;
605 	int i;
606 
607 	param_buf = evt_buf;
608 	if (!param_buf || !resp) {
609 		wmi_err("Invalid param");
610 		return QDF_STATUS_E_INVAL;
611 	}
612 
613 	evt = param_buf->fixed_param;
614 	resp->status = evt->status;
615 	wmi_debug("status: %u", resp->status);
616 
617 	bitmap = param_buf->force_active_vdev_bitmap;
618 	entry_num = qdf_min(param_buf->num_force_active_vdev_bitmap,
619 			    (uint32_t)MLO_VDEV_BITMAP_SZ);
620 	resp->active_sz = entry_num;
621 	for (i = 0; i < entry_num; i++) {
622 		resp->active[i] = bitmap[i];
623 		wmi_debug("active[%d]: 0x%x", i, resp->active[i]);
624 	}
625 
626 	bitmap = param_buf->force_inactive_vdev_bitmap;
627 	entry_num = qdf_min(param_buf->num_force_inactive_vdev_bitmap,
628 			    (uint32_t)MLO_VDEV_BITMAP_SZ);
629 	resp->inactive_sz = entry_num;
630 	for (i = 0; i < entry_num; i++) {
631 		resp->inactive[i] = bitmap[i];
632 		wmi_debug("inactive[%d]: 0x%x", i, resp->inactive[i]);
633 	}
634 
635 	return QDF_STATUS_SUCCESS;
636 }
637 
638 /**
639  * send_mlo_link_removal_cmd_tlv() - Send WMI command for MLO link removal
640  * @wmi_handle: wmi handle
641  * @params: MLO link removal command parameters
642  *
643  * Return: QDF_STATUS_SUCCESS of operation
644  */
645 static QDF_STATUS send_mlo_link_removal_cmd_tlv(
646 	wmi_unified_t wmi_handle,
647 	const struct mlo_link_removal_cmd_params *params)
648 {
649 	wmi_mlo_link_removal_cmd_fixed_param *fixed_params;
650 	wmi_buf_t buf;
651 	uint8_t *buf_ptr;
652 	uint32_t buf_len = 0;
653 	uint32_t ie_len_aligned = 0;
654 	QDF_STATUS ret;
655 
656 	if (!params) {
657 		wmi_err("command params is NULL");
658 		return QDF_STATUS_E_NULL_VALUE;
659 	}
660 
661 	ie_len_aligned = roundup(params->reconfig_ml_ie_size, sizeof(uint32_t));
662 
663 	buf_len = sizeof(wmi_mlo_link_removal_cmd_fixed_param) +
664 		  WMI_TLV_HDR_SIZE + ie_len_aligned;
665 
666 	buf = wmi_buf_alloc(wmi_handle, buf_len);
667 	if (!buf) {
668 		wmi_err("wmi buf alloc failed for link removal cmd: psoc (%pK) vdev(%u)",
669 			wmi_handle->soc->wmi_psoc, params->vdev_id);
670 		return QDF_STATUS_E_NOMEM;
671 	}
672 
673 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
674 
675 	/* Populate fixed params TLV */
676 	fixed_params = (wmi_mlo_link_removal_cmd_fixed_param *)buf_ptr;
677 	WMITLV_SET_HDR(&fixed_params->tlv_header,
678 		       WMITLV_TAG_STRUC_wmi_mlo_link_removal_cmd_fixed_param,
679 		       WMITLV_GET_STRUCT_TLVLEN(
680 			   wmi_mlo_link_removal_cmd_fixed_param));
681 	fixed_params->vdev_id = params->vdev_id;
682 	fixed_params->reconfig_ml_ie_num_bytes_valid =
683 		params->reconfig_ml_ie_size;
684 	buf_ptr += sizeof(*fixed_params);
685 
686 	/* Populate the array of bytes TLV */
687 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned);
688 	buf_ptr += WMI_TLV_HDR_SIZE;
689 
690 	/* Populate ML reconfiguration element in raw bytes */
691 	qdf_mem_copy(buf_ptr, params->reconfig_ml_ie,
692 		     params->reconfig_ml_ie_size);
693 
694 	wmi_mtrace(WMI_MLO_LINK_REMOVAL_CMDID, fixed_params->vdev_id, 0);
695 	ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len,
696 				   WMI_MLO_LINK_REMOVAL_CMDID);
697 	if (QDF_IS_STATUS_ERROR(ret)) {
698 		wmi_err("Failed to send MLO link removal cmd: psoc (%pK) vdev(%u)",
699 			wmi_handle->soc->wmi_psoc, params->vdev_id);
700 		wmi_buf_free(buf);
701 	}
702 
703 	return ret;
704 }
705 
706 /**
707  * extract_mlo_link_removal_evt_fixed_param_tlv() - Extract fixed parameters TLV
708  * from the MLO link removal WMI  event
709  * @wmi_handle: wmi handle
710  * @buf: pointer to event buffer
711  * @params: MLO link removal event parameters
712  *
713  * Return: QDF_STATUS of operation
714  */
715 static QDF_STATUS
716 extract_mlo_link_removal_evt_fixed_param_tlv(
717 	struct wmi_unified *wmi_handle,
718 	void *buf,
719 	struct mlo_link_removal_evt_params *params)
720 {
721 	WMI_MLO_LINK_REMOVAL_EVENTID_param_tlvs *param_buf = buf;
722 	wmi_mlo_link_removal_evt_fixed_param *ev;
723 
724 	if (!param_buf) {
725 		wmi_err_rl("Param_buf is NULL");
726 		return QDF_STATUS_E_NULL_VALUE;
727 	}
728 
729 	if (!params) {
730 		wmi_err_rl("params is NULL");
731 		return QDF_STATUS_E_NULL_VALUE;
732 	}
733 
734 	ev = param_buf->fixed_param;
735 	params->vdev_id = ev->vdev_id;
736 
737 	return QDF_STATUS_SUCCESS;
738 }
739 
740 /**
741  * extract_mlo_link_removal_tbtt_update_tlv() - Extract TBTT update TLV
742  * from the MLO link removal WMI  event
743  * @wmi_handle: wmi handle
744  * @buf: pointer to event buffer
745  * @tbtt_info: TBTT information to be populated
746  *
747  * Return: QDF_STATUS of operation
748  */
749 static QDF_STATUS
750 extract_mlo_link_removal_tbtt_update_tlv(
751 	struct wmi_unified *wmi_handle,
752 	void *buf,
753 	struct mlo_link_removal_tbtt_info *tbtt_info)
754 {
755 	WMI_MLO_LINK_REMOVAL_EVENTID_param_tlvs *param_buf = buf;
756 	wmi_mlo_link_removal_tbtt_update *tlv;
757 
758 	if (!param_buf) {
759 		wmi_err_rl("Param_buf is NULL");
760 		return QDF_STATUS_E_NULL_VALUE;
761 	}
762 
763 	if (!tbtt_info) {
764 		wmi_err_rl("Writable argument is NULL");
765 		return QDF_STATUS_E_NULL_VALUE;
766 	}
767 
768 	tlv = param_buf->tbtt_update;
769 
770 	tbtt_info->tbtt_count = tlv->tbtt_count;
771 	tbtt_info->tsf = ((uint64_t)tlv->tsf_high << 32) | tlv->tsf_low;
772 	tbtt_info->qtimer_reading =
773 		((uint64_t)tlv->qtimer_ts_high << 32) | tlv->qtimer_ts_low;
774 
775 	return QDF_STATUS_SUCCESS;
776 }
777 
778 /**
779  * extract_mgmt_rx_mlo_link_removal_info_tlv() - Extract MLO link removal info
780  * from MGMT Rx event
781  * @wmi_handle: wmi handle
782  * @buf: event buffer
783  * @link_removal_info: link removal information array to be populated
784  * @num_link_removal_info: Number of elements in @link_removal_info
785  *
786  * Return: QDF_STATUS of operation
787  */
788 static QDF_STATUS
789 extract_mgmt_rx_mlo_link_removal_info_tlv(
790 	struct wmi_unified *wmi_handle,
791 	void *buf,
792 	struct mgmt_rx_mlo_link_removal_info *link_removal_info,
793 	int num_link_removal_info)
794 {
795 	WMI_MGMT_RX_EVENTID_param_tlvs *param_buf = buf;
796 	wmi_mlo_link_removal_tbtt_count *tlv_arr;
797 	int tlv_idx = 0;
798 	struct mgmt_rx_mlo_link_removal_info *info;
799 
800 	if (!param_buf) {
801 		wmi_err_rl("Param_buf is NULL");
802 		return QDF_STATUS_E_NULL_VALUE;
803 	}
804 
805 	if (!link_removal_info) {
806 		wmi_err_rl("Writable argument is NULL");
807 		return QDF_STATUS_E_NULL_VALUE;
808 	}
809 
810 	if (num_link_removal_info != param_buf->num_link_removal_tbtt_count) {
811 		wmi_err_rl("link_removal_info array size (%d) is not equal to"
812 			   "number of corresponding TLVs(%d) present in event",
813 			   num_link_removal_info,
814 			   param_buf->num_link_removal_tbtt_count);
815 		return QDF_STATUS_E_RANGE;
816 	}
817 
818 	tlv_arr = param_buf->link_removal_tbtt_count;
819 	for (; tlv_idx < param_buf->num_link_removal_tbtt_count; tlv_idx++) {
820 		info = &link_removal_info[tlv_idx];
821 
822 		info->hw_link_id = WMI_MLO_LINK_REMOVAL_GET_LINKID(
823 					tlv_arr[tlv_idx].tbtt_info);
824 		info->vdev_id = WMI_MLO_LINK_REMOVAL_GET_VDEVID(
825 					tlv_arr[tlv_idx].tbtt_info);
826 		info->tbtt_count = WMI_MLO_LINK_REMOVAL_GET_TBTT_COUNT(
827 					tlv_arr[tlv_idx].tbtt_info);
828 	}
829 
830 	return QDF_STATUS_SUCCESS;
831 }
832 
833 #ifdef WLAN_FEATURE_11BE
834 size_t peer_assoc_t2lm_params_size(struct peer_assoc_params *req)
835 {
836 	size_t peer_assoc_t2lm_size = WMI_TLV_HDR_SIZE +
837 		(req->t2lm_params.num_dir * T2LM_MAX_NUM_TIDS *
838 		 (sizeof(wmi_peer_assoc_tid_to_link_map)));
839 
840 	return peer_assoc_t2lm_size;
841 }
842 
843 static void peer_assoc_populate_t2lm_tlv(wmi_peer_assoc_tid_to_link_map *cmd,
844 				  struct wlan_host_t2lm_of_tids *t2lm,
845 				  uint8_t tid_num)
846 {
847 	WMITLV_SET_HDR(&cmd->tlv_header,
848 		       WMITLV_TAG_STRUC_wmi_peer_assoc_tid_to_link_map,
849 		       WMITLV_GET_STRUCT_TLVLEN(
850 				   wmi_peer_assoc_tid_to_link_map));
851 
852 	/* Populate TID number */
853 	WMI_TID_TO_LINK_MAP_TID_NUM_SET(cmd->tid_to_link_map_info, tid_num);
854 
855 	/* Populate the direction */
856 	WMI_TID_TO_LINK_MAP_DIR_SET(cmd->tid_to_link_map_info,
857 				    t2lm->direction);
858 
859 	/* Populate the default link mapping value */
860 	WMI_TID_TO_LINK_MAP_DEFAULT_MAPPING_SET(
861 			cmd->tid_to_link_map_info,
862 			t2lm->default_link_mapping);
863 
864 	/* Populate the T2LM provisioned links for the corresponding TID
865 	 * number.
866 	 */
867 	WMI_TID_TO_LINK_MAP_LINK_MASK_SET(
868 			cmd->tid_to_link_map_info,
869 			t2lm->t2lm_provisioned_links[tid_num]);
870 
871 	wmi_debug("Add T2LM TLV: tid_to_link_map_info:%x",
872 		  cmd->tid_to_link_map_info);
873 }
874 
875 uint8_t *peer_assoc_add_tid_to_link_map(uint8_t *buf_ptr,
876 					struct peer_assoc_params *req)
877 {
878 	struct wmi_host_tid_to_link_map_params *t2lm_params = &req->t2lm_params;
879 	wmi_peer_assoc_tid_to_link_map *cmd;
880 	uint8_t dir = 0;
881 	uint8_t tid_num = 0;
882 
883 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
884 		       (req->t2lm_params.num_dir * T2LM_MAX_NUM_TIDS *
885 		       sizeof(wmi_peer_assoc_tid_to_link_map)));
886 	buf_ptr += sizeof(uint32_t);
887 
888 	for (dir = 0; dir < t2lm_params->num_dir; dir++) {
889 		wmi_debug("Add T2LM TLV for peer: " QDF_MAC_ADDR_FMT " direction:%d",
890 				QDF_MAC_ADDR_REF(t2lm_params->peer_macaddr),
891 				t2lm_params->t2lm_info[dir].direction);
892 		for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
893 			cmd = (wmi_peer_assoc_tid_to_link_map *)buf_ptr;
894 			peer_assoc_populate_t2lm_tlv(
895 					cmd, &t2lm_params->t2lm_info[dir],
896 					tid_num);
897 			buf_ptr += sizeof(wmi_peer_assoc_tid_to_link_map);
898 		}
899 	}
900 
901 	return buf_ptr;
902 }
903 
904 static QDF_STATUS send_mlo_peer_tid_to_link_map_cmd_tlv(
905 		wmi_unified_t wmi_handle,
906 		struct wmi_host_tid_to_link_map_params *params)
907 {
908 	wmi_peer_tid_to_link_map_fixed_param *cmd;
909 	wmi_tid_to_link_map *t2lm;
910 	wmi_buf_t buf;
911 	uint8_t *buf_ptr;
912 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
913 	uint32_t buf_len = 0;
914 	uint8_t dir = 0;
915 	uint8_t tid_num = 0;
916 
917 	buf_len = sizeof(wmi_peer_tid_to_link_map_fixed_param) +
918 		WMI_TLV_HDR_SIZE + (params->num_dir * T2LM_MAX_NUM_TIDS *
919 		 sizeof(wmi_tid_to_link_map));
920 
921 	buf = wmi_buf_alloc(wmi_handle, buf_len);
922 	if (!buf) {
923 		wmi_err("wmi buf alloc failed for mlo_peer_mac: "
924 				QDF_MAC_ADDR_FMT,
925 				QDF_MAC_ADDR_REF(params->peer_macaddr));
926 		return QDF_STATUS_E_NOMEM;
927 	}
928 
929 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
930 	cmd = (wmi_peer_tid_to_link_map_fixed_param *)buf_ptr;
931 
932 	WMITLV_SET_HDR(&cmd->tlv_header,
933 		       WMITLV_TAG_STRUC_wmi_peer_tid_to_link_map_fixed_param,
934 		       WMITLV_GET_STRUCT_TLVLEN(
935 			   wmi_peer_tid_to_link_map_fixed_param));
936 
937 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
938 			wmi_handle, params->pdev_id);
939 
940 	WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->link_macaddr);
941 
942 	buf_ptr += sizeof(wmi_peer_tid_to_link_map_fixed_param);
943 
944 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
945 		       (params->num_dir * T2LM_MAX_NUM_TIDS *
946 		       sizeof(wmi_tid_to_link_map)));
947 	buf_ptr += sizeof(uint32_t);
948 
949 	for (dir = 0; dir < params->num_dir; dir++) {
950 		wmi_debug("Add T2LM TLV for peer: " QDF_MAC_ADDR_FMT " direction:%d",
951 				QDF_MAC_ADDR_REF(params->peer_macaddr),
952 				params->t2lm_info[dir].direction);
953 
954 		for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
955 			t2lm = (wmi_tid_to_link_map *)buf_ptr;
956 
957 			WMITLV_SET_HDR(&t2lm->tlv_header,
958 				       WMITLV_TAG_STRUC_wmi_tid_to_link_map,
959 				       WMITLV_GET_STRUCT_TLVLEN(
960 					   wmi_tid_to_link_map));
961 
962 			/* Populate TID number */
963 			WMI_TID_TO_LINK_MAP_TID_NUM_SET(
964 					t2lm->tid_to_link_map_info, tid_num);
965 
966 			/* Populate the direction */
967 			WMI_TID_TO_LINK_MAP_DIR_SET(
968 					t2lm->tid_to_link_map_info,
969 					params->t2lm_info[dir].direction);
970 
971 			/* Populate the default link mapping value */
972 			WMI_TID_TO_LINK_MAP_DEFAULT_MAPPING_SET(
973 					t2lm->tid_to_link_map_info,
974 					params->t2lm_info[dir].default_link_mapping);
975 
976 			/* Populate the T2LM provisioned links for the
977 			 * corresponding TID number.
978 			 */
979 			WMI_TID_TO_LINK_MAP_LINK_MASK_SET(
980 					t2lm->tid_to_link_map_info,
981 					params->t2lm_info[dir].t2lm_provisioned_links[tid_num]);
982 
983 			buf_ptr += sizeof(wmi_tid_to_link_map);
984 
985 			wmi_debug("Add T2LM TLV: tid_to_link_map_info:%x",
986 				  t2lm->tid_to_link_map_info);
987 		}
988 	}
989 
990 	wmi_mtrace(WMI_MLO_PEER_TID_TO_LINK_MAP_CMDID, cmd->pdev_id, 0);
991 	ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len,
992 				   WMI_MLO_PEER_TID_TO_LINK_MAP_CMDID);
993 	if (ret) {
994 		wmi_err("Failed to send T2LM command to FW: %d mlo_peer_mac: " QDF_MAC_ADDR_FMT,
995 				ret, QDF_MAC_ADDR_REF(params->peer_macaddr));
996 		wmi_buf_free(buf);
997 	}
998 
999 	return ret;
1000 }
1001 
1002 static void update_t2lm_ie_info_params(
1003 		wmi_mlo_ap_vdev_tid_to_link_map_ie_info * info,
1004 		struct wlan_t2lm_info *params)
1005 {
1006 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_DIR_SET(
1007 			info->tid_to_link_map_ctrl,
1008 			params->direction);
1009 
1010 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_DEF_LINK_SET(
1011 			info->tid_to_link_map_ctrl,
1012 			params->default_link_mapping);
1013 
1014 	info->map_switch_time = params->mapping_switch_time;
1015 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_SWT_TIME_SET(
1016 			info->tid_to_link_map_ctrl,
1017 			params->mapping_switch_time_present);
1018 
1019 	info->expected_duration = params->expected_duration;
1020 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_DUR_TIME_SET(
1021 			info->tid_to_link_map_ctrl,
1022 			params->expected_duration_present);
1023 
1024 	wmi_debug("tid_to_link_map_ctrl:%x map_switch_time:%d expected_duration:%d",
1025 		  info->tid_to_link_map_ctrl, info->map_switch_time,
1026 		  info->expected_duration);
1027 
1028 	/* Do not fill link mapping values when default mapping is set to 1 */
1029 	if (params->default_link_mapping)
1030 		return;
1031 
1032 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_LINK_MAP_PRE_SET(
1033 			info->tid_to_link_map_ctrl, 0xff);
1034 
1035 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_0_SET(
1036 			info->ieee_tid_0_1_link_map,
1037 			params->ieee_link_map_tid[0]);
1038 
1039 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_1_SET(
1040 			info->ieee_tid_0_1_link_map,
1041 			params->ieee_link_map_tid[1]);
1042 
1043 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_2_SET(
1044 			info->ieee_tid_2_3_link_map,
1045 			params->ieee_link_map_tid[2]);
1046 
1047 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_3_SET(
1048 			info->ieee_tid_2_3_link_map,
1049 			params->ieee_link_map_tid[3]);
1050 
1051 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_4_SET(
1052 			info->ieee_tid_4_5_link_map,
1053 			params->ieee_link_map_tid[4]);
1054 
1055 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_5_SET(
1056 			info->ieee_tid_4_5_link_map,
1057 			params->ieee_link_map_tid[5]);
1058 
1059 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_6_SET(
1060 			info->ieee_tid_6_7_link_map,
1061 			params->ieee_link_map_tid[6]);
1062 
1063 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_7_SET(
1064 			info->ieee_tid_6_7_link_map,
1065 			params->ieee_link_map_tid[7]);
1066 
1067 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_0_SET(
1068 			info->hw_tid_0_1_link_map,
1069 			params->hw_link_map_tid[0]);
1070 
1071 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_1_SET(
1072 			info->hw_tid_0_1_link_map,
1073 			params->hw_link_map_tid[1]);
1074 
1075 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_2_SET(
1076 			info->hw_tid_2_3_link_map,
1077 			params->hw_link_map_tid[2]);
1078 
1079 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_3_SET(
1080 			info->hw_tid_2_3_link_map,
1081 			params->hw_link_map_tid[3]);
1082 
1083 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_4_SET(
1084 			info->hw_tid_4_5_link_map,
1085 			params->hw_link_map_tid[4]);
1086 
1087 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_5_SET(
1088 			info->hw_tid_4_5_link_map,
1089 			params->hw_link_map_tid[5]);
1090 
1091 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_6_SET(
1092 			info->hw_tid_6_7_link_map,
1093 			params->hw_link_map_tid[6]);
1094 
1095 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_7_SET(
1096 			info->hw_tid_6_7_link_map,
1097 			params->hw_link_map_tid[7]);
1098 
1099 	wmi_debug("tid_to_link_map_ctrl:%x", info->tid_to_link_map_ctrl);
1100 	wmi_debug("ieee_link_map: tid_0_1:%x tid_2_3:%x tid_4_5:%x tid_6_7:%x",
1101 		  info->ieee_tid_0_1_link_map, info->ieee_tid_2_3_link_map,
1102 		  info->ieee_tid_4_5_link_map, info->ieee_tid_6_7_link_map);
1103 	wmi_debug("hw_link_map: tid_0_1:%x tid_2_3:%x tid_4_5:%x tid_6_7:%x",
1104 		  info->hw_tid_0_1_link_map, info->hw_tid_2_3_link_map,
1105 		  info->hw_tid_4_5_link_map, info->hw_tid_6_7_link_map);
1106 }
1107 
1108 static QDF_STATUS send_mlo_vdev_tid_to_link_map_cmd_tlv(
1109 		wmi_unified_t wmi_handle,
1110 		struct wmi_host_tid_to_link_map_ap_params *params)
1111 {
1112 	wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param *cmd;
1113 	wmi_mlo_ap_vdev_tid_to_link_map_ie_info *info;
1114 	wmi_buf_t buf;
1115 	uint8_t *buf_ptr;
1116 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
1117 	uint32_t buf_len = 0;
1118 	uint32_t num_info = 0;
1119 
1120 	if (params->num_t2lm_info > WLAN_MAX_T2LM_IE) {
1121 		wmi_err("Failed to send T2LM command to FW for vdev id %d as t2lm info %d is greater than max %d",
1122 			params->vdev_id,
1123 			params->num_t2lm_info,
1124 			WLAN_MAX_T2LM_IE);
1125 		return QDF_STATUS_E_INVAL;
1126 	}
1127 
1128 	buf_len = sizeof(wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param) +
1129 		WMI_TLV_HDR_SIZE + (params->num_t2lm_info *
1130 		 sizeof(wmi_mlo_ap_vdev_tid_to_link_map_ie_info));
1131 
1132 	buf = wmi_buf_alloc(wmi_handle, buf_len);
1133 	if (!buf) {
1134 		wmi_err("wmi buf alloc failed for vdev id %d while t2lm map cmd send: ",
1135 			params->vdev_id);
1136 		return QDF_STATUS_E_NOMEM;
1137 	}
1138 
1139 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
1140 	cmd = (wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param *)buf_ptr;
1141 
1142 	WMITLV_SET_HDR(
1143 	       &cmd->tlv_header,
1144 	       WMITLV_TAG_STRUC_wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param,
1145 	       WMITLV_GET_STRUCT_TLVLEN(
1146 	       wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param));
1147 
1148 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1149 			wmi_handle, params->pdev_id);
1150 	cmd->vdev_id = params->vdev_id;
1151 	cmd->disabled_link_bitmap = params->disabled_link_bitmap;
1152 	wmi_debug("pdev_id:%d vdev_id:%d disabled_link_bitmap:%x num_t2lm_info:%d",
1153 		  cmd->pdev_id, cmd->vdev_id, cmd->disabled_link_bitmap,
1154 		  params->num_t2lm_info);
1155 
1156 	buf_ptr += sizeof(wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param);
1157 
1158 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1159 		       (params->num_t2lm_info *
1160 			sizeof(wmi_mlo_ap_vdev_tid_to_link_map_ie_info)));
1161 	buf_ptr += sizeof(uint32_t);
1162 
1163 	for (num_info = 0; num_info < params->num_t2lm_info; num_info++) {
1164 		info = (wmi_mlo_ap_vdev_tid_to_link_map_ie_info *)buf_ptr;
1165 
1166 		WMITLV_SET_HDR(
1167 		       &info->tlv_header,
1168 		       WMITLV_TAG_STRUC_wmi_mlo_ap_vdev_tid_to_link_map_ie_info,
1169 		       WMITLV_GET_STRUCT_TLVLEN(
1170 		       wmi_mlo_ap_vdev_tid_to_link_map_ie_info));
1171 		update_t2lm_ie_info_params(info, &params->info[num_info]);
1172 		buf_ptr += sizeof(wmi_mlo_ap_vdev_tid_to_link_map_ie_info);
1173 	}
1174 
1175 	wmi_mtrace(WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_CMDID, cmd->vdev_id, 0);
1176 	ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len,
1177 				   WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_CMDID);
1178 	if (ret) {
1179 		wmi_err("Failed to send T2LM command to FW: %d vdev id %d",
1180 			ret, cmd->vdev_id);
1181 		wmi_buf_free(buf);
1182 	}
1183 
1184 	return ret;
1185 }
1186 
1187 static QDF_STATUS
1188 extract_mlo_vdev_tid_to_link_map_event_tlv(
1189 		struct wmi_unified *wmi_handle,
1190 		uint8_t *buf,
1191 		struct mlo_vdev_host_tid_to_link_map_resp *params)
1192 {
1193 	WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_EVENTID_param_tlvs *param_buf;
1194 	wmi_mlo_ap_vdev_tid_to_link_map_evt_fixed_param *ev;
1195 
1196 	param_buf = (WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_EVENTID_param_tlvs *)buf;
1197 	if (!param_buf) {
1198 		wmi_err_rl("Param_buf is NULL");
1199 		return QDF_STATUS_E_FAILURE;
1200 	}
1201 
1202 	ev = (wmi_mlo_ap_vdev_tid_to_link_map_evt_fixed_param *)
1203 		param_buf->fixed_param;
1204 
1205 	params->vdev_id = ev->vdev_id;
1206 	params->status  = ev->status_type;
1207 	params->mapping_switch_tsf = ev->mapping_switch_tsf;
1208 
1209 	return QDF_STATUS_SUCCESS;
1210 }
1211 
1212 static QDF_STATUS
1213 extract_mlo_vdev_bcast_tid_to_link_map_event_tlv(
1214 				struct wmi_unified *wmi_handle,
1215 				void *buf,
1216 				struct mlo_bcast_t2lm_info *bcast_info)
1217 {
1218 	WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs;
1219 	wmi_mlo_bcast_t2lm_info *info;
1220 	int i;
1221 
1222 	param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *)buf;
1223 	if (!param_tlvs) {
1224 		wmi_err(" MGMT RX param_tlvs is NULL");
1225 		return QDF_STATUS_E_INVAL;
1226 	}
1227 
1228 	if (param_tlvs->num_mlo_bcast_t2lm_info > MAX_AP_MLDS_PER_LINK) {
1229 		wmi_err("num_mlo_bcast_t2lm_info is greater than %d",
1230 			MAX_AP_MLDS_PER_LINK);
1231 		return QDF_STATUS_E_INVAL;
1232 	}
1233 
1234 	info = param_tlvs->mlo_bcast_t2lm_info;
1235 	if (!info) {
1236 		wmi_debug("mlo_bcast_t2lm_info is not applicable");
1237 		return QDF_STATUS_SUCCESS;
1238 	}
1239 
1240 	bcast_info->num_vdevs = param_tlvs->num_mlo_bcast_t2lm_info;
1241 	wmi_debug("num_vdevs:%d", bcast_info->num_vdevs);
1242 	for (i = 0; i < param_tlvs->num_mlo_bcast_t2lm_info; i++) {
1243 		bcast_info->vdev_id[i] =
1244 			WMI_MLO_BROADCAST_TID_TO_LINK_MAP_INFO_VDEV_ID_GET(
1245 					info->vdev_id_expec_dur);
1246 
1247 		bcast_info->expected_duration[i] =
1248 			WMI_MLO_BROADCAST_TID_TO_LINK_MAP_INFO_EXP_DUR_GET(
1249 					info->vdev_id_expec_dur);
1250 		wmi_debug("vdev_id:%d expected_duration:%d",
1251 			  bcast_info->vdev_id[i],
1252 			  bcast_info->expected_duration[i]);
1253 	}
1254 
1255 	return QDF_STATUS_SUCCESS;
1256 }
1257 #else
1258 size_t peer_assoc_t2lm_params_size(struct peer_assoc_params *req)
1259 {
1260 	return WMI_TLV_HDR_SIZE;
1261 }
1262 
1263 uint8_t *peer_assoc_add_tid_to_link_map(uint8_t *buf_ptr,
1264 					       struct peer_assoc_params *req)
1265 {
1266 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1267 	return buf_ptr + WMI_TLV_HDR_SIZE;
1268 }
1269 #endif /* WLAN_FEATURE_11BE */
1270 
1271 #ifdef WLAN_MLO_MULTI_CHIP
1272 QDF_STATUS mlo_setup_cmd_send_tlv(struct wmi_unified *wmi_handle,
1273 				  struct wmi_mlo_setup_params *param)
1274 {
1275 	QDF_STATUS ret;
1276 	wmi_mlo_setup_cmd_fixed_param *cmd;
1277 	wmi_buf_t buf;
1278 	int32_t len;
1279 	uint8_t *buf_ptr;
1280 	uint32_t *partner_links;
1281 	uint8_t idx;
1282 
1283 	if (param->num_valid_hw_links > MAX_LINK_IN_MLO)
1284 		return QDF_STATUS_E_INVAL;
1285 
1286 	len = sizeof(*cmd) +
1287 		(param->num_valid_hw_links * sizeof(uint32_t)) +
1288 		WMI_TLV_HDR_SIZE;
1289 
1290 	buf = wmi_buf_alloc(wmi_handle, len);
1291 	if (!buf)
1292 		return QDF_STATUS_E_NOMEM;
1293 
1294 	cmd = (wmi_mlo_setup_cmd_fixed_param *)wmi_buf_data(buf);
1295 	WMITLV_SET_HDR(&cmd->tlv_header,
1296 		       WMITLV_TAG_STRUC_wmi_mlo_setup_cmd_fixed_param,
1297 		       WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_setup_cmd_fixed_param));
1298 
1299 	cmd->mld_group_id = param->mld_grp_id;
1300 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1301 								wmi_handle,
1302 								param->pdev_id);
1303 	buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
1304 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1305 		       (sizeof(uint32_t) * param->num_valid_hw_links));
1306 	partner_links = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
1307 	for (idx = 0; idx < param->num_valid_hw_links; idx++)
1308 		partner_links[idx] = param->partner_links[idx];
1309 
1310 	wmi_mtrace(WMI_MLO_SETUP_CMDID, NO_SESSION, 0);
1311 	ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_MLO_SETUP_CMDID);
1312 	if (QDF_IS_STATUS_ERROR(ret)) {
1313 		wmi_err("Failed to send MLO setup command ret = %d", ret);
1314 		wmi_buf_free(buf);
1315 	}
1316 
1317 	return ret;
1318 }
1319 
1320 QDF_STATUS mlo_ready_cmd_send_tlv(struct wmi_unified *wmi_handle,
1321 				  struct wmi_mlo_ready_params *param)
1322 {
1323 	QDF_STATUS ret;
1324 	wmi_mlo_ready_cmd_fixed_param *cmd;
1325 	wmi_buf_t buf;
1326 	int32_t len;
1327 
1328 	len = sizeof(*cmd);
1329 
1330 	buf = wmi_buf_alloc(wmi_handle, len);
1331 	if (!buf)
1332 		return QDF_STATUS_E_NOMEM;
1333 
1334 	cmd = (wmi_mlo_ready_cmd_fixed_param *)wmi_buf_data(buf);
1335 	WMITLV_SET_HDR(&cmd->tlv_header,
1336 		       WMITLV_TAG_STRUC_wmi_mlo_ready_cmd_fixed_param,
1337 		       WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_ready_cmd_fixed_param));
1338 
1339 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1340 								wmi_handle,
1341 								param->pdev_id);
1342 
1343 	wmi_mtrace(WMI_MLO_READY_CMDID, NO_SESSION, 0);
1344 	ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_MLO_READY_CMDID);
1345 	if (QDF_IS_STATUS_ERROR(ret)) {
1346 		wmi_err("Failed to send MLO ready command ret = %d", ret);
1347 		wmi_buf_free(buf);
1348 	}
1349 
1350 	return ret;
1351 }
1352 
1353 QDF_STATUS mlo_teardown_cmd_send_tlv(struct wmi_unified *wmi_handle,
1354 				     struct wmi_mlo_teardown_params *param)
1355 {
1356 	QDF_STATUS ret;
1357 	wmi_mlo_teardown_fixed_param *cmd;
1358 	wmi_buf_t buf;
1359 	int32_t len;
1360 
1361 	len = sizeof(*cmd);
1362 
1363 	buf = wmi_buf_alloc(wmi_handle, len);
1364 	if (!buf)
1365 		return QDF_STATUS_E_NOMEM;
1366 
1367 	cmd = (wmi_mlo_teardown_fixed_param *)wmi_buf_data(buf);
1368 	WMITLV_SET_HDR(&cmd->tlv_header,
1369 		       WMITLV_TAG_STRUC_wmi_mlo_teardown_fixed_param,
1370 		       WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_teardown_fixed_param));
1371 
1372 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1373 								wmi_handle,
1374 								param->pdev_id);
1375 	switch (param->reason) {
1376 	case WMI_MLO_TEARDOWN_REASON_SSR:
1377 		cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON;
1378 		break;
1379 	case WMI_MLO_TEARDOWN_REASON_DOWN:
1380 	default:
1381 		cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON + 1;
1382 		break;
1383 	}
1384 
1385 	wmi_mtrace(WMI_MLO_TEARDOWN_CMDID, NO_SESSION, 0);
1386 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1387 				   WMI_MLO_TEARDOWN_CMDID);
1388 	if (QDF_IS_STATUS_ERROR(ret)) {
1389 		wmi_err("Failed to send MLO Teardown command ret = %d", ret);
1390 		wmi_buf_free(buf);
1391 	}
1392 
1393 	return ret;
1394 }
1395 
1396 QDF_STATUS
1397 extract_mlo_setup_cmpl_event_tlv(struct wmi_unified *wmi_handle,
1398 				 uint8_t *buf,
1399 				 struct wmi_mlo_setup_complete_params *params)
1400 {
1401 	WMI_MLO_SETUP_COMPLETE_EVENTID_param_tlvs *param_buf;
1402 	wmi_mlo_setup_complete_event_fixed_param *ev;
1403 
1404 	param_buf = (WMI_MLO_SETUP_COMPLETE_EVENTID_param_tlvs *)buf;
1405 	if (!param_buf) {
1406 		wmi_err_rl("Param_buf is NULL");
1407 		return QDF_STATUS_E_FAILURE;
1408 	}
1409 	ev = (wmi_mlo_setup_complete_event_fixed_param *)param_buf->fixed_param;
1410 
1411 	params->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
1412 								wmi_handle,
1413 								ev->pdev_id);
1414 	if (!ev->status)
1415 		params->status = WMI_MLO_SETUP_STATUS_SUCCESS;
1416 	else
1417 		params->status = WMI_MLO_SETUP_STATUS_FAILURE;
1418 
1419 	return QDF_STATUS_SUCCESS;
1420 }
1421 
1422 QDF_STATUS
1423 extract_mlo_teardown_cmpl_event_tlv(struct wmi_unified *wmi_handle,
1424 				    uint8_t *buf,
1425 				    struct wmi_mlo_teardown_cmpl_params *params)
1426 {
1427 	WMI_MLO_TEARDOWN_COMPLETE_EVENTID_param_tlvs *param_buf;
1428 	wmi_mlo_teardown_complete_fixed_param *ev;
1429 
1430 	param_buf = (WMI_MLO_TEARDOWN_COMPLETE_EVENTID_param_tlvs *)buf;
1431 	if (!param_buf) {
1432 		wmi_err_rl("Param_buf is NULL");
1433 		return QDF_STATUS_E_FAILURE;
1434 	}
1435 	ev = (wmi_mlo_teardown_complete_fixed_param *)param_buf->fixed_param;
1436 
1437 	params->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
1438 								wmi_handle,
1439 								ev->pdev_id);
1440 	if (!ev->status)
1441 		params->status = WMI_MLO_TEARDOWN_STATUS_SUCCESS;
1442 	else
1443 		params->status = WMI_MLO_TEARDOWN_STATUS_FAILURE;
1444 
1445 	return QDF_STATUS_SUCCESS;
1446 }
1447 
1448 static void wmi_11be_attach_mlo_setup_tlv(wmi_unified_t wmi_handle)
1449 {
1450 	struct wmi_ops *ops = wmi_handle->ops;
1451 
1452 	ops->mlo_setup_cmd_send = mlo_setup_cmd_send_tlv;
1453 	ops->mlo_teardown_cmd_send = mlo_teardown_cmd_send_tlv;
1454 	ops->mlo_ready_cmd_send = mlo_ready_cmd_send_tlv;
1455 	ops->extract_mlo_setup_cmpl_event = extract_mlo_setup_cmpl_event_tlv;
1456 	ops->extract_mlo_teardown_cmpl_event =
1457 					extract_mlo_teardown_cmpl_event_tlv;
1458 }
1459 
1460 #else /*WLAN_MLO_MULTI_CHIP*/
1461 
1462 static void wmi_11be_attach_mlo_setup_tlv(wmi_unified_t wmi_handle)
1463 {}
1464 
1465 #endif /*WLAN_MLO_MULTI_CHIP*/
1466 
1467 /**
1468  * extract_mgmt_rx_ml_cu_params_tlv() - extract MGMT Critical Update params
1469  * from MGMT_RX_EVENT_ID
1470  * @wmi_handle: wmi handle
1471  * @evt_buf: pointer to event buffer
1472  * @cu_params: Pointer to MGMT Critical update parameters
1473  *
1474  * Return: QDF_STATUS_SUCCESS for success or error code
1475  */
1476 static
1477 QDF_STATUS extract_mgmt_rx_ml_cu_params_tlv(wmi_unified_t wmi_handle,
1478 					    void *evt_buf,
1479 					    struct mlo_mgmt_ml_info *cu_params)
1480 {
1481 	WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs;
1482 	wmi_mgmt_ml_info *cu_params_tlv;
1483 	wmi_mgmt_rx_hdr *ev_hdr;
1484 	uint32_t num_bpcc_bufp;
1485 
1486 	param_tlvs = evt_buf;
1487 	if (!param_tlvs) {
1488 		wmi_err(" MGMT RX param_tlvs is NULL");
1489 		return QDF_STATUS_E_INVAL;
1490 	}
1491 
1492 	ev_hdr = param_tlvs->hdr;
1493 	if (!ev_hdr) {
1494 		wmi_err("Rx event is NULL");
1495 		return QDF_STATUS_E_INVAL;
1496 	}
1497 
1498 	if (!cu_params) {
1499 		wmi_debug("MGMT Rx CU params is NULL");
1500 		return QDF_STATUS_E_INVAL;
1501 	}
1502 
1503 	cu_params_tlv = param_tlvs->ml_info;
1504 	if (!cu_params_tlv) {
1505 		wmi_debug("mgmt_ml_info TLV is not sent by FW");
1506 		return QDF_STATUS_E_INVAL;
1507 	}
1508 
1509 	cu_params->cu_vdev_map[0] =
1510 		cu_params_tlv->cu_vdev_map_1 & CU_VDEV_MAP_MASK;
1511 	cu_params->cu_vdev_map[1] =
1512 		(cu_params_tlv->cu_vdev_map_1 >> 16) & CU_VDEV_MAP_MASK;
1513 	cu_params->cu_vdev_map[2] =
1514 		cu_params_tlv->cu_vdev_map_2 & CU_VDEV_MAP_MASK;
1515 	cu_params->cu_vdev_map[3] =
1516 		(cu_params_tlv->cu_vdev_map_2 >> 16) & CU_VDEV_MAP_MASK;
1517 	cu_params->cu_vdev_map[4] =
1518 		cu_params_tlv->cu_vdev_map_3 & CU_VDEV_MAP_MASK;
1519 	cu_params->cu_vdev_map[5] =
1520 		(cu_params_tlv->cu_vdev_map_3 >> 16) & CU_VDEV_MAP_MASK;
1521 
1522 	/* At present MAX_LINKS_SUPPORTED are 6.
1523 	 * cu_vdev_map_4 which required for links
1524 	 * 7 and 8 is unused.
1525 	 */
1526 	num_bpcc_bufp = param_tlvs->num_bpcc_bufp;
1527 	if (param_tlvs->num_bpcc_bufp > sizeof(cu_params->vdev_bpcc)) {
1528 		wmi_err("Invalid num_bpcc_bufp:%u", num_bpcc_bufp);
1529 		return QDF_STATUS_E_INVAL;
1530 	}
1531 	qdf_mem_copy(cu_params->vdev_bpcc, param_tlvs->bpcc_bufp,
1532 		     num_bpcc_bufp);
1533 
1534 	qdf_trace_hex_dump(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
1535 			   param_tlvs->bpcc_bufp, num_bpcc_bufp);
1536 
1537 	return QDF_STATUS_SUCCESS;
1538 }
1539 
1540 void wmi_11be_attach_tlv(wmi_unified_t wmi_handle)
1541 {
1542 	struct wmi_ops *ops = wmi_handle->ops;
1543 
1544 	wmi_11be_attach_mlo_setup_tlv(wmi_handle);
1545 	ops->extract_mlo_link_set_active_resp =
1546 		extract_mlo_link_set_active_resp_tlv;
1547 	ops->send_mlo_link_set_active_cmd =
1548 		send_mlo_link_set_active_cmd_tlv;
1549 #ifdef WLAN_FEATURE_11BE
1550 	ops->send_mlo_peer_tid_to_link_map =
1551 		send_mlo_peer_tid_to_link_map_cmd_tlv;
1552 	ops->send_mlo_vdev_tid_to_link_map =
1553 		send_mlo_vdev_tid_to_link_map_cmd_tlv;
1554 	ops->extract_mlo_vdev_tid_to_link_map_event =
1555 		extract_mlo_vdev_tid_to_link_map_event_tlv;
1556 	ops->extract_mlo_vdev_bcast_tid_to_link_map_event =
1557 		extract_mlo_vdev_bcast_tid_to_link_map_event_tlv;
1558 #endif /* WLAN_FEATURE_11BE */
1559 	ops->extract_mgmt_rx_ml_cu_params =
1560 		extract_mgmt_rx_ml_cu_params_tlv;
1561 	ops->send_mlo_link_removal_cmd = send_mlo_link_removal_cmd_tlv;
1562 	ops->extract_mlo_link_removal_evt_fixed_param =
1563 			extract_mlo_link_removal_evt_fixed_param_tlv;
1564 	ops->extract_mlo_link_removal_tbtt_update =
1565 			extract_mlo_link_removal_tbtt_update_tlv;
1566 	ops->extract_mgmt_rx_mlo_link_removal_info =
1567 			extract_mgmt_rx_mlo_link_removal_info_tlv;
1568 }
1569