xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_11be_tlv.c (revision 70a19e16789e308182f63b15c75decec7bf0b342)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #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_NUM:
380 		*fw_mode = WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM;
381 		break;
382 	case MLO_LINK_FORCE_MODE_INACTIVE_NUM:
383 		*fw_mode = WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM;
384 		break;
385 	case MLO_LINK_FORCE_MODE_NO_FORCE:
386 		*fw_mode = WMI_MLO_LINK_NO_FORCE;
387 		break;
388 	default:
389 		wmi_err("Invalid force mode: %d", host_mode);
390 		return QDF_STATUS_E_INVAL;
391 	}
392 
393 	return QDF_STATUS_SUCCESS;
394 }
395 
396 /**
397  * force_reason_host_to_fw() - translate force reason for MLO link set active
398  *  command
399  * @host_reason: force reason defined by host
400  * @fw_reason: buffer to store force reason defined by FW
401  *
402  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL otherwise
403  */
404 static inline QDF_STATUS
405 force_reason_host_to_fw(enum mlo_link_force_reason host_reason,
406 			WMI_MLO_LINK_FORCE_REASON *fw_reason)
407 {
408 	switch (host_reason) {
409 	case MLO_LINK_FORCE_REASON_CONNECT:
410 		*fw_reason = WMI_MLO_LINK_FORCE_REASON_NEW_CONNECT;
411 		break;
412 	case MLO_LINK_FORCE_REASON_DISCONNECT:
413 		*fw_reason =  WMI_MLO_LINK_FORCE_REASON_NEW_DISCONNECT;
414 		break;
415 	default:
416 		wmi_err("Invalid force reason: %d", host_reason);
417 		return QDF_STATUS_E_INVAL;
418 	}
419 
420 	return QDF_STATUS_SUCCESS;
421 }
422 
423 /**
424  * send_mlo_link_set_active_cmd_tlv() - send mlo link set active command
425  * @wmi_handle: wmi handle
426  * @param: Pointer to mlo link set active param
427  *
428  * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error
429  */
430 static QDF_STATUS
431 send_mlo_link_set_active_cmd_tlv(wmi_unified_t wmi_handle,
432 				 struct mlo_link_set_active_param *param)
433 {
434 	QDF_STATUS status;
435 	wmi_mlo_link_set_active_cmd_fixed_param *cmd;
436 	wmi_mlo_set_active_link_number_param *link_num_param;
437 	uint32_t *vdev_bitmap;
438 	uint32_t num_link_num_param = 0, num_vdev_bitmap = 0, tlv_len;
439 	wmi_buf_t buf;
440 	uint8_t *buf_ptr;
441 	uint32_t len;
442 	int i;
443 	WMITLV_TAG_ID tag_id;
444 	WMI_MLO_LINK_FORCE_MODE force_mode;
445 	WMI_MLO_LINK_FORCE_REASON force_reason;
446 
447 	if (!param->num_vdev_bitmap && !param->num_link_entry) {
448 		wmi_err("No entry is provided vdev bit map %d link entry %d",
449 			param->num_vdev_bitmap,
450 			param->num_link_entry);
451 		return QDF_STATUS_E_INVAL;
452 	}
453 
454 	status = force_mode_host_to_fw(param->force_mode, &force_mode);
455 	if (QDF_IS_STATUS_ERROR(status))
456 		return QDF_STATUS_E_INVAL;
457 
458 	status = force_reason_host_to_fw(param->reason, &force_reason);
459 	if (QDF_IS_STATUS_ERROR(status))
460 		return QDF_STATUS_E_INVAL;
461 
462 	switch (force_mode) {
463 	case WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM:
464 	case WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM:
465 		num_link_num_param = param->num_link_entry;
466 		fallthrough;
467 	case WMI_MLO_LINK_FORCE_ACTIVE:
468 	case WMI_MLO_LINK_FORCE_INACTIVE:
469 	case WMI_MLO_LINK_NO_FORCE:
470 		num_vdev_bitmap = param->num_vdev_bitmap;
471 		break;
472 	default:
473 		wmi_err("Invalid force reason: %d", force_mode);
474 		return QDF_STATUS_E_INVAL;
475 	}
476 
477 	len = sizeof(*cmd) +
478 	      WMI_TLV_HDR_SIZE + sizeof(*link_num_param) * num_link_num_param +
479 	      WMI_TLV_HDR_SIZE + sizeof(*vdev_bitmap) * num_vdev_bitmap;
480 
481 	buf = wmi_buf_alloc(wmi_handle, len);
482 	if (!buf)
483 		return QDF_STATUS_E_NOMEM;
484 
485 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
486 	cmd = (wmi_mlo_link_set_active_cmd_fixed_param *)buf_ptr;
487 	tlv_len = WMITLV_GET_STRUCT_TLVLEN
488 			(wmi_mlo_link_set_active_cmd_fixed_param);
489 
490 	tag_id = WMITLV_TAG_STRUC_wmi_mlo_link_set_active_cmd_fixed_param;
491 	WMITLV_SET_HDR(&cmd->tlv_header, tag_id, tlv_len);
492 	cmd->force_mode = force_mode;
493 	cmd->reason = force_reason;
494 	wmi_debug("mode %d reason %d num_link_num_param %d num_vdev_bitmap %d",
495 		  cmd->force_mode, cmd->reason, num_link_num_param,
496 		  num_vdev_bitmap);
497 	buf_ptr += sizeof(*cmd);
498 
499 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
500 		       sizeof(*link_num_param) * num_link_num_param);
501 	buf_ptr += WMI_TLV_HDR_SIZE;
502 
503 	if (num_link_num_param) {
504 		link_num_param =
505 			(wmi_mlo_set_active_link_number_param *)buf_ptr;
506 		tlv_len = WMITLV_GET_STRUCT_TLVLEN
507 				(wmi_mlo_set_active_link_number_param);
508 		for (i = 0; i < num_link_num_param; i++) {
509 			WMITLV_SET_HDR(&link_num_param->tlv_header, 0, tlv_len);
510 			link_num_param->num_of_link =
511 				param->link_num[i].num_of_link;
512 			link_num_param->vdev_type =
513 				param->link_num[i].vdev_type;
514 			link_num_param->vdev_subtype =
515 				param->link_num[i].vdev_subtype;
516 			link_num_param->home_freq =
517 				param->link_num[i].home_freq;
518 			wmi_debug("entry[%d]: num_of_link %d vdev type %d subtype %d freq %d",
519 				  i, link_num_param->num_of_link,
520 				  link_num_param->vdev_type,
521 				  link_num_param->vdev_subtype,
522 				  link_num_param->home_freq);
523 			link_num_param++;
524 		}
525 
526 		buf_ptr += sizeof(*link_num_param) * num_link_num_param;
527 	}
528 
529 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
530 		       sizeof(*vdev_bitmap) * num_vdev_bitmap);
531 	buf_ptr += WMI_TLV_HDR_SIZE;
532 
533 	if (num_vdev_bitmap) {
534 		vdev_bitmap = (A_UINT32 *)(buf_ptr);
535 		for (i = 0; i < num_vdev_bitmap; i++) {
536 			vdev_bitmap[i] = param->vdev_bitmap[i];
537 			wmi_debug("entry[%d]: vdev_id_bitmap 0x%x ",
538 				  i, vdev_bitmap[i]);
539 		}
540 
541 		buf_ptr += sizeof(*vdev_bitmap) * num_vdev_bitmap;
542 	}
543 
544 	wmi_mtrace(WMI_MLO_LINK_SET_ACTIVE_CMDID, 0, cmd->force_mode);
545 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
546 				      WMI_MLO_LINK_SET_ACTIVE_CMDID);
547 	if (QDF_IS_STATUS_ERROR(status)) {
548 		wmi_err("Failed to send MLO link set active command to FW: %d",
549 			status);
550 		wmi_buf_free(buf);
551 	}
552 
553 	return status;
554 }
555 
556 /**
557  * extract_mlo_link_set_active_resp_tlv() - extract mlo link set active resp
558  *  from event
559  * @wmi_handle: wmi handle
560  * @evt_buf: pointer to event buffer
561  * @resp: Pointer to hold mlo link set active resp
562  *
563  * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error
564  */
565 static QDF_STATUS
566 extract_mlo_link_set_active_resp_tlv(wmi_unified_t wmi_handle, void *evt_buf,
567 				     struct mlo_link_set_active_resp *resp)
568 {
569 	wmi_mlo_link_set_active_resp_event_fixed_param *evt;
570 	WMI_MLO_LINK_SET_ACTIVE_RESP_EVENTID_param_tlvs *param_buf;
571 	uint32_t entry_num, *bitmap;
572 	int i;
573 
574 	param_buf = evt_buf;
575 	if (!param_buf || !resp) {
576 		wmi_err("Invalid param");
577 		return QDF_STATUS_E_INVAL;
578 	}
579 
580 	evt = param_buf->fixed_param;
581 	resp->status = evt->status;
582 	wmi_debug("status: %u", resp->status);
583 
584 	bitmap = param_buf->force_active_vdev_bitmap;
585 	entry_num = qdf_min(param_buf->num_force_active_vdev_bitmap,
586 			    (uint32_t)MLO_VDEV_BITMAP_SZ);
587 	resp->active_sz = entry_num;
588 	for (i = 0; i < entry_num; i++) {
589 		resp->active[i] = bitmap[i];
590 		wmi_debug("active[%d]: 0x%x", i, resp->active[i]);
591 	}
592 
593 	bitmap = param_buf->force_inactive_vdev_bitmap;
594 	entry_num = qdf_min(param_buf->num_force_inactive_vdev_bitmap,
595 			    (uint32_t)MLO_VDEV_BITMAP_SZ);
596 	resp->inactive_sz = entry_num;
597 	for (i = 0; i < entry_num; i++) {
598 		resp->inactive[i] = bitmap[i];
599 		wmi_debug("inactive[%d]: 0x%x", i, resp->inactive[i]);
600 	}
601 
602 	return QDF_STATUS_SUCCESS;
603 }
604 
605 /**
606  * send_mlo_link_removal_cmd_tlv() - Send WMI command for MLO link removal
607  * @wmi_handle: wmi handle
608  * @params: MLO link removal command parameters
609  *
610  * Return: QDF_STATUS_SUCCESS of operation
611  */
612 static QDF_STATUS send_mlo_link_removal_cmd_tlv(
613 	wmi_unified_t wmi_handle,
614 	const struct mlo_link_removal_cmd_params *params)
615 {
616 	wmi_mlo_link_removal_cmd_fixed_param *fixed_params;
617 	wmi_buf_t buf;
618 	uint8_t *buf_ptr;
619 	uint32_t buf_len = 0;
620 	uint32_t ie_len_aligned = 0;
621 	QDF_STATUS ret;
622 
623 	if (!params) {
624 		wmi_err("command params is NULL");
625 		return QDF_STATUS_E_NULL_VALUE;
626 	}
627 
628 	ie_len_aligned = roundup(params->reconfig_ml_ie_size, sizeof(uint32_t));
629 
630 	buf_len = sizeof(wmi_mlo_link_removal_cmd_fixed_param) +
631 		  WMI_TLV_HDR_SIZE + ie_len_aligned;
632 
633 	buf = wmi_buf_alloc(wmi_handle, buf_len);
634 	if (!buf) {
635 		wmi_err("wmi buf alloc failed for link removal cmd: psoc (%pK) vdev(%u)",
636 			wmi_handle->soc->wmi_psoc, params->vdev_id);
637 		return QDF_STATUS_E_NOMEM;
638 	}
639 
640 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
641 
642 	/* Populate fixed params TLV */
643 	fixed_params = (wmi_mlo_link_removal_cmd_fixed_param *)buf_ptr;
644 	WMITLV_SET_HDR(&fixed_params->tlv_header,
645 		       WMITLV_TAG_STRUC_wmi_mlo_link_removal_cmd_fixed_param,
646 		       WMITLV_GET_STRUCT_TLVLEN(
647 			   wmi_mlo_link_removal_cmd_fixed_param));
648 	fixed_params->vdev_id = params->vdev_id;
649 	fixed_params->reconfig_ml_ie_num_bytes_valid =
650 		params->reconfig_ml_ie_size;
651 	buf_ptr += sizeof(*fixed_params);
652 
653 	/* Populate the array of bytes TLV */
654 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned);
655 	buf_ptr += WMI_TLV_HDR_SIZE;
656 
657 	/* Populate ML reconfiguration element in raw bytes */
658 	qdf_mem_copy(buf_ptr, params->reconfig_ml_ie,
659 		     params->reconfig_ml_ie_size);
660 
661 	wmi_mtrace(WMI_MLO_LINK_REMOVAL_CMDID, fixed_params->vdev_id, 0);
662 	ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len,
663 				   WMI_MLO_LINK_REMOVAL_CMDID);
664 	if (QDF_IS_STATUS_ERROR(ret)) {
665 		wmi_err("Failed to send MLO link removal cmd: psoc (%pK) vdev(%u)",
666 			wmi_handle->soc->wmi_psoc, params->vdev_id);
667 		wmi_buf_free(buf);
668 	}
669 
670 	return ret;
671 }
672 
673 /**
674  * extract_mlo_link_removal_evt_fixed_param_tlv() - Extract fixed parameters TLV
675  * from the MLO link removal WMI  event
676  * @wmi_handle: wmi handle
677  * @buf: pointer to event buffer
678  * @params: MLO link removal event parameters
679  *
680  * Return: QDF_STATUS of operation
681  */
682 static QDF_STATUS
683 extract_mlo_link_removal_evt_fixed_param_tlv(
684 	struct wmi_unified *wmi_handle,
685 	void *buf,
686 	struct mlo_link_removal_evt_params *params)
687 {
688 	WMI_MLO_LINK_REMOVAL_EVENTID_param_tlvs *param_buf = buf;
689 	wmi_mlo_link_removal_evt_fixed_param *ev;
690 
691 	if (!param_buf) {
692 		wmi_err_rl("Param_buf is NULL");
693 		return QDF_STATUS_E_NULL_VALUE;
694 	}
695 
696 	if (!params) {
697 		wmi_err_rl("params is NULL");
698 		return QDF_STATUS_E_NULL_VALUE;
699 	}
700 
701 	ev = param_buf->fixed_param;
702 	params->vdev_id = ev->vdev_id;
703 
704 	return QDF_STATUS_SUCCESS;
705 }
706 
707 /**
708  * extract_mlo_link_removal_tbtt_update_tlv() - Extract TBTT update TLV
709  * from the MLO link removal WMI  event
710  * @wmi_handle: wmi handle
711  * @buf: pointer to event buffer
712  * @tbtt_info: TBTT information to be populated
713  *
714  * Return: QDF_STATUS of operation
715  */
716 static QDF_STATUS
717 extract_mlo_link_removal_tbtt_update_tlv(
718 	struct wmi_unified *wmi_handle,
719 	void *buf,
720 	struct mlo_link_removal_tbtt_info *tbtt_info)
721 {
722 	WMI_MLO_LINK_REMOVAL_EVENTID_param_tlvs *param_buf = buf;
723 	wmi_mlo_link_removal_tbtt_update *tlv;
724 
725 	if (!param_buf) {
726 		wmi_err_rl("Param_buf is NULL");
727 		return QDF_STATUS_E_NULL_VALUE;
728 	}
729 
730 	if (!tbtt_info) {
731 		wmi_err_rl("Writable argument is NULL");
732 		return QDF_STATUS_E_NULL_VALUE;
733 	}
734 
735 	tlv = param_buf->tbtt_update;
736 
737 	tbtt_info->tbtt_count = tlv->tbtt_count;
738 	tbtt_info->tsf = ((uint64_t)tlv->tsf_high << 32) | tlv->tsf_low;
739 	tbtt_info->qtimer_reading =
740 		((uint64_t)tlv->qtimer_ts_high << 32) | tlv->qtimer_ts_low;
741 
742 	return QDF_STATUS_SUCCESS;
743 }
744 
745 /**
746  * extract_mgmt_rx_mlo_link_removal_info_tlv() - Extract MLO link removal info
747  * from MGMT Rx event
748  * @wmi_handle: wmi handle
749  * @buf: event buffer
750  * @link_removal_info: link removal information array to be populated
751  * @num_link_removal_info: Number of elements in @link_removal_info
752  *
753  * Return: QDF_STATUS of operation
754  */
755 static QDF_STATUS
756 extract_mgmt_rx_mlo_link_removal_info_tlv(
757 	struct wmi_unified *wmi_handle,
758 	void *buf,
759 	struct mgmt_rx_mlo_link_removal_info *link_removal_info,
760 	int num_link_removal_info)
761 {
762 	WMI_MGMT_RX_EVENTID_param_tlvs *param_buf = buf;
763 	wmi_mlo_link_removal_tbtt_count *tlv_arr;
764 	int tlv_idx = 0;
765 	struct mgmt_rx_mlo_link_removal_info *info;
766 
767 	if (!param_buf) {
768 		wmi_err_rl("Param_buf is NULL");
769 		return QDF_STATUS_E_NULL_VALUE;
770 	}
771 
772 	if (!link_removal_info) {
773 		wmi_err_rl("Writable argument is NULL");
774 		return QDF_STATUS_E_NULL_VALUE;
775 	}
776 
777 	if (num_link_removal_info != param_buf->num_link_removal_tbtt_count) {
778 		wmi_err_rl("link_removal_info array size (%d) is not equal to"
779 			   "number of corresponding TLVs(%d) present in event",
780 			   num_link_removal_info,
781 			   param_buf->num_link_removal_tbtt_count);
782 		return QDF_STATUS_E_RANGE;
783 	}
784 
785 	tlv_arr = param_buf->link_removal_tbtt_count;
786 	for (; tlv_idx < param_buf->num_link_removal_tbtt_count; tlv_idx++) {
787 		info = &link_removal_info[tlv_idx];
788 
789 		info->hw_link_id = WMI_MLO_LINK_REMOVAL_GET_LINKID(
790 					tlv_arr[tlv_idx].tbtt_info);
791 		info->vdev_id = WMI_MLO_LINK_REMOVAL_GET_VDEVID(
792 					tlv_arr[tlv_idx].tbtt_info);
793 		info->tbtt_count = WMI_MLO_LINK_REMOVAL_GET_TBTT_COUNT(
794 					tlv_arr[tlv_idx].tbtt_info);
795 	}
796 
797 	return QDF_STATUS_SUCCESS;
798 }
799 
800 #ifdef WLAN_FEATURE_11BE
801 size_t peer_assoc_t2lm_params_size(struct peer_assoc_params *req)
802 {
803 	size_t peer_assoc_t2lm_size = WMI_TLV_HDR_SIZE +
804 		(req->t2lm_params.num_dir * T2LM_MAX_NUM_TIDS *
805 		 (sizeof(wmi_peer_assoc_tid_to_link_map)));
806 
807 	return peer_assoc_t2lm_size;
808 }
809 
810 static void peer_assoc_populate_t2lm_tlv(wmi_peer_assoc_tid_to_link_map *cmd,
811 				  struct wlan_host_t2lm_of_tids *t2lm,
812 				  uint8_t tid_num)
813 {
814 	WMITLV_SET_HDR(&cmd->tlv_header,
815 		       WMITLV_TAG_STRUC_wmi_peer_assoc_tid_to_link_map,
816 		       WMITLV_GET_STRUCT_TLVLEN(
817 				   wmi_peer_assoc_tid_to_link_map));
818 
819 	/* Populate TID number */
820 	WMI_TID_TO_LINK_MAP_TID_NUM_SET(cmd->tid_to_link_map_info, tid_num);
821 
822 	/* Populate the direction */
823 	WMI_TID_TO_LINK_MAP_DIR_SET(cmd->tid_to_link_map_info,
824 				    t2lm->direction);
825 
826 	/* Populate the default link mapping value */
827 	WMI_TID_TO_LINK_MAP_DEFAULT_MAPPING_SET(
828 			cmd->tid_to_link_map_info,
829 			t2lm->default_link_mapping);
830 
831 	/* Populate the T2LM provisioned links for the corresponding TID
832 	 * number.
833 	 */
834 	WMI_TID_TO_LINK_MAP_LINK_MASK_SET(
835 			cmd->tid_to_link_map_info,
836 			t2lm->t2lm_provisioned_links[tid_num]);
837 
838 	wmi_debug("Add T2LM TLV: tid_to_link_map_info:%x",
839 		  cmd->tid_to_link_map_info);
840 }
841 
842 uint8_t *peer_assoc_add_tid_to_link_map(uint8_t *buf_ptr,
843 					struct peer_assoc_params *req)
844 {
845 	struct wmi_host_tid_to_link_map_params *t2lm_params = &req->t2lm_params;
846 	wmi_peer_assoc_tid_to_link_map *cmd;
847 	uint8_t dir = 0;
848 	uint8_t tid_num = 0;
849 
850 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
851 		       (req->t2lm_params.num_dir * T2LM_MAX_NUM_TIDS *
852 		       sizeof(wmi_peer_assoc_tid_to_link_map)));
853 	buf_ptr += sizeof(uint32_t);
854 
855 	for (dir = 0; dir < t2lm_params->num_dir; dir++) {
856 		wmi_debug("Add T2LM TLV for peer: " QDF_MAC_ADDR_FMT " direction:%d",
857 				QDF_MAC_ADDR_REF(t2lm_params->peer_macaddr),
858 				t2lm_params->t2lm_info[dir].direction);
859 		for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
860 			cmd = (wmi_peer_assoc_tid_to_link_map *)buf_ptr;
861 			peer_assoc_populate_t2lm_tlv(
862 					cmd, &t2lm_params->t2lm_info[dir],
863 					tid_num);
864 			buf_ptr += sizeof(wmi_peer_assoc_tid_to_link_map);
865 		}
866 	}
867 
868 	return buf_ptr;
869 }
870 
871 static QDF_STATUS send_mlo_peer_tid_to_link_map_cmd_tlv(
872 		wmi_unified_t wmi_handle,
873 		struct wmi_host_tid_to_link_map_params *params)
874 {
875 	wmi_peer_tid_to_link_map_fixed_param *cmd;
876 	wmi_tid_to_link_map *t2lm;
877 	wmi_buf_t buf;
878 	uint8_t *buf_ptr;
879 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
880 	uint32_t buf_len = 0;
881 	uint8_t dir = 0;
882 	uint8_t tid_num = 0;
883 
884 	buf_len = sizeof(wmi_peer_tid_to_link_map_fixed_param) +
885 		WMI_TLV_HDR_SIZE + (params->num_dir * T2LM_MAX_NUM_TIDS *
886 		 sizeof(wmi_tid_to_link_map));
887 
888 	buf = wmi_buf_alloc(wmi_handle, buf_len);
889 	if (!buf) {
890 		wmi_err("wmi buf alloc failed for mlo_peer_mac: "
891 				QDF_MAC_ADDR_FMT,
892 				QDF_MAC_ADDR_REF(params->peer_macaddr));
893 		return QDF_STATUS_E_NOMEM;
894 	}
895 
896 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
897 	cmd = (wmi_peer_tid_to_link_map_fixed_param *)buf_ptr;
898 
899 	WMITLV_SET_HDR(&cmd->tlv_header,
900 		       WMITLV_TAG_STRUC_wmi_peer_tid_to_link_map_fixed_param,
901 		       WMITLV_GET_STRUCT_TLVLEN(
902 			   wmi_peer_tid_to_link_map_fixed_param));
903 
904 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
905 			wmi_handle, params->pdev_id);
906 
907 	WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->link_macaddr);
908 
909 	buf_ptr += sizeof(wmi_peer_tid_to_link_map_fixed_param);
910 
911 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
912 		       (params->num_dir * T2LM_MAX_NUM_TIDS *
913 		       sizeof(wmi_tid_to_link_map)));
914 	buf_ptr += sizeof(uint32_t);
915 
916 	for (dir = 0; dir < params->num_dir; dir++) {
917 		wmi_debug("Add T2LM TLV for peer: " QDF_MAC_ADDR_FMT " direction:%d",
918 				QDF_MAC_ADDR_REF(params->peer_macaddr),
919 				params->t2lm_info[dir].direction);
920 
921 		for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
922 			t2lm = (wmi_tid_to_link_map *)buf_ptr;
923 
924 			WMITLV_SET_HDR(&t2lm->tlv_header,
925 				       WMITLV_TAG_STRUC_wmi_tid_to_link_map,
926 				       WMITLV_GET_STRUCT_TLVLEN(
927 					   wmi_tid_to_link_map));
928 
929 			/* Populate TID number */
930 			WMI_TID_TO_LINK_MAP_TID_NUM_SET(
931 					t2lm->tid_to_link_map_info, tid_num);
932 
933 			/* Populate the direction */
934 			WMI_TID_TO_LINK_MAP_DIR_SET(
935 					t2lm->tid_to_link_map_info,
936 					params->t2lm_info[dir].direction);
937 
938 			/* Populate the default link mapping value */
939 			WMI_TID_TO_LINK_MAP_DEFAULT_MAPPING_SET(
940 					t2lm->tid_to_link_map_info,
941 					params->t2lm_info[dir].default_link_mapping);
942 
943 			/* Populate the T2LM provisioned links for the
944 			 * corresponding TID number.
945 			 */
946 			WMI_TID_TO_LINK_MAP_LINK_MASK_SET(
947 					t2lm->tid_to_link_map_info,
948 					params->t2lm_info[dir].t2lm_provisioned_links[tid_num]);
949 
950 			buf_ptr += sizeof(wmi_tid_to_link_map);
951 
952 			wmi_debug("Add T2LM TLV: tid_to_link_map_info:%x",
953 				  t2lm->tid_to_link_map_info);
954 		}
955 	}
956 
957 	wmi_mtrace(WMI_MLO_PEER_TID_TO_LINK_MAP_CMDID, cmd->pdev_id, 0);
958 	ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len,
959 				   WMI_MLO_PEER_TID_TO_LINK_MAP_CMDID);
960 	if (ret) {
961 		wmi_err("Failed to send T2LM command to FW: %d mlo_peer_mac: " QDF_MAC_ADDR_FMT,
962 				ret, QDF_MAC_ADDR_REF(params->peer_macaddr));
963 		wmi_buf_free(buf);
964 	}
965 
966 	return ret;
967 }
968 
969 static void update_t2lm_ie_info_params(
970 		wmi_mlo_ap_vdev_tid_to_link_map_ie_info * info,
971 		struct wlan_t2lm_info *params)
972 {
973 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_DIR_SET(
974 			info->tid_to_link_map_ctrl,
975 			params->direction);
976 
977 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_DEF_LINK_SET(
978 			info->tid_to_link_map_ctrl,
979 			params->default_link_mapping);
980 
981 	info->map_switch_time = params->mapping_switch_time;
982 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_SWT_TIME_SET(
983 			info->tid_to_link_map_ctrl,
984 			params->mapping_switch_time_present);
985 
986 	info->expected_duration = params->expected_duration;
987 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_DUR_TIME_SET(
988 			info->tid_to_link_map_ctrl,
989 			params->expected_duration_present);
990 
991 	wmi_debug("tid_to_link_map_ctrl:%x map_switch_time:%d expected_duration:%d",
992 		  info->tid_to_link_map_ctrl, info->map_switch_time,
993 		  info->expected_duration);
994 
995 	/* Do not fill link mapping values when default mapping is set to 1 */
996 	if (params->default_link_mapping)
997 		return;
998 
999 	WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_LINK_MAP_PRE_SET(
1000 			info->tid_to_link_map_ctrl, 0xff);
1001 
1002 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_0_SET(
1003 			info->ieee_tid_0_1_link_map,
1004 			params->ieee_link_map_tid[0]);
1005 
1006 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_1_SET(
1007 			info->ieee_tid_0_1_link_map,
1008 			params->ieee_link_map_tid[1]);
1009 
1010 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_2_SET(
1011 			info->ieee_tid_2_3_link_map,
1012 			params->ieee_link_map_tid[2]);
1013 
1014 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_3_SET(
1015 			info->ieee_tid_2_3_link_map,
1016 			params->ieee_link_map_tid[3]);
1017 
1018 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_4_SET(
1019 			info->ieee_tid_4_5_link_map,
1020 			params->ieee_link_map_tid[4]);
1021 
1022 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_5_SET(
1023 			info->ieee_tid_4_5_link_map,
1024 			params->ieee_link_map_tid[5]);
1025 
1026 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_6_SET(
1027 			info->ieee_tid_6_7_link_map,
1028 			params->ieee_link_map_tid[6]);
1029 
1030 	WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_7_SET(
1031 			info->ieee_tid_6_7_link_map,
1032 			params->ieee_link_map_tid[7]);
1033 
1034 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_0_SET(
1035 			info->hw_tid_0_1_link_map,
1036 			params->hw_link_map_tid[0]);
1037 
1038 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_1_SET(
1039 			info->hw_tid_0_1_link_map,
1040 			params->hw_link_map_tid[1]);
1041 
1042 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_2_SET(
1043 			info->hw_tid_2_3_link_map,
1044 			params->hw_link_map_tid[2]);
1045 
1046 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_3_SET(
1047 			info->hw_tid_2_3_link_map,
1048 			params->hw_link_map_tid[3]);
1049 
1050 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_4_SET(
1051 			info->hw_tid_4_5_link_map,
1052 			params->hw_link_map_tid[4]);
1053 
1054 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_5_SET(
1055 			info->hw_tid_4_5_link_map,
1056 			params->hw_link_map_tid[5]);
1057 
1058 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_6_SET(
1059 			info->hw_tid_6_7_link_map,
1060 			params->hw_link_map_tid[6]);
1061 
1062 	WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_7_SET(
1063 			info->hw_tid_6_7_link_map,
1064 			params->hw_link_map_tid[7]);
1065 
1066 	wmi_debug("tid_to_link_map_ctrl:%x", info->tid_to_link_map_ctrl);
1067 	wmi_debug("ieee_link_map: tid_0_1:%x tid_2_3:%x tid_4_5:%x tid_6_7:%x",
1068 		  info->ieee_tid_0_1_link_map, info->ieee_tid_2_3_link_map,
1069 		  info->ieee_tid_4_5_link_map, info->ieee_tid_6_7_link_map);
1070 	wmi_debug("hw_link_map: tid_0_1:%x tid_2_3:%x tid_4_5:%x tid_6_7:%x",
1071 		  info->hw_tid_0_1_link_map, info->hw_tid_2_3_link_map,
1072 		  info->hw_tid_4_5_link_map, info->hw_tid_6_7_link_map);
1073 }
1074 
1075 static QDF_STATUS send_mlo_vdev_tid_to_link_map_cmd_tlv(
1076 		wmi_unified_t wmi_handle,
1077 		struct wmi_host_tid_to_link_map_ap_params *params)
1078 {
1079 	wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param *cmd;
1080 	wmi_mlo_ap_vdev_tid_to_link_map_ie_info *info;
1081 	wmi_buf_t buf;
1082 	uint8_t *buf_ptr;
1083 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
1084 	uint32_t buf_len = 0;
1085 	uint32_t num_info = 0;
1086 
1087 	if (params->num_t2lm_info > WLAN_MAX_T2LM_IE) {
1088 		wmi_err("Failed to send T2LM command to FW for vdev id %d as t2lm info %d is greater than max %d",
1089 			params->vdev_id,
1090 			params->num_t2lm_info,
1091 			WLAN_MAX_T2LM_IE);
1092 		return QDF_STATUS_E_INVAL;
1093 	}
1094 
1095 	buf_len = sizeof(wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param) +
1096 		WMI_TLV_HDR_SIZE + (params->num_t2lm_info *
1097 		 sizeof(wmi_mlo_ap_vdev_tid_to_link_map_ie_info));
1098 
1099 	buf = wmi_buf_alloc(wmi_handle, buf_len);
1100 	if (!buf) {
1101 		wmi_err("wmi buf alloc failed for vdev id %d while t2lm map cmd send: ",
1102 			params->vdev_id);
1103 		return QDF_STATUS_E_NOMEM;
1104 	}
1105 
1106 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
1107 	cmd = (wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param *)buf_ptr;
1108 
1109 	WMITLV_SET_HDR(
1110 	       &cmd->tlv_header,
1111 	       WMITLV_TAG_STRUC_wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param,
1112 	       WMITLV_GET_STRUCT_TLVLEN(
1113 	       wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param));
1114 
1115 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1116 			wmi_handle, params->pdev_id);
1117 	cmd->vdev_id = params->vdev_id;
1118 	cmd->disabled_link_bitmap = params->disabled_link_bitmap;
1119 	wmi_debug("pdev_id:%d vdev_id:%d disabled_link_bitmap:%x num_t2lm_info:%d",
1120 		  cmd->pdev_id, cmd->vdev_id, cmd->disabled_link_bitmap,
1121 		  params->num_t2lm_info);
1122 
1123 	buf_ptr += sizeof(wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param);
1124 
1125 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1126 		       (params->num_t2lm_info *
1127 			sizeof(wmi_mlo_ap_vdev_tid_to_link_map_ie_info)));
1128 	buf_ptr += sizeof(uint32_t);
1129 
1130 	for (num_info = 0; num_info < params->num_t2lm_info; num_info++) {
1131 		info = (wmi_mlo_ap_vdev_tid_to_link_map_ie_info *)buf_ptr;
1132 
1133 		WMITLV_SET_HDR(
1134 		       &info->tlv_header,
1135 		       WMITLV_TAG_STRUC_wmi_mlo_ap_vdev_tid_to_link_map_ie_info,
1136 		       WMITLV_GET_STRUCT_TLVLEN(
1137 		       wmi_mlo_ap_vdev_tid_to_link_map_ie_info));
1138 		update_t2lm_ie_info_params(info, &params->info[num_info]);
1139 		buf_ptr += sizeof(wmi_mlo_ap_vdev_tid_to_link_map_ie_info);
1140 	}
1141 
1142 	wmi_mtrace(WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_CMDID, cmd->vdev_id, 0);
1143 	ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len,
1144 				   WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_CMDID);
1145 	if (ret) {
1146 		wmi_err("Failed to send T2LM command to FW: %d vdev id %d",
1147 			ret, cmd->vdev_id);
1148 		wmi_buf_free(buf);
1149 	}
1150 
1151 	return ret;
1152 }
1153 
1154 static QDF_STATUS
1155 extract_mlo_vdev_tid_to_link_map_event_tlv(
1156 		struct wmi_unified *wmi_handle,
1157 		uint8_t *buf,
1158 		struct mlo_vdev_host_tid_to_link_map_resp *params)
1159 {
1160 	WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_EVENTID_param_tlvs *param_buf;
1161 	wmi_mlo_ap_vdev_tid_to_link_map_evt_fixed_param *ev;
1162 
1163 	param_buf = (WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_EVENTID_param_tlvs *)buf;
1164 	if (!param_buf) {
1165 		wmi_err_rl("Param_buf is NULL");
1166 		return QDF_STATUS_E_FAILURE;
1167 	}
1168 
1169 	ev = (wmi_mlo_ap_vdev_tid_to_link_map_evt_fixed_param *)
1170 		param_buf->fixed_param;
1171 
1172 	params->vdev_id = ev->vdev_id;
1173 	params->status  = ev->status_type;
1174 	params->mapping_switch_tsf = ev->mapping_switch_tsf;
1175 
1176 	return QDF_STATUS_SUCCESS;
1177 }
1178 
1179 static QDF_STATUS
1180 extract_mlo_vdev_bcast_tid_to_link_map_event_tlv(
1181 				struct wmi_unified *wmi_handle,
1182 				void *buf,
1183 				struct mlo_bcast_t2lm_info *bcast_info)
1184 {
1185 	WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs;
1186 	wmi_mlo_bcast_t2lm_info *info;
1187 	int i;
1188 
1189 	param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *)buf;
1190 	if (!param_tlvs) {
1191 		wmi_err(" MGMT RX param_tlvs is NULL");
1192 		return QDF_STATUS_E_INVAL;
1193 	}
1194 
1195 	if (param_tlvs->num_mlo_bcast_t2lm_info > MAX_AP_MLDS_PER_LINK) {
1196 		wmi_err("num_mlo_bcast_t2lm_info is greater than %d",
1197 			MAX_AP_MLDS_PER_LINK);
1198 		return QDF_STATUS_E_INVAL;
1199 	}
1200 
1201 	info = param_tlvs->mlo_bcast_t2lm_info;
1202 	if (!info) {
1203 		wmi_debug("mlo_bcast_t2lm_info is not applicable");
1204 		return QDF_STATUS_SUCCESS;
1205 	}
1206 
1207 	bcast_info->num_vdevs = param_tlvs->num_mlo_bcast_t2lm_info;
1208 	wmi_debug("num_vdevs:%d", bcast_info->num_vdevs);
1209 	for (i = 0; i < param_tlvs->num_mlo_bcast_t2lm_info; i++) {
1210 		bcast_info->vdev_id[i] =
1211 			WMI_MLO_BROADCAST_TID_TO_LINK_MAP_INFO_VDEV_ID_GET(
1212 					info->vdev_id_expec_dur);
1213 
1214 		bcast_info->expected_duration[i] =
1215 			WMI_MLO_BROADCAST_TID_TO_LINK_MAP_INFO_EXP_DUR_GET(
1216 					info->vdev_id_expec_dur);
1217 		wmi_debug("vdev_id:%d expected_duration:%d",
1218 			  bcast_info->vdev_id[i],
1219 			  bcast_info->expected_duration[i]);
1220 	}
1221 
1222 	return QDF_STATUS_SUCCESS;
1223 }
1224 #else
1225 size_t peer_assoc_t2lm_params_size(struct peer_assoc_params *req)
1226 {
1227 	return WMI_TLV_HDR_SIZE;
1228 }
1229 
1230 uint8_t *peer_assoc_add_tid_to_link_map(uint8_t *buf_ptr,
1231 					       struct peer_assoc_params *req)
1232 {
1233 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1234 	return buf_ptr + WMI_TLV_HDR_SIZE;
1235 }
1236 #endif /* WLAN_FEATURE_11BE */
1237 
1238 #ifdef WLAN_MLO_MULTI_CHIP
1239 QDF_STATUS mlo_setup_cmd_send_tlv(struct wmi_unified *wmi_handle,
1240 				  struct wmi_mlo_setup_params *param)
1241 {
1242 	QDF_STATUS ret;
1243 	wmi_mlo_setup_cmd_fixed_param *cmd;
1244 	wmi_buf_t buf;
1245 	int32_t len;
1246 	uint8_t *buf_ptr;
1247 	uint32_t *partner_links;
1248 	uint8_t idx;
1249 
1250 	if (param->num_valid_hw_links > MAX_LINK_IN_MLO)
1251 		return QDF_STATUS_E_INVAL;
1252 
1253 	len = sizeof(*cmd) +
1254 		(param->num_valid_hw_links * sizeof(uint32_t)) +
1255 		WMI_TLV_HDR_SIZE;
1256 
1257 	buf = wmi_buf_alloc(wmi_handle, len);
1258 	if (!buf)
1259 		return QDF_STATUS_E_NOMEM;
1260 
1261 	cmd = (wmi_mlo_setup_cmd_fixed_param *)wmi_buf_data(buf);
1262 	WMITLV_SET_HDR(&cmd->tlv_header,
1263 		       WMITLV_TAG_STRUC_wmi_mlo_setup_cmd_fixed_param,
1264 		       WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_setup_cmd_fixed_param));
1265 
1266 	cmd->mld_group_id = param->mld_grp_id;
1267 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1268 								wmi_handle,
1269 								param->pdev_id);
1270 	buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
1271 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1272 		       (sizeof(uint32_t) * param->num_valid_hw_links));
1273 	partner_links = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
1274 	for (idx = 0; idx < param->num_valid_hw_links; idx++)
1275 		partner_links[idx] = param->partner_links[idx];
1276 
1277 	wmi_mtrace(WMI_MLO_SETUP_CMDID, NO_SESSION, 0);
1278 	ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_MLO_SETUP_CMDID);
1279 	if (QDF_IS_STATUS_ERROR(ret)) {
1280 		wmi_err("Failed to send MLO setup command ret = %d", ret);
1281 		wmi_buf_free(buf);
1282 	}
1283 
1284 	return ret;
1285 }
1286 
1287 QDF_STATUS mlo_ready_cmd_send_tlv(struct wmi_unified *wmi_handle,
1288 				  struct wmi_mlo_ready_params *param)
1289 {
1290 	QDF_STATUS ret;
1291 	wmi_mlo_ready_cmd_fixed_param *cmd;
1292 	wmi_buf_t buf;
1293 	int32_t len;
1294 
1295 	len = sizeof(*cmd);
1296 
1297 	buf = wmi_buf_alloc(wmi_handle, len);
1298 	if (!buf)
1299 		return QDF_STATUS_E_NOMEM;
1300 
1301 	cmd = (wmi_mlo_ready_cmd_fixed_param *)wmi_buf_data(buf);
1302 	WMITLV_SET_HDR(&cmd->tlv_header,
1303 		       WMITLV_TAG_STRUC_wmi_mlo_ready_cmd_fixed_param,
1304 		       WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_ready_cmd_fixed_param));
1305 
1306 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1307 								wmi_handle,
1308 								param->pdev_id);
1309 
1310 	wmi_mtrace(WMI_MLO_READY_CMDID, NO_SESSION, 0);
1311 	ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_MLO_READY_CMDID);
1312 	if (QDF_IS_STATUS_ERROR(ret)) {
1313 		wmi_err("Failed to send MLO ready command ret = %d", ret);
1314 		wmi_buf_free(buf);
1315 	}
1316 
1317 	return ret;
1318 }
1319 
1320 QDF_STATUS mlo_teardown_cmd_send_tlv(struct wmi_unified *wmi_handle,
1321 				     struct wmi_mlo_teardown_params *param)
1322 {
1323 	QDF_STATUS ret;
1324 	wmi_mlo_teardown_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_teardown_fixed_param *)wmi_buf_data(buf);
1335 	WMITLV_SET_HDR(&cmd->tlv_header,
1336 		       WMITLV_TAG_STRUC_wmi_mlo_teardown_fixed_param,
1337 		       WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_teardown_fixed_param));
1338 
1339 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1340 								wmi_handle,
1341 								param->pdev_id);
1342 	switch (param->reason) {
1343 	case WMI_MLO_TEARDOWN_REASON_SSR:
1344 		cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON;
1345 		break;
1346 	case WMI_MLO_TEARDOWN_REASON_DOWN:
1347 	default:
1348 		cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON + 1;
1349 		break;
1350 	}
1351 
1352 	wmi_mtrace(WMI_MLO_TEARDOWN_CMDID, NO_SESSION, 0);
1353 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1354 				   WMI_MLO_TEARDOWN_CMDID);
1355 	if (QDF_IS_STATUS_ERROR(ret)) {
1356 		wmi_err("Failed to send MLO Teardown command ret = %d", ret);
1357 		wmi_buf_free(buf);
1358 	}
1359 
1360 	return ret;
1361 }
1362 
1363 QDF_STATUS
1364 extract_mlo_setup_cmpl_event_tlv(struct wmi_unified *wmi_handle,
1365 				 uint8_t *buf,
1366 				 struct wmi_mlo_setup_complete_params *params)
1367 {
1368 	WMI_MLO_SETUP_COMPLETE_EVENTID_param_tlvs *param_buf;
1369 	wmi_mlo_setup_complete_event_fixed_param *ev;
1370 
1371 	param_buf = (WMI_MLO_SETUP_COMPLETE_EVENTID_param_tlvs *)buf;
1372 	if (!param_buf) {
1373 		wmi_err_rl("Param_buf is NULL");
1374 		return QDF_STATUS_E_FAILURE;
1375 	}
1376 	ev = (wmi_mlo_setup_complete_event_fixed_param *)param_buf->fixed_param;
1377 
1378 	params->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
1379 								wmi_handle,
1380 								ev->pdev_id);
1381 	if (!ev->status)
1382 		params->status = WMI_MLO_SETUP_STATUS_SUCCESS;
1383 	else
1384 		params->status = WMI_MLO_SETUP_STATUS_FAILURE;
1385 
1386 	return QDF_STATUS_SUCCESS;
1387 }
1388 
1389 QDF_STATUS
1390 extract_mlo_teardown_cmpl_event_tlv(struct wmi_unified *wmi_handle,
1391 				    uint8_t *buf,
1392 				    struct wmi_mlo_teardown_cmpl_params *params)
1393 {
1394 	WMI_MLO_TEARDOWN_COMPLETE_EVENTID_param_tlvs *param_buf;
1395 	wmi_mlo_teardown_complete_fixed_param *ev;
1396 
1397 	param_buf = (WMI_MLO_TEARDOWN_COMPLETE_EVENTID_param_tlvs *)buf;
1398 	if (!param_buf) {
1399 		wmi_err_rl("Param_buf is NULL");
1400 		return QDF_STATUS_E_FAILURE;
1401 	}
1402 	ev = (wmi_mlo_teardown_complete_fixed_param *)param_buf->fixed_param;
1403 
1404 	params->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
1405 								wmi_handle,
1406 								ev->pdev_id);
1407 	if (!ev->status)
1408 		params->status = WMI_MLO_TEARDOWN_STATUS_SUCCESS;
1409 	else
1410 		params->status = WMI_MLO_TEARDOWN_STATUS_FAILURE;
1411 
1412 	return QDF_STATUS_SUCCESS;
1413 }
1414 
1415 static void wmi_11be_attach_mlo_setup_tlv(wmi_unified_t wmi_handle)
1416 {
1417 	struct wmi_ops *ops = wmi_handle->ops;
1418 
1419 	ops->mlo_setup_cmd_send = mlo_setup_cmd_send_tlv;
1420 	ops->mlo_teardown_cmd_send = mlo_teardown_cmd_send_tlv;
1421 	ops->mlo_ready_cmd_send = mlo_ready_cmd_send_tlv;
1422 	ops->extract_mlo_setup_cmpl_event = extract_mlo_setup_cmpl_event_tlv;
1423 	ops->extract_mlo_teardown_cmpl_event =
1424 					extract_mlo_teardown_cmpl_event_tlv;
1425 }
1426 
1427 #else /*WLAN_MLO_MULTI_CHIP*/
1428 
1429 static void wmi_11be_attach_mlo_setup_tlv(wmi_unified_t wmi_handle)
1430 {}
1431 
1432 #endif /*WLAN_MLO_MULTI_CHIP*/
1433 
1434 /**
1435  * extract_mgmt_rx_ml_cu_params_tlv() - extract MGMT Critical Update params
1436  * from MGMT_RX_EVENT_ID
1437  * @wmi_handle: wmi handle
1438  * @evt_buf: pointer to event buffer
1439  * @cu_params: Pointer to MGMT Critical update parameters
1440  *
1441  * Return: QDF_STATUS_SUCCESS for success or error code
1442  */
1443 static
1444 QDF_STATUS extract_mgmt_rx_ml_cu_params_tlv(wmi_unified_t wmi_handle,
1445 					    void *evt_buf,
1446 					    struct mlo_mgmt_ml_info *cu_params)
1447 {
1448 	WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs;
1449 	wmi_mgmt_ml_info *cu_params_tlv;
1450 	wmi_mgmt_rx_hdr *ev_hdr;
1451 	uint32_t num_bpcc_bufp;
1452 
1453 	param_tlvs = evt_buf;
1454 	if (!param_tlvs) {
1455 		wmi_err(" MGMT RX param_tlvs is NULL");
1456 		return QDF_STATUS_E_INVAL;
1457 	}
1458 
1459 	ev_hdr = param_tlvs->hdr;
1460 	if (!ev_hdr) {
1461 		wmi_err("Rx event is NULL");
1462 		return QDF_STATUS_E_INVAL;
1463 	}
1464 
1465 	if (!cu_params) {
1466 		wmi_debug("MGMT Rx CU params is NULL");
1467 		return QDF_STATUS_E_INVAL;
1468 	}
1469 
1470 	cu_params_tlv = param_tlvs->ml_info;
1471 	if (!cu_params_tlv) {
1472 		wmi_debug("mgmt_ml_info TLV is not sent by FW");
1473 		return QDF_STATUS_E_INVAL;
1474 	}
1475 
1476 	cu_params->cu_vdev_map[0] =
1477 		cu_params_tlv->cu_vdev_map_1 & CU_VDEV_MAP_MASK;
1478 	cu_params->cu_vdev_map[1] =
1479 		(cu_params_tlv->cu_vdev_map_1 >> 16) & CU_VDEV_MAP_MASK;
1480 	cu_params->cu_vdev_map[2] =
1481 		cu_params_tlv->cu_vdev_map_2 & CU_VDEV_MAP_MASK;
1482 	cu_params->cu_vdev_map[3] =
1483 		(cu_params_tlv->cu_vdev_map_2 >> 16) & CU_VDEV_MAP_MASK;
1484 	cu_params->cu_vdev_map[4] =
1485 		cu_params_tlv->cu_vdev_map_3 & CU_VDEV_MAP_MASK;
1486 	cu_params->cu_vdev_map[5] =
1487 		(cu_params_tlv->cu_vdev_map_3 >> 16) & CU_VDEV_MAP_MASK;
1488 
1489 	/* At present MAX_LINKS_SUPPORTED are 6.
1490 	 * cu_vdev_map_4 which required for links
1491 	 * 7 and 8 is unused.
1492 	 */
1493 	num_bpcc_bufp = param_tlvs->num_bpcc_bufp;
1494 	if (param_tlvs->num_bpcc_bufp > sizeof(cu_params->vdev_bpcc)) {
1495 		wmi_err("Invalid num_bpcc_bufp:%u", num_bpcc_bufp);
1496 		return QDF_STATUS_E_INVAL;
1497 	}
1498 	qdf_mem_copy(cu_params->vdev_bpcc, param_tlvs->bpcc_bufp,
1499 		     num_bpcc_bufp);
1500 
1501 	qdf_trace_hex_dump(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
1502 			   param_tlvs->bpcc_bufp, num_bpcc_bufp);
1503 
1504 	return QDF_STATUS_SUCCESS;
1505 }
1506 
1507 void wmi_11be_attach_tlv(wmi_unified_t wmi_handle)
1508 {
1509 	struct wmi_ops *ops = wmi_handle->ops;
1510 
1511 	wmi_11be_attach_mlo_setup_tlv(wmi_handle);
1512 	ops->extract_mlo_link_set_active_resp =
1513 		extract_mlo_link_set_active_resp_tlv;
1514 	ops->send_mlo_link_set_active_cmd =
1515 		send_mlo_link_set_active_cmd_tlv;
1516 #ifdef WLAN_FEATURE_11BE
1517 	ops->send_mlo_peer_tid_to_link_map =
1518 		send_mlo_peer_tid_to_link_map_cmd_tlv;
1519 	ops->send_mlo_vdev_tid_to_link_map =
1520 		send_mlo_vdev_tid_to_link_map_cmd_tlv;
1521 	ops->extract_mlo_vdev_tid_to_link_map_event =
1522 		extract_mlo_vdev_tid_to_link_map_event_tlv;
1523 	ops->extract_mlo_vdev_bcast_tid_to_link_map_event =
1524 		extract_mlo_vdev_bcast_tid_to_link_map_event_tlv;
1525 #endif /* WLAN_FEATURE_11BE */
1526 	ops->extract_mgmt_rx_ml_cu_params =
1527 		extract_mgmt_rx_ml_cu_params_tlv;
1528 	ops->send_mlo_link_removal_cmd = send_mlo_link_removal_cmd_tlv;
1529 	ops->extract_mlo_link_removal_evt_fixed_param =
1530 			extract_mlo_link_removal_evt_fixed_param_tlv;
1531 	ops->extract_mlo_link_removal_tbtt_update =
1532 			extract_mlo_link_removal_tbtt_update_tlv;
1533 	ops->extract_mgmt_rx_mlo_link_removal_info =
1534 			extract_mgmt_rx_mlo_link_removal_info_tlv;
1535 }
1536