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, ¶ms->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