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