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 wmi_info("mlo_flags 0x%x emlsr_support %d ", 112 mlo_params->mlo_flags.mlo_flags, 113 mlo_params->mlo_flags.emlsr_support); 114 115 return buf_ptr + sizeof(wmi_vdev_start_mlo_params); 116 } 117 118 uint8_t *vdev_start_add_ml_partner_links(uint8_t *buf_ptr, 119 struct vdev_start_params *req) 120 { 121 wmi_partner_link_params *ml_partner_link; 122 struct mlo_vdev_start_partner_links *req_partner; 123 uint8_t i; 124 125 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 126 (req->mlo_partner.num_links * 127 sizeof(wmi_partner_link_params))); 128 buf_ptr += sizeof(uint32_t); 129 130 req_partner = &req->mlo_partner; 131 ml_partner_link = (wmi_partner_link_params *)buf_ptr; 132 for (i = 0; i < req->mlo_partner.num_links; i++) { 133 WMITLV_SET_HDR(&ml_partner_link->tlv_header, 134 WMITLV_TAG_STRUC_wmi_partner_link_params, 135 WMITLV_GET_STRUCT_TLVLEN(wmi_partner_link_params)); 136 ml_partner_link->vdev_id = req_partner->partner_info[i].vdev_id; 137 ml_partner_link->hw_link_id = 138 req_partner->partner_info[i].hw_mld_link_id; 139 WMI_CHAR_ARRAY_TO_MAC_ADDR(req_partner->partner_info[i].mac_addr, 140 &ml_partner_link->vdev_macaddr); 141 wmi_info("vdev_id %d hw_link_id %d MAC addr " QDF_MAC_ADDR_FMT, 142 ml_partner_link->vdev_id, 143 ml_partner_link->hw_link_id, 144 QDF_MAC_ADDR_REF(req_partner->partner_info[i].mac_addr)); 145 ml_partner_link++; 146 } 147 148 return buf_ptr + 149 (req->mlo_partner.num_links * 150 sizeof(wmi_partner_link_params)); 151 } 152 153 size_t bcn_tmpl_mlo_param_size(struct beacon_tmpl_params *param) 154 { 155 return WMI_TLV_HDR_SIZE; 156 } 157 158 uint8_t *bcn_tmpl_add_ml_partner_links(uint8_t *buf_ptr, 159 struct beacon_tmpl_params *param) 160 { 161 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 162 return buf_ptr + WMI_TLV_HDR_SIZE; 163 } 164 165 size_t bcn_tmpl_ml_info_size(struct beacon_tmpl_params *param) 166 { 167 return (WMI_TLV_HDR_SIZE + sizeof(wmi_bcn_tmpl_ml_info)); 168 } 169 170 uint8_t *bcn_tmpl_add_ml_info(uint8_t *buf_ptr, 171 struct beacon_tmpl_params *param) 172 { 173 wmi_bcn_tmpl_ml_info *ml_info; 174 175 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 176 sizeof(wmi_bcn_tmpl_ml_info)); 177 buf_ptr += WMI_TLV_HDR_SIZE; 178 179 ml_info = (wmi_bcn_tmpl_ml_info *)buf_ptr; 180 181 WMITLV_SET_HDR(&ml_info->tlv_header, 182 WMITLV_TAG_STRUC_wmi_bcn_tmpl_ml_info, 183 WMITLV_GET_STRUCT_TLVLEN(wmi_bcn_tmpl_ml_info)); 184 185 ml_info->hw_link_id = param->cu_ml_info.hw_link_id; 186 ml_info->cu_vdev_map_cat1_lo = param->cu_ml_info.cu_vdev_map_cat1_lo; 187 ml_info->cu_vdev_map_cat1_hi = param->cu_ml_info.cu_vdev_map_cat1_hi; 188 ml_info->cu_vdev_map_cat2_lo = param->cu_ml_info.cu_vdev_map_cat2_lo; 189 ml_info->cu_vdev_map_cat2_hi = param->cu_ml_info.cu_vdev_map_cat2_hi; 190 191 return buf_ptr + sizeof(wmi_bcn_tmpl_ml_info); 192 } 193 194 size_t prb_resp_tmpl_ml_info_size(struct wmi_probe_resp_params *param) 195 { 196 return (WMI_TLV_HDR_SIZE + sizeof(wmi_prb_resp_tmpl_ml_info)); 197 } 198 199 uint8_t *prb_resp_tmpl_add_ml_info(uint8_t *buf_ptr, 200 struct wmi_probe_resp_params *param) 201 { 202 wmi_prb_resp_tmpl_ml_info *ml_info; 203 204 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 205 sizeof(wmi_prb_resp_tmpl_ml_info)); 206 buf_ptr += WMI_TLV_HDR_SIZE; 207 208 ml_info = (wmi_prb_resp_tmpl_ml_info *)buf_ptr; 209 210 WMITLV_SET_HDR(&ml_info->tlv_header, 211 WMITLV_TAG_STRUC_wmi_prb_resp_tmpl_ml_info, 212 WMITLV_GET_STRUCT_TLVLEN(wmi_prb_resp_tmpl_ml_info)); 213 214 ml_info->hw_link_id = param->cu_ml_info.hw_link_id; 215 ml_info->cu_vdev_map_cat1_lo = param->cu_ml_info.cu_vdev_map_cat1_lo; 216 ml_info->cu_vdev_map_cat1_hi = param->cu_ml_info.cu_vdev_map_cat1_hi; 217 ml_info->cu_vdev_map_cat2_lo = param->cu_ml_info.cu_vdev_map_cat2_lo; 218 ml_info->cu_vdev_map_cat2_hi = param->cu_ml_info.cu_vdev_map_cat2_hi; 219 220 return buf_ptr + sizeof(wmi_prb_resp_tmpl_ml_info); 221 } 222 223 size_t peer_create_mlo_params_size(struct peer_create_params *req) 224 { 225 return sizeof(wmi_peer_create_mlo_params) + WMI_TLV_HDR_SIZE; 226 } 227 228 uint8_t *peer_create_add_mlo_params(uint8_t *buf_ptr, 229 struct peer_create_params *req) 230 { 231 wmi_peer_create_mlo_params *mlo_params; 232 233 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 234 sizeof(wmi_peer_create_mlo_params)); 235 buf_ptr += sizeof(uint32_t); 236 237 mlo_params = (wmi_peer_create_mlo_params *)buf_ptr; 238 WMITLV_SET_HDR(&mlo_params->tlv_header, 239 WMITLV_TAG_STRUC_wmi_peer_create_mlo_params, 240 WMITLV_GET_STRUCT_TLVLEN(wmi_peer_create_mlo_params)); 241 242 mlo_params->mlo_flags.mlo_flags = 0; 243 WMI_MLO_FLAGS_SET_ENABLED(mlo_params->mlo_flags.mlo_flags, 244 req->mlo_enabled); 245 WMI_MLO_FLAGS_SET_BRIDGE_PEER(mlo_params->mlo_flags.mlo_flags, 246 req->mlo_bridge_peer); 247 248 return buf_ptr + sizeof(wmi_peer_create_mlo_params); 249 } 250 251 size_t peer_assoc_mlo_params_size(struct peer_assoc_params *req) 252 { 253 size_t peer_assoc_mlo_size = sizeof(wmi_peer_assoc_mlo_params) + 254 WMI_TLV_HDR_SIZE + 255 ((req->ml_links.num_links) * 256 sizeof(wmi_peer_assoc_mlo_partner_link_params)) + 257 WMI_TLV_HDR_SIZE; 258 259 if (req->is_assoc_vdev) 260 peer_assoc_mlo_size = peer_assoc_mlo_size + 261 sizeof(wmi_peer_assoc_mlo_partner_link_params); 262 263 return peer_assoc_mlo_size; 264 } 265 266 uint8_t *peer_assoc_add_mlo_params(uint8_t *buf_ptr, 267 struct peer_assoc_params *req) 268 { 269 wmi_peer_assoc_mlo_params *mlo_params; 270 271 /* Add WMI peer assoc mlo params */ 272 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 273 sizeof(wmi_peer_assoc_mlo_params)); 274 buf_ptr += sizeof(uint32_t); 275 276 mlo_params = (wmi_peer_assoc_mlo_params *)buf_ptr; 277 WMITLV_SET_HDR(&mlo_params->tlv_header, 278 WMITLV_TAG_STRUC_wmi_peer_assoc_mlo_params, 279 WMITLV_GET_STRUCT_TLVLEN(wmi_peer_assoc_mlo_params)); 280 281 mlo_params->mlo_flags.mlo_flags = 0; 282 WMI_MLO_FLAGS_SET_ENABLED(mlo_params->mlo_flags.mlo_flags, 283 req->mlo_params.mlo_enabled); 284 WMI_MLO_FLAGS_SET_ASSOC_LINK(mlo_params->mlo_flags.mlo_flags, 285 req->mlo_params.mlo_assoc_link); 286 WMI_MLO_FLAGS_SET_PRIMARY_UMAC(mlo_params->mlo_flags.mlo_flags, 287 req->mlo_params.mlo_primary_umac); 288 WMI_MLO_FLAGS_SET_LINK_INDEX_VALID(mlo_params->mlo_flags.mlo_flags, 289 req->mlo_params.mlo_logical_link_index_valid); 290 WMI_MLO_FLAGS_SET_PEER_ID_VALID(mlo_params->mlo_flags.mlo_flags, 291 req->mlo_params.mlo_peer_id_valid); 292 WMI_MLO_FLAGS_SET_BRIDGE_PEER(mlo_params->mlo_flags.mlo_flags, 293 req->mlo_params.mlo_bridge_peer); 294 mlo_params->mlo_flags.emlsr_support = req->mlo_params.emlsr_support; 295 296 mlo_params->mlo_flags.mlo_force_link_inactive = 297 req->mlo_params.mlo_force_link_inactive; 298 299 WMI_CHAR_ARRAY_TO_MAC_ADDR(req->mlo_params.mld_mac, 300 &mlo_params->mld_macaddr); 301 mlo_params->logical_link_index = req->mlo_params.logical_link_index; 302 mlo_params->mld_peer_id = req->mlo_params.ml_peer_id; 303 304 mlo_params->ieee_link_id = req->mlo_params.ieee_link_id; 305 mlo_params->emlsr_trans_timeout_us = req->mlo_params.trans_timeout_us; 306 mlo_params->emlsr_trans_delay_us = req->mlo_params.emlsr_trans_delay_us; 307 mlo_params->emlsr_padding_delay_us = req->mlo_params.emlsr_pad_delay_us; 308 309 mlo_params->msd_dur_subfield = req->mlo_params.medium_sync_duration; 310 mlo_params->msd_ofdm_ed_thr = 311 req->mlo_params.medium_sync_ofdm_ed_thresh; 312 mlo_params->msd_max_num_txops = 313 req->mlo_params.medium_sync_max_txop_num; 314 315 mlo_params->max_num_simultaneous_links = 316 req->mlo_params.max_num_simultaneous_links; 317 mlo_params->mlo_flags.nstr_bitmap_present = 318 req->mlo_params.nstr_bitmap_present; 319 mlo_params->mlo_flags.nstr_bitmap_size = 320 req->mlo_params.nstr_bitmap_size; 321 mlo_params->mlo_flags.mlo_link_switch = 322 req->mlo_params.link_switch_in_progress; 323 mlo_params->nstr_indication_bitmap = 324 req->mlo_params.nstr_indication_bitmap; 325 326 wmi_debug("emlsr_support %d mlo_flags 0x%x logical_link_index %d mld_peer_id %d ieee_link_id %d " 327 "emlsr_trans_timeout_us %d emlsr_trans_delay_us %d " 328 "emlsr_padding_delay_us %d msd_dur_subfield %d msd_ofdm_ed_thr %d msd_max_num_txops %d " 329 "max_num_simultaneous_links %d nstr_bitmap_present %d nstr_bitmap_size %d " 330 "mlo_link_switch %d " 331 "nstr_indication_bitmap 0x%x MLD addr " QDF_MAC_ADDR_FMT, 332 mlo_params->mlo_flags.emlsr_support, 333 mlo_params->mlo_flags.mlo_flags, 334 mlo_params->logical_link_index, 335 mlo_params->mld_peer_id, mlo_params->ieee_link_id, 336 mlo_params->emlsr_trans_timeout_us, 337 mlo_params->emlsr_trans_delay_us, 338 mlo_params->emlsr_padding_delay_us, 339 mlo_params->msd_dur_subfield, mlo_params->msd_ofdm_ed_thr, 340 mlo_params->msd_max_num_txops, mlo_params->max_num_simultaneous_links, 341 mlo_params->mlo_flags.nstr_bitmap_present, 342 mlo_params->mlo_flags.nstr_bitmap_size, 343 mlo_params->mlo_flags.mlo_link_switch, 344 mlo_params->nstr_indication_bitmap, 345 req->mlo_params.mld_mac); 346 347 return buf_ptr + sizeof(wmi_peer_assoc_mlo_params); 348 } 349 350 static inline void wmi_copy_chan_info(wmi_channel *dst_chan, 351 struct wlan_channel *src_chan) 352 { 353 WMI_HOST_WLAN_PHY_MODE fw_phy_mode; 354 355 dst_chan->mhz = src_chan->ch_freq; 356 dst_chan->band_center_freq1 = src_chan->ch_cfreq1; 357 dst_chan->band_center_freq2 = src_chan->ch_cfreq2; 358 fw_phy_mode = wmi_host_to_fw_phymode(src_chan->ch_phymode); 359 WMI_SET_CHANNEL_MODE(dst_chan, fw_phy_mode); 360 } 361 362 static inline void 363 peer_assoc_update_assoc_link_info(uint8_t **buf_ptr, 364 struct peer_assoc_params *req) 365 { 366 wmi_peer_assoc_mlo_partner_link_params *ml_partner_link; 367 368 if (!req->is_assoc_vdev) 369 return; 370 371 ml_partner_link = (wmi_peer_assoc_mlo_partner_link_params *)(*buf_ptr); 372 373 /* Fill Assoc link info */ 374 WMITLV_SET_HDR(&ml_partner_link->tlv_header, 375 WMITLV_TAG_STRUC_wmi_peer_assoc_mlo_partner_link_params, 376 WMITLV_GET_STRUCT_TLVLEN(wmi_peer_assoc_mlo_partner_link_params)); 377 ml_partner_link->vdev_id = req->mlo_params.vdev_id; 378 ml_partner_link->ieee_link_id = req->mlo_params.ieee_link_id; 379 WMI_CHAR_ARRAY_TO_MAC_ADDR(req->mlo_params.bssid.bytes, 380 &ml_partner_link->bss_id); 381 WMI_CHAR_ARRAY_TO_MAC_ADDR(req->mlo_params.mac_addr.bytes, 382 &ml_partner_link->self_mac); 383 wmi_copy_chan_info(&ml_partner_link->wmi_chan, &req->mlo_params.chan); 384 385 wmi_debug("Send Link info with link_id: %d vdev_id: %d AP link addr: "QDF_MAC_ADDR_FMT ", STA addr: "QDF_MAC_ADDR_FMT, 386 ml_partner_link->ieee_link_id, ml_partner_link->vdev_id, 387 QDF_MAC_ADDR_REF(req->mlo_params.bssid.bytes), 388 QDF_MAC_ADDR_REF(req->mlo_params.mac_addr.bytes)); 389 390 ml_partner_link++; 391 *buf_ptr = (uint8_t *)ml_partner_link; 392 } 393 394 uint8_t *peer_assoc_add_ml_partner_links(uint8_t *buf_ptr, 395 struct peer_assoc_params *req) 396 { 397 wmi_peer_assoc_mlo_partner_link_params *ml_partner_link; 398 struct ml_partner_info *partner_info; 399 uint8_t i; 400 401 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 402 ((req->ml_links.num_links + req->is_assoc_vdev) * 403 sizeof(wmi_peer_assoc_mlo_partner_link_params))); 404 buf_ptr += sizeof(uint32_t); 405 406 ml_partner_link = (wmi_peer_assoc_mlo_partner_link_params *)buf_ptr; 407 peer_assoc_update_assoc_link_info((uint8_t **)&ml_partner_link, req); 408 partner_info = req->ml_links.partner_info; 409 for (i = 0; i < req->ml_links.num_links; i++) { 410 WMITLV_SET_HDR(&ml_partner_link->tlv_header, 411 WMITLV_TAG_STRUC_wmi_peer_assoc_mlo_partner_link_params, 412 WMITLV_GET_STRUCT_TLVLEN(wmi_peer_assoc_mlo_partner_link_params)); 413 ml_partner_link->vdev_id = partner_info[i].vdev_id; 414 ml_partner_link->hw_mld_link_id = partner_info[i].hw_mld_link_id; 415 WMI_MLO_FLAGS_SET_ENABLED(ml_partner_link->mlo_flags.mlo_flags, 416 partner_info[i].mlo_enabled); 417 WMI_MLO_FLAGS_SET_ASSOC_LINK(ml_partner_link->mlo_flags.mlo_flags, 418 partner_info[i].mlo_assoc_link); 419 WMI_MLO_FLAGS_SET_PRIMARY_UMAC(ml_partner_link->mlo_flags.mlo_flags, 420 partner_info[i].mlo_primary_umac); 421 WMI_MLO_FLAGS_SET_LINK_INDEX_VALID(ml_partner_link->mlo_flags.mlo_flags, 422 partner_info[i].mlo_logical_link_index_valid); 423 WMI_MLO_FLAGS_SET_BRIDGE_PEER(ml_partner_link->mlo_flags.mlo_flags, 424 partner_info[i].mlo_bridge_peer); 425 ml_partner_link->mlo_flags.emlsr_support = partner_info[i].emlsr_support; 426 ml_partner_link->logical_link_index = partner_info[i].logical_link_index; 427 ml_partner_link->ieee_link_id = partner_info[i].link_id; 428 WMI_CHAR_ARRAY_TO_MAC_ADDR(partner_info[i].bssid.bytes, 429 &ml_partner_link->bss_id); 430 WMI_CHAR_ARRAY_TO_MAC_ADDR(partner_info[i].mac_addr.bytes, 431 &ml_partner_link->self_mac); 432 433 wmi_debug("Send Link info with link_id: %d vdev_id: %d AP link addr: "QDF_MAC_ADDR_FMT ", STA addr: "QDF_MAC_ADDR_FMT, 434 ml_partner_link->ieee_link_id, 435 ml_partner_link->vdev_id, 436 QDF_MAC_ADDR_REF(partner_info[i].bssid.bytes), 437 QDF_MAC_ADDR_REF(partner_info[i].mac_addr.bytes)); 438 wmi_copy_chan_info(&ml_partner_link->wmi_chan, 439 &partner_info[i].chan); 440 441 ml_partner_link++; 442 } 443 444 return buf_ptr + 445 ((req->ml_links.num_links + req->is_assoc_vdev) * 446 sizeof(wmi_peer_assoc_mlo_partner_link_params)); 447 } 448 449 size_t peer_delete_mlo_params_size(struct peer_delete_cmd_params *req) 450 { 451 if (!req->hw_link_id_bitmap) 452 return WMI_TLV_HDR_SIZE; 453 454 return sizeof(wmi_peer_delete_mlo_params) + WMI_TLV_HDR_SIZE; 455 } 456 457 uint8_t *peer_delete_add_mlo_params(uint8_t *buf_ptr, 458 struct peer_delete_cmd_params *req) 459 { 460 wmi_peer_delete_mlo_params *mlo_params; 461 462 if (!req->hw_link_id_bitmap) { 463 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 464 return buf_ptr + WMI_TLV_HDR_SIZE; 465 } 466 467 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 468 sizeof(wmi_peer_delete_mlo_params)); 469 buf_ptr += sizeof(uint32_t); 470 471 mlo_params = (wmi_peer_delete_mlo_params *)buf_ptr; 472 WMITLV_SET_HDR(&mlo_params->tlv_header, 473 WMITLV_TAG_STRUC_wmi_peer_delete_mlo_params, 474 WMITLV_GET_STRUCT_TLVLEN(wmi_peer_delete_mlo_params)); 475 mlo_params->mlo_hw_link_id_bitmap = req->hw_link_id_bitmap; 476 return buf_ptr + sizeof(wmi_peer_delete_mlo_params); 477 } 478 479 /** 480 * force_mode_host_to_fw() - translate force mode for MLO link set active 481 * command 482 * @host_mode: force mode defined by host 483 * @fw_mode: buffer to store force mode defined by FW 484 * 485 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL otherwise 486 */ 487 static inline QDF_STATUS 488 force_mode_host_to_fw(enum mlo_link_force_mode host_mode, 489 WMI_MLO_LINK_FORCE_MODE *fw_mode) 490 { 491 switch (host_mode) { 492 case MLO_LINK_FORCE_MODE_ACTIVE: 493 *fw_mode = WMI_MLO_LINK_FORCE_ACTIVE; 494 break; 495 case MLO_LINK_FORCE_MODE_INACTIVE: 496 *fw_mode = WMI_MLO_LINK_FORCE_INACTIVE; 497 break; 498 case MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE: 499 *fw_mode = WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE; 500 break; 501 case MLO_LINK_FORCE_MODE_ACTIVE_NUM: 502 *fw_mode = WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM; 503 break; 504 case MLO_LINK_FORCE_MODE_INACTIVE_NUM: 505 *fw_mode = WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM; 506 break; 507 case MLO_LINK_FORCE_MODE_NO_FORCE: 508 *fw_mode = WMI_MLO_LINK_NO_FORCE; 509 break; 510 default: 511 wmi_err("Invalid force mode: %d", host_mode); 512 return QDF_STATUS_E_INVAL; 513 } 514 515 return QDF_STATUS_SUCCESS; 516 } 517 518 /** 519 * force_reason_host_to_fw() - translate force reason for MLO link set active 520 * command 521 * @host_reason: force reason defined by host 522 * @fw_reason: buffer to store force reason defined by FW 523 * 524 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL otherwise 525 */ 526 static inline QDF_STATUS 527 force_reason_host_to_fw(enum mlo_link_force_reason host_reason, 528 WMI_MLO_LINK_FORCE_REASON *fw_reason) 529 { 530 switch (host_reason) { 531 case MLO_LINK_FORCE_REASON_CONNECT: 532 *fw_reason = WMI_MLO_LINK_FORCE_REASON_NEW_CONNECT; 533 break; 534 case MLO_LINK_FORCE_REASON_DISCONNECT: 535 *fw_reason = WMI_MLO_LINK_FORCE_REASON_NEW_DISCONNECT; 536 break; 537 case MLO_LINK_FORCE_REASON_TDLS: 538 *fw_reason = WMI_MLO_LINK_FORCE_REASON_TDLS; 539 break; 540 case MLO_LINK_FORCE_REASON_LINK_REMOVAL: 541 *fw_reason = WMI_MLO_LINK_FORCE_REASON_LINK_REMOVAL; 542 break; 543 default: 544 wmi_err("Invalid force reason: %d", host_reason); 545 return QDF_STATUS_E_INVAL; 546 } 547 548 return QDF_STATUS_SUCCESS; 549 } 550 551 /** 552 * send_mlo_link_set_active_id_cmd_tlv() - send mlo link set active command 553 * by link id bitmap 554 * @wmi_handle: wmi handle 555 * @param: Pointer to mlo link set active param 556 * 557 * This API will populate link bitmap for corresponding force mode and 558 * send command to target. 559 * Previous API send_mlo_link_set_active_cmd_tlv can only handle vdev 560 * bitmap, if some associated links have no vdev attached, we have to use 561 * this API to do link force active/inactive. 562 * Note: no vdev associated links can be "non forced" state, so that target 563 * can repurpose vdev to such link. 564 * If link with no vdev attached is forced inactive for such concurrency 565 * reason, target will not switch to such link. 566 * 567 * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error 568 */ 569 static QDF_STATUS 570 send_mlo_link_set_active_id_cmd_tlv(wmi_unified_t wmi_handle, 571 struct mlo_link_set_active_param *param) 572 { 573 QDF_STATUS status; 574 wmi_mlo_link_set_active_cmd_fixed_param *cmd; 575 wmi_mlo_set_active_link_number_param *link_num_param; 576 uint32_t *link_bitmap; 577 uint32_t num_link_num_param = 0, num_link_bitmap = 0, tlv_len; 578 uint32_t num_inactive_link_bitmap = 0; 579 wmi_buf_t buf; 580 uint8_t *buf_ptr; 581 uint32_t len; 582 WMITLV_TAG_ID tag_id; 583 WMI_MLO_LINK_FORCE_MODE force_mode; 584 WMI_MLO_LINK_FORCE_REASON force_reason; 585 586 status = force_mode_host_to_fw(param->force_mode, &force_mode); 587 if (QDF_IS_STATUS_ERROR(status)) 588 return QDF_STATUS_E_INVAL; 589 590 status = force_reason_host_to_fw(param->reason, &force_reason); 591 if (QDF_IS_STATUS_ERROR(status)) 592 return QDF_STATUS_E_INVAL; 593 594 switch (force_mode) { 595 case WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM: 596 case WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM: 597 num_link_num_param = 1; 598 fallthrough; 599 case WMI_MLO_LINK_FORCE_ACTIVE: 600 case WMI_MLO_LINK_FORCE_INACTIVE: 601 case WMI_MLO_LINK_NO_FORCE: 602 num_link_bitmap = 1; 603 break; 604 case WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE: 605 num_link_bitmap = 1; 606 num_inactive_link_bitmap = 1; 607 break; 608 default: 609 wmi_err("Invalid force reason: %d", force_mode); 610 return QDF_STATUS_E_INVAL; 611 } 612 613 len = sizeof(*cmd) + 614 WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + 615 WMI_TLV_HDR_SIZE + sizeof(*link_num_param) * num_link_num_param + 616 WMI_TLV_HDR_SIZE + sizeof(*link_bitmap) * num_link_bitmap; 617 if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE) 618 len += WMI_TLV_HDR_SIZE + 619 sizeof(*link_bitmap) * num_inactive_link_bitmap; 620 621 buf = wmi_buf_alloc(wmi_handle, len); 622 if (!buf) 623 return QDF_STATUS_E_NOMEM; 624 625 buf_ptr = (uint8_t *)wmi_buf_data(buf); 626 cmd = (wmi_mlo_link_set_active_cmd_fixed_param *)buf_ptr; 627 tlv_len = WMITLV_GET_STRUCT_TLVLEN 628 (wmi_mlo_link_set_active_cmd_fixed_param); 629 630 tag_id = WMITLV_TAG_STRUC_wmi_mlo_link_set_active_cmd_fixed_param; 631 WMITLV_SET_HDR(&cmd->tlv_header, tag_id, tlv_len); 632 cmd->force_mode = force_mode; 633 cmd->reason = force_reason; 634 cmd->use_ieee_link_id_bitmap = 1; 635 WMI_CHAR_ARRAY_TO_MAC_ADDR(param->force_cmd.ap_mld_mac_addr.bytes, 636 &cmd->ap_mld_mac_addr); 637 if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE) { 638 cmd->ctrl_flags.overwrite_force_active_bitmap = 639 param->control_flags.overwrite_force_active_bitmap; 640 } else if (force_mode == WMI_MLO_LINK_FORCE_INACTIVE) { 641 cmd->ctrl_flags.overwrite_force_inactive_bitmap = 642 param->control_flags.overwrite_force_inactive_bitmap; 643 } else if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE) { 644 cmd->ctrl_flags.overwrite_force_active_bitmap = 645 param->control_flags.overwrite_force_active_bitmap; 646 cmd->ctrl_flags.overwrite_force_inactive_bitmap = 647 param->control_flags.overwrite_force_inactive_bitmap; 648 } else { 649 cmd->ctrl_flags.dynamic_force_link_num = 650 param->control_flags.dynamic_force_link_num; 651 } 652 653 wmi_debug("mode %d reason %d num_link_num_param %d num_link_bitmap %d num_inactive %d overwrite %d %d %d", 654 cmd->force_mode, cmd->reason, num_link_num_param, 655 num_link_bitmap, num_inactive_link_bitmap, 656 cmd->ctrl_flags.overwrite_force_active_bitmap, 657 cmd->ctrl_flags.overwrite_force_inactive_bitmap, 658 cmd->ctrl_flags.dynamic_force_link_num); 659 wmi_debug("ap mld mac addr: "QDF_MAC_ADDR_FMT, 660 QDF_MAC_ADDR_REF(param->force_cmd.ap_mld_mac_addr.bytes)); 661 662 buf_ptr += sizeof(*cmd); 663 664 /* set num of link tlv */ 665 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 666 sizeof(*link_num_param) * num_link_num_param); 667 buf_ptr += WMI_TLV_HDR_SIZE; 668 669 if (num_link_num_param) { 670 link_num_param = 671 (wmi_mlo_set_active_link_number_param *)buf_ptr; 672 tlv_len = WMITLV_GET_STRUCT_TLVLEN 673 (wmi_mlo_set_active_link_number_param); 674 675 WMITLV_SET_HDR(&link_num_param->tlv_header, 0, tlv_len); 676 link_num_param->num_of_link = param->force_cmd.link_num; 677 wmi_debug("entry[0]: num_of_link %d", 678 link_num_param->num_of_link); 679 680 buf_ptr += sizeof(*link_num_param) * 1; 681 } 682 /* add empty vdev bitmap tlv */ 683 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0); 684 buf_ptr += WMI_TLV_HDR_SIZE; 685 /* add empty vdev bitmap2 tlv */ 686 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0); 687 buf_ptr += WMI_TLV_HDR_SIZE; 688 689 /* add link bitmap tlv */ 690 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 691 sizeof(*link_bitmap) * num_link_bitmap); 692 buf_ptr += WMI_TLV_HDR_SIZE; 693 694 if (num_link_bitmap) { 695 link_bitmap = (A_UINT32 *)(buf_ptr); 696 697 link_bitmap[0] = param->force_cmd.ieee_link_id_bitmap; 698 wmi_debug("entry[0]: link_bitmap 0x%x ", link_bitmap[0]); 699 700 buf_ptr += sizeof(*link_bitmap) * 1; 701 } 702 /* add link bitmap2 tlv */ 703 if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE) { 704 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 705 sizeof(*link_bitmap) * 706 num_inactive_link_bitmap); 707 buf_ptr += WMI_TLV_HDR_SIZE; 708 709 if (num_inactive_link_bitmap) { 710 link_bitmap = (A_UINT32 *)(buf_ptr); 711 link_bitmap[0] = param->force_cmd.ieee_link_id_bitmap2; 712 wmi_debug("entry[0]: link_bitmap2 0x%x ", 713 link_bitmap[0]); 714 715 buf_ptr += sizeof(*link_bitmap) * 1; 716 } 717 } 718 719 wmi_mtrace(WMI_MLO_LINK_SET_ACTIVE_CMDID, 0, cmd->force_mode); 720 status = wmi_unified_cmd_send(wmi_handle, buf, len, 721 WMI_MLO_LINK_SET_ACTIVE_CMDID); 722 if (QDF_IS_STATUS_ERROR(status)) { 723 wmi_err("Failed to send MLO link set active command to FW: %d", 724 status); 725 wmi_buf_free(buf); 726 } 727 728 return status; 729 } 730 731 /** 732 * send_mlo_link_set_active_cmd_tlv() - send mlo link set active command 733 * @wmi_handle: wmi handle 734 * @param: Pointer to mlo link set active param 735 * 736 * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error 737 */ 738 static QDF_STATUS 739 send_mlo_link_set_active_cmd_tlv(wmi_unified_t wmi_handle, 740 struct mlo_link_set_active_param *param) 741 { 742 QDF_STATUS status; 743 wmi_mlo_link_set_active_cmd_fixed_param *cmd; 744 wmi_mlo_set_active_link_number_param *link_num_param; 745 uint32_t *vdev_bitmap; 746 uint32_t num_link_num_param = 0, num_vdev_bitmap = 0, tlv_len; 747 uint32_t num_inactive_vdev_bitmap = 0; 748 wmi_buf_t buf; 749 uint8_t *buf_ptr; 750 uint32_t len; 751 int i; 752 WMITLV_TAG_ID tag_id; 753 WMI_MLO_LINK_FORCE_MODE force_mode; 754 WMI_MLO_LINK_FORCE_REASON force_reason; 755 756 /* If use_ieee_link_id = true, use new API 757 * send_mlo_link_set_active_id_cmd_tlv to fill link bitamp 758 * to wmi buffer. 759 * And target will indicate event with same flag set to true 760 * to indicate link bitmap included in the event. 761 */ 762 if (param->use_ieee_link_id) 763 return send_mlo_link_set_active_id_cmd_tlv(wmi_handle, 764 param); 765 766 if (!param->num_vdev_bitmap && !param->num_link_entry) { 767 wmi_err("No entry is provided vdev bit map %d link entry %d", 768 param->num_vdev_bitmap, 769 param->num_link_entry); 770 return QDF_STATUS_E_INVAL; 771 } 772 773 status = force_mode_host_to_fw(param->force_mode, &force_mode); 774 if (QDF_IS_STATUS_ERROR(status)) 775 return QDF_STATUS_E_INVAL; 776 777 status = force_reason_host_to_fw(param->reason, &force_reason); 778 if (QDF_IS_STATUS_ERROR(status)) 779 return QDF_STATUS_E_INVAL; 780 781 switch (force_mode) { 782 case WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM: 783 case WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM: 784 num_link_num_param = param->num_link_entry; 785 fallthrough; 786 case WMI_MLO_LINK_FORCE_ACTIVE: 787 case WMI_MLO_LINK_FORCE_INACTIVE: 788 case WMI_MLO_LINK_NO_FORCE: 789 num_vdev_bitmap = param->num_vdev_bitmap; 790 break; 791 case WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE: 792 num_vdev_bitmap = param->num_vdev_bitmap; 793 num_inactive_vdev_bitmap = param->num_inactive_vdev_bitmap; 794 break; 795 default: 796 wmi_err("Invalid force reason: %d", force_mode); 797 return QDF_STATUS_E_INVAL; 798 } 799 800 len = sizeof(*cmd) + 801 WMI_TLV_HDR_SIZE + sizeof(*link_num_param) * num_link_num_param + 802 WMI_TLV_HDR_SIZE + sizeof(*vdev_bitmap) * num_vdev_bitmap; 803 if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE) 804 len += WMI_TLV_HDR_SIZE + 805 sizeof(*vdev_bitmap) * num_inactive_vdev_bitmap; 806 807 buf = wmi_buf_alloc(wmi_handle, len); 808 if (!buf) 809 return QDF_STATUS_E_NOMEM; 810 811 buf_ptr = (uint8_t *)wmi_buf_data(buf); 812 cmd = (wmi_mlo_link_set_active_cmd_fixed_param *)buf_ptr; 813 tlv_len = WMITLV_GET_STRUCT_TLVLEN 814 (wmi_mlo_link_set_active_cmd_fixed_param); 815 816 tag_id = WMITLV_TAG_STRUC_wmi_mlo_link_set_active_cmd_fixed_param; 817 WMITLV_SET_HDR(&cmd->tlv_header, tag_id, tlv_len); 818 cmd->force_mode = force_mode; 819 cmd->reason = force_reason; 820 wmi_debug("mode %d reason %d num_link_num_param %d num_vdev_bitmap %d inactive %d", 821 cmd->force_mode, cmd->reason, num_link_num_param, 822 num_vdev_bitmap, num_inactive_vdev_bitmap); 823 buf_ptr += sizeof(*cmd); 824 825 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 826 sizeof(*link_num_param) * num_link_num_param); 827 buf_ptr += WMI_TLV_HDR_SIZE; 828 829 if (num_link_num_param) { 830 cmd->ctrl_flags.dynamic_force_link_num = 831 param->control_flags.dynamic_force_link_num; 832 link_num_param = 833 (wmi_mlo_set_active_link_number_param *)buf_ptr; 834 tlv_len = WMITLV_GET_STRUCT_TLVLEN 835 (wmi_mlo_set_active_link_number_param); 836 for (i = 0; i < num_link_num_param; i++) { 837 WMITLV_SET_HDR(&link_num_param->tlv_header, 0, tlv_len); 838 link_num_param->num_of_link = 839 param->link_num[i].num_of_link; 840 link_num_param->vdev_type = 841 param->link_num[i].vdev_type; 842 link_num_param->vdev_subtype = 843 param->link_num[i].vdev_subtype; 844 link_num_param->home_freq = 845 param->link_num[i].home_freq; 846 wmi_debug("entry[%d]: num_of_link %d vdev type %d subtype %d freq %d, control_flags:%d", 847 i, link_num_param->num_of_link, 848 link_num_param->vdev_type, 849 link_num_param->vdev_subtype, 850 link_num_param->home_freq, 851 cmd->ctrl_flags.control_flags); 852 link_num_param++; 853 } 854 855 buf_ptr += sizeof(*link_num_param) * num_link_num_param; 856 } 857 858 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 859 sizeof(*vdev_bitmap) * num_vdev_bitmap); 860 buf_ptr += WMI_TLV_HDR_SIZE; 861 862 if (num_vdev_bitmap) { 863 vdev_bitmap = (A_UINT32 *)(buf_ptr); 864 for (i = 0; i < num_vdev_bitmap; i++) { 865 vdev_bitmap[i] = param->vdev_bitmap[i]; 866 wmi_debug("entry[%d]: vdev_id_bitmap 0x%x ", 867 i, vdev_bitmap[i]); 868 } 869 870 buf_ptr += sizeof(*vdev_bitmap) * num_vdev_bitmap; 871 } 872 if (force_mode == WMI_MLO_LINK_FORCE_ACTIVE_INACTIVE) { 873 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 874 sizeof(*vdev_bitmap) * 875 num_inactive_vdev_bitmap); 876 buf_ptr += WMI_TLV_HDR_SIZE; 877 878 if (num_inactive_vdev_bitmap) { 879 vdev_bitmap = (A_UINT32 *)(buf_ptr); 880 for (i = 0; i < num_inactive_vdev_bitmap; i++) { 881 vdev_bitmap[i] = 882 param->inactive_vdev_bitmap[i]; 883 wmi_debug("entry[%d]: inactive_vdev_id_bitmap 0x%x ", 884 i, vdev_bitmap[i]); 885 } 886 887 buf_ptr += sizeof(*vdev_bitmap) * 888 num_inactive_vdev_bitmap; 889 } 890 } 891 892 wmi_mtrace(WMI_MLO_LINK_SET_ACTIVE_CMDID, 0, cmd->force_mode); 893 status = wmi_unified_cmd_send(wmi_handle, buf, len, 894 WMI_MLO_LINK_SET_ACTIVE_CMDID); 895 if (QDF_IS_STATUS_ERROR(status)) { 896 wmi_err("Failed to send MLO link set active command to FW: %d", 897 status); 898 wmi_buf_free(buf); 899 } 900 901 return status; 902 } 903 904 /** 905 * extract_mlo_link_set_active_resp_tlv() - extract mlo link set active resp 906 * from event 907 * @wmi_handle: wmi handle 908 * @evt_buf: pointer to event buffer 909 * @resp: Pointer to hold mlo link set active resp 910 * 911 * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error 912 */ 913 static QDF_STATUS 914 extract_mlo_link_set_active_resp_tlv(wmi_unified_t wmi_handle, void *evt_buf, 915 struct mlo_link_set_active_resp *resp) 916 { 917 wmi_mlo_link_set_active_resp_event_fixed_param *evt; 918 WMI_MLO_LINK_SET_ACTIVE_RESP_EVENTID_param_tlvs *param_buf; 919 uint32_t entry_num, *bitmap; 920 int i; 921 922 param_buf = evt_buf; 923 if (!param_buf || !resp) { 924 wmi_err("Invalid param"); 925 return QDF_STATUS_E_INVAL; 926 } 927 928 evt = param_buf->fixed_param; 929 resp->status = evt->status; 930 WMI_MAC_ADDR_TO_CHAR_ARRAY(&evt->ap_mld_mac_addr, 931 resp->ap_mld_mac_addr.bytes); 932 wmi_debug("status: %u use linkid %d ap mld:"QDF_MAC_ADDR_FMT, 933 resp->status, 934 evt->use_ieee_link_id_bitmap, 935 QDF_MAC_ADDR_REF(resp->ap_mld_mac_addr.bytes)); 936 937 bitmap = param_buf->current_active_ieee_link_id_bitmap; 938 if (bitmap && 939 param_buf->num_current_active_ieee_link_id_bitmap > 0) 940 resp->curr_active_linkid_bitmap = bitmap[0]; 941 bitmap = param_buf->current_inactive_ieee_link_id_bitmap; 942 if (bitmap && 943 param_buf->num_current_inactive_ieee_link_id_bitmap > 0) 944 resp->curr_inactive_linkid_bitmap = bitmap[0]; 945 wmi_debug("curr active links: 0x%x inactive links: 0x%x num: %x %x", 946 resp->curr_active_linkid_bitmap, 947 resp->curr_inactive_linkid_bitmap, 948 param_buf->num_current_active_ieee_link_id_bitmap, 949 param_buf->num_current_inactive_ieee_link_id_bitmap); 950 951 if (evt->use_ieee_link_id_bitmap) { 952 bitmap = param_buf->force_active_ieee_link_id_bitmap; 953 if (bitmap && 954 param_buf->num_force_active_ieee_link_id_bitmap > 0) 955 resp->active_linkid_bitmap = bitmap[0]; 956 957 bitmap = param_buf->force_inactive_ieee_link_id_bitmap; 958 if (bitmap && 959 param_buf->num_force_inactive_ieee_link_id_bitmap > 0) 960 resp->inactive_linkid_bitmap = bitmap[0]; 961 resp->use_ieee_link_id = true; 962 wmi_debug("forced active links: 0x%x inactive links: 0x%x num: %x %x", 963 resp->active_linkid_bitmap, 964 resp->inactive_linkid_bitmap, 965 param_buf->num_force_active_ieee_link_id_bitmap, 966 param_buf->num_force_inactive_ieee_link_id_bitmap); 967 return QDF_STATUS_SUCCESS; 968 } 969 970 bitmap = param_buf->force_active_vdev_bitmap; 971 entry_num = qdf_min(param_buf->num_force_active_vdev_bitmap, 972 (uint32_t)MLO_VDEV_BITMAP_SZ); 973 resp->active_sz = entry_num; 974 for (i = 0; i < entry_num; i++) { 975 resp->active[i] = bitmap[i]; 976 wmi_debug("vdev active[%d]: 0x%x", i, resp->active[i]); 977 } 978 979 bitmap = param_buf->force_inactive_vdev_bitmap; 980 entry_num = qdf_min(param_buf->num_force_inactive_vdev_bitmap, 981 (uint32_t)MLO_VDEV_BITMAP_SZ); 982 resp->inactive_sz = entry_num; 983 for (i = 0; i < entry_num; i++) { 984 resp->inactive[i] = bitmap[i]; 985 wmi_debug("vdev inactive[%d]: 0x%x", i, resp->inactive[i]); 986 } 987 988 return QDF_STATUS_SUCCESS; 989 } 990 991 /** 992 * send_mlo_link_removal_cmd_tlv() - Send WMI command for MLO link removal 993 * @wmi_handle: wmi handle 994 * @params: MLO link removal command parameters 995 * 996 * Return: QDF_STATUS_SUCCESS of operation 997 */ 998 static QDF_STATUS send_mlo_link_removal_cmd_tlv( 999 wmi_unified_t wmi_handle, 1000 const struct mlo_link_removal_cmd_params *params) 1001 { 1002 wmi_mlo_link_removal_cmd_fixed_param *fixed_params; 1003 wmi_buf_t buf; 1004 uint8_t *buf_ptr; 1005 uint32_t buf_len = 0; 1006 uint32_t ie_len_aligned = 0; 1007 QDF_STATUS ret; 1008 1009 if (!params) { 1010 wmi_err("command params is NULL"); 1011 return QDF_STATUS_E_NULL_VALUE; 1012 } 1013 1014 ie_len_aligned = roundup(params->reconfig_ml_ie_size, sizeof(uint32_t)); 1015 1016 buf_len = sizeof(wmi_mlo_link_removal_cmd_fixed_param) + 1017 WMI_TLV_HDR_SIZE + ie_len_aligned; 1018 1019 buf = wmi_buf_alloc(wmi_handle, buf_len); 1020 if (!buf) { 1021 wmi_err("wmi buf alloc failed for link removal cmd: psoc (%pK) vdev(%u)", 1022 wmi_handle->soc->wmi_psoc, params->vdev_id); 1023 return QDF_STATUS_E_NOMEM; 1024 } 1025 1026 buf_ptr = (uint8_t *)wmi_buf_data(buf); 1027 1028 /* Populate fixed params TLV */ 1029 fixed_params = (wmi_mlo_link_removal_cmd_fixed_param *)buf_ptr; 1030 WMITLV_SET_HDR(&fixed_params->tlv_header, 1031 WMITLV_TAG_STRUC_wmi_mlo_link_removal_cmd_fixed_param, 1032 WMITLV_GET_STRUCT_TLVLEN( 1033 wmi_mlo_link_removal_cmd_fixed_param)); 1034 fixed_params->vdev_id = params->vdev_id; 1035 fixed_params->reconfig_ml_ie_num_bytes_valid = 1036 params->reconfig_ml_ie_size; 1037 buf_ptr += sizeof(*fixed_params); 1038 1039 /* Populate the array of bytes TLV */ 1040 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned); 1041 buf_ptr += WMI_TLV_HDR_SIZE; 1042 1043 /* Populate ML reconfiguration element in raw bytes */ 1044 qdf_mem_copy(buf_ptr, params->reconfig_ml_ie, 1045 params->reconfig_ml_ie_size); 1046 1047 wmi_mtrace(WMI_MLO_LINK_REMOVAL_CMDID, fixed_params->vdev_id, 0); 1048 ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len, 1049 WMI_MLO_LINK_REMOVAL_CMDID); 1050 if (QDF_IS_STATUS_ERROR(ret)) { 1051 wmi_err("Failed to send MLO link removal cmd: psoc (%pK) vdev(%u)", 1052 wmi_handle->soc->wmi_psoc, params->vdev_id); 1053 wmi_buf_free(buf); 1054 } 1055 1056 return ret; 1057 } 1058 1059 /** 1060 * send_mlo_vdev_pause_cmd_tlv() - Send WMI command for MLO vdev pause 1061 * @wmi_handle: wmi handle 1062 * @info: MLO vdev pause information 1063 * 1064 * Return: QDF_STATUS of operation 1065 */ 1066 static QDF_STATUS send_mlo_vdev_pause_cmd_tlv(wmi_unified_t wmi_handle, 1067 struct mlo_vdev_pause *info) 1068 { 1069 wmi_vdev_pause_cmd_fixed_param *fixed_params; 1070 wmi_buf_t buf; 1071 uint32_t buf_len = 0; 1072 QDF_STATUS ret; 1073 1074 if (!info) { 1075 wmi_err("ML vdev pause info is NULL"); 1076 return QDF_STATUS_E_NULL_VALUE; 1077 } 1078 1079 buf_len = sizeof(*fixed_params); 1080 1081 buf = wmi_buf_alloc(wmi_handle, buf_len); 1082 if (!buf) { 1083 wmi_err("wmi buf alloc failed for vdev pause cmd: psoc (%pK) vdev(%u)", 1084 wmi_handle->soc->wmi_psoc, info->vdev_id); 1085 return QDF_STATUS_E_NOMEM; 1086 } 1087 1088 /* Populate fixed params TLV */ 1089 fixed_params = (wmi_vdev_pause_cmd_fixed_param *)wmi_buf_data(buf); 1090 WMITLV_SET_HDR(&fixed_params->tlv_header, 1091 WMITLV_TAG_STRUC_wmi_vdev_pause_cmd_fixed_param, 1092 WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_pause_cmd_fixed_param)); 1093 fixed_params->vdev_id = info->vdev_id; 1094 fixed_params->pause_dur_ms = info->vdev_pause_duration; 1095 fixed_params->pause_type = WMI_VDEV_PAUSE_TYPE_MLO_LINK; 1096 wmi_debug("vdev id: %d pause duration: %d pause type %d", 1097 fixed_params->vdev_id, fixed_params->pause_dur_ms, 1098 fixed_params->pause_type); 1099 1100 wmi_mtrace(WMI_VDEV_PAUSE_CMDID, fixed_params->vdev_id, 0); 1101 ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len, 1102 WMI_VDEV_PAUSE_CMDID); 1103 if (QDF_IS_STATUS_ERROR(ret)) { 1104 wmi_err("Failed to send vdev pause cmd: psoc (%pK) vdev(%u)", 1105 wmi_handle->soc->wmi_psoc, info->vdev_id); 1106 wmi_buf_free(buf); 1107 } 1108 1109 return ret; 1110 } 1111 1112 /** 1113 * extract_mlo_link_removal_evt_fixed_param_tlv() - Extract fixed parameters TLV 1114 * from the MLO link removal WMI event 1115 * @wmi_handle: wmi handle 1116 * @buf: pointer to event buffer 1117 * @params: MLO link removal event parameters 1118 * 1119 * Return: QDF_STATUS of operation 1120 */ 1121 static QDF_STATUS 1122 extract_mlo_link_removal_evt_fixed_param_tlv( 1123 struct wmi_unified *wmi_handle, 1124 void *buf, 1125 struct mlo_link_removal_evt_params *params) 1126 { 1127 WMI_MLO_LINK_REMOVAL_EVENTID_param_tlvs *param_buf = buf; 1128 wmi_mlo_link_removal_evt_fixed_param *ev; 1129 1130 if (!param_buf) { 1131 wmi_err_rl("Param_buf is NULL"); 1132 return QDF_STATUS_E_NULL_VALUE; 1133 } 1134 1135 if (!params) { 1136 wmi_err_rl("params is NULL"); 1137 return QDF_STATUS_E_NULL_VALUE; 1138 } 1139 1140 ev = param_buf->fixed_param; 1141 params->vdev_id = ev->vdev_id; 1142 1143 return QDF_STATUS_SUCCESS; 1144 } 1145 1146 /** 1147 * extract_mlo_link_removal_tbtt_update_tlv() - Extract TBTT update TLV 1148 * from the MLO link removal WMI event 1149 * @wmi_handle: wmi handle 1150 * @buf: pointer to event buffer 1151 * @tbtt_info: TBTT information to be populated 1152 * 1153 * Return: QDF_STATUS of operation 1154 */ 1155 static QDF_STATUS 1156 extract_mlo_link_removal_tbtt_update_tlv( 1157 struct wmi_unified *wmi_handle, 1158 void *buf, 1159 struct mlo_link_removal_tbtt_info *tbtt_info) 1160 { 1161 WMI_MLO_LINK_REMOVAL_EVENTID_param_tlvs *param_buf = buf; 1162 wmi_mlo_link_removal_tbtt_update *tlv; 1163 1164 if (!param_buf) { 1165 wmi_err_rl("Param_buf is NULL"); 1166 return QDF_STATUS_E_NULL_VALUE; 1167 } 1168 1169 if (!tbtt_info) { 1170 wmi_err_rl("Writable argument is NULL"); 1171 return QDF_STATUS_E_NULL_VALUE; 1172 } 1173 1174 tlv = param_buf->tbtt_update; 1175 1176 tbtt_info->tbtt_count = tlv->tbtt_count; 1177 tbtt_info->tsf = ((uint64_t)tlv->tsf_high << 32) | tlv->tsf_low; 1178 tbtt_info->qtimer_reading = 1179 ((uint64_t)tlv->qtimer_ts_high << 32) | tlv->qtimer_ts_low; 1180 1181 return QDF_STATUS_SUCCESS; 1182 } 1183 1184 /** 1185 * extract_mgmt_rx_mlo_link_removal_info_tlv() - Extract MLO link removal info 1186 * from MGMT Rx event 1187 * @wmi_handle: wmi handle 1188 * @buf: event buffer 1189 * @link_removal_info: link removal information array to be populated 1190 * @num_link_removal_info: Number of elements in @link_removal_info 1191 * 1192 * Return: QDF_STATUS of operation 1193 */ 1194 static QDF_STATUS 1195 extract_mgmt_rx_mlo_link_removal_info_tlv( 1196 struct wmi_unified *wmi_handle, 1197 void *buf, 1198 struct mgmt_rx_mlo_link_removal_info *link_removal_info, 1199 int num_link_removal_info) 1200 { 1201 WMI_MGMT_RX_EVENTID_param_tlvs *param_buf = buf; 1202 wmi_mlo_link_removal_tbtt_count *tlv_arr; 1203 int tlv_idx = 0; 1204 struct mgmt_rx_mlo_link_removal_info *info; 1205 1206 if (!param_buf) { 1207 wmi_err_rl("Param_buf is NULL"); 1208 return QDF_STATUS_E_NULL_VALUE; 1209 } 1210 1211 if (!link_removal_info) { 1212 wmi_err_rl("Writable argument is NULL"); 1213 return QDF_STATUS_E_NULL_VALUE; 1214 } 1215 1216 if (num_link_removal_info != param_buf->num_link_removal_tbtt_count) { 1217 wmi_err_rl("link_removal_info array size (%d) is not equal to" 1218 "number of corresponding TLVs(%d) present in event", 1219 num_link_removal_info, 1220 param_buf->num_link_removal_tbtt_count); 1221 return QDF_STATUS_E_RANGE; 1222 } 1223 1224 tlv_arr = param_buf->link_removal_tbtt_count; 1225 for (; tlv_idx < param_buf->num_link_removal_tbtt_count; tlv_idx++) { 1226 info = &link_removal_info[tlv_idx]; 1227 1228 info->hw_link_id = WMI_MLO_LINK_REMOVAL_GET_LINKID( 1229 tlv_arr[tlv_idx].tbtt_info); 1230 info->vdev_id = WMI_MLO_LINK_REMOVAL_GET_VDEVID( 1231 tlv_arr[tlv_idx].tbtt_info); 1232 info->tbtt_count = WMI_MLO_LINK_REMOVAL_GET_TBTT_COUNT( 1233 tlv_arr[tlv_idx].tbtt_info); 1234 } 1235 1236 return QDF_STATUS_SUCCESS; 1237 } 1238 1239 /** 1240 * extract_mlo_link_disable_request_evt_param_tlv() - Extract fixed 1241 * parameters TLV from the MLO link removal WMI event 1242 * @wmi_handle: wmi handle 1243 * @buf: pointer to event buffer 1244 * @params: MLO link removal event parameters 1245 * 1246 * Return: QDF_STATUS of operation 1247 */ 1248 static QDF_STATUS 1249 extract_mlo_link_disable_request_evt_param_tlv( 1250 struct wmi_unified *wmi_handle, 1251 void *buf, 1252 struct mlo_link_disable_request_evt_params *params) 1253 { 1254 WMI_MLO_LINK_DISABLE_REQUEST_EVENTID_param_tlvs *param_buf = buf; 1255 wmi_mlo_link_disable_request_event_fixed_param *ev; 1256 1257 if (!param_buf) { 1258 wmi_err_rl("Param_buf is NULL"); 1259 return QDF_STATUS_E_NULL_VALUE; 1260 } 1261 1262 if (!params) { 1263 wmi_err_rl("params is NULL"); 1264 return QDF_STATUS_E_NULL_VALUE; 1265 } 1266 1267 ev = param_buf->fixed_param; 1268 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->mld_addr, 1269 params->mld_addr.bytes); 1270 1271 params->link_id_bitmap = ev->linkid_bitmap; 1272 1273 wmi_debug("Link id bitmap 0x%x MLD addr " QDF_MAC_ADDR_FMT, 1274 params->link_id_bitmap, 1275 QDF_MAC_ADDR_REF(params->mld_addr.bytes)); 1276 1277 return QDF_STATUS_SUCCESS; 1278 } 1279 1280 #ifdef WLAN_FEATURE_11BE 1281 size_t peer_assoc_t2lm_params_size(struct peer_assoc_params *req) 1282 { 1283 size_t peer_assoc_t2lm_size = WMI_TLV_HDR_SIZE + 1284 (req->t2lm_params.num_dir * T2LM_MAX_NUM_TIDS * 1285 (sizeof(wmi_peer_assoc_tid_to_link_map))); 1286 1287 return peer_assoc_t2lm_size; 1288 } 1289 1290 static void peer_assoc_populate_t2lm_tlv(wmi_peer_assoc_tid_to_link_map *cmd, 1291 struct wlan_host_t2lm_of_tids *t2lm, 1292 uint8_t tid_num) 1293 { 1294 WMITLV_SET_HDR(&cmd->tlv_header, 1295 WMITLV_TAG_STRUC_wmi_peer_assoc_tid_to_link_map, 1296 WMITLV_GET_STRUCT_TLVLEN( 1297 wmi_peer_assoc_tid_to_link_map)); 1298 1299 /* Populate TID number */ 1300 WMI_TID_TO_LINK_MAP_TID_NUM_SET(cmd->tid_to_link_map_info, tid_num); 1301 1302 /* Populate the direction */ 1303 WMI_TID_TO_LINK_MAP_DIR_SET(cmd->tid_to_link_map_info, 1304 t2lm->direction); 1305 1306 /* Populate the default link mapping value */ 1307 WMI_TID_TO_LINK_MAP_DEFAULT_MAPPING_SET( 1308 cmd->tid_to_link_map_info, 1309 t2lm->default_link_mapping); 1310 1311 /* Populate the T2LM provisioned links for the corresponding TID 1312 * number. 1313 */ 1314 WMI_TID_TO_LINK_MAP_LINK_MASK_SET( 1315 cmd->tid_to_link_map_info, 1316 t2lm->t2lm_provisioned_links[tid_num]); 1317 1318 wmi_debug("Add T2LM TLV: tid_to_link_map_info:%x", 1319 cmd->tid_to_link_map_info); 1320 } 1321 1322 uint8_t *peer_assoc_add_tid_to_link_map(uint8_t *buf_ptr, 1323 struct peer_assoc_params *req) 1324 { 1325 struct wmi_host_tid_to_link_map_params *t2lm_params = &req->t2lm_params; 1326 wmi_peer_assoc_tid_to_link_map *cmd; 1327 uint8_t dir = 0; 1328 uint8_t tid_num = 0; 1329 1330 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 1331 (req->t2lm_params.num_dir * T2LM_MAX_NUM_TIDS * 1332 sizeof(wmi_peer_assoc_tid_to_link_map))); 1333 buf_ptr += sizeof(uint32_t); 1334 1335 for (dir = 0; dir < t2lm_params->num_dir; dir++) { 1336 wmi_debug("Add T2LM TLV for peer: " QDF_MAC_ADDR_FMT " direction:%d", 1337 QDF_MAC_ADDR_REF(t2lm_params->peer_macaddr), 1338 t2lm_params->t2lm_info[dir].direction); 1339 for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) { 1340 cmd = (wmi_peer_assoc_tid_to_link_map *)buf_ptr; 1341 peer_assoc_populate_t2lm_tlv( 1342 cmd, &t2lm_params->t2lm_info[dir], 1343 tid_num); 1344 buf_ptr += sizeof(wmi_peer_assoc_tid_to_link_map); 1345 } 1346 } 1347 1348 return buf_ptr; 1349 } 1350 1351 #ifdef WMI_AP_SUPPORT 1352 static uint32_t find_buf_len_pref_link( 1353 struct wmi_host_tid_to_link_map_params *params, 1354 bool t2lm_info) 1355 { 1356 uint32_t buf_len = 0; 1357 1358 buf_len = sizeof(wmi_peer_tid_to_link_map_fixed_param); 1359 1360 /* Update the length for T2LM info TLV */ 1361 if (t2lm_info) { 1362 buf_len += (WMI_TLV_HDR_SIZE + 1363 (params->num_dir * T2LM_MAX_NUM_TIDS * 1364 sizeof(wmi_tid_to_link_map))); 1365 } else { 1366 buf_len += WMI_TLV_HDR_SIZE; 1367 } 1368 1369 /* Update the length for Preferred Link TLV. 1370 * The Link Preference TLV is planned to be deprecated, 1371 * so the TLV is going to be exlcuded by default 1372 */ 1373 buf_len += WMI_TLV_HDR_SIZE; 1374 1375 /* Update the length for Link control TLV */ 1376 if (params->preferred_links.num_pref_links) { 1377 buf_len += (WMI_TLV_HDR_SIZE + 1378 sizeof(wmi_mlo_peer_link_control_param)); 1379 } else { 1380 buf_len += WMI_TLV_HDR_SIZE; 1381 } 1382 1383 return buf_len; 1384 } 1385 1386 static uint8_t *populate_link_control_tlv( 1387 uint8_t *buf_ptr, 1388 struct wmi_host_tid_to_link_map_params *params) 1389 { 1390 wmi_mlo_peer_link_control_param *link_control; 1391 uint8_t pref_link = 0; 1392 uint8_t latency = 0; 1393 uint8_t links = 0; 1394 1395 /* The Link Preference TLV is planned to be deprecated, 1396 * so the TLV is going to be exlcuded by default. 1397 */ 1398 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 1399 buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE; 1400 1401 if (params->preferred_links.num_pref_links) { 1402 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 1403 sizeof(wmi_mlo_peer_link_control_param)); 1404 buf_ptr += sizeof(uint32_t); 1405 1406 link_control = (wmi_mlo_peer_link_control_param *)buf_ptr; 1407 1408 WMITLV_SET_HDR(&link_control->tlv_header, 1409 WMITLV_TAG_STRUC_wmi_mlo_peer_link_control_param, 1410 WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_peer_link_control_param)); 1411 1412 link_control->num_links = params->preferred_links.num_pref_links; 1413 links = params->preferred_links.num_pref_links; 1414 1415 for (pref_link = 0; pref_link < links; pref_link++) { 1416 link_control->link_priority_order[pref_link] = 1417 params->preferred_links.preffered_link_order[pref_link]; 1418 wmi_debug("Add preference link TLV: preffered_link_order: %d", 1419 link_control->link_priority_order[pref_link]); 1420 } 1421 1422 link_control->flags = 1423 params->preferred_links.link_control_flags; 1424 link_control->tx_link_tuple_bitmap = 1425 params->preferred_links.tlt_characterization_params; 1426 1427 for (latency = 0; latency < WLAN_MAX_AC; latency++) { 1428 link_control->max_timeout_ms[latency] = 1429 params->preferred_links.timeout[latency]; 1430 wmi_debug("Add preference link TLV: expected_timeout_ms: %d", 1431 link_control->max_timeout_ms[latency]); 1432 } 1433 buf_ptr += sizeof(wmi_mlo_peer_link_control_param); 1434 } else { 1435 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 1436 buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE; 1437 } 1438 1439 return buf_ptr; 1440 } 1441 1442 static void 1443 populate_fill_t2lm_timer_tlv(wmi_peer_tid_to_link_map_fixed_param *cmd, 1444 struct wmi_host_tid_to_link_map_params *params) 1445 { 1446 } 1447 #else 1448 static uint32_t find_buf_len_pref_link( 1449 struct wmi_host_tid_to_link_map_params *params, 1450 bool t2lm_info) 1451 { 1452 uint32_t buf_len = 0; 1453 1454 buf_len = sizeof(wmi_peer_tid_to_link_map_fixed_param) + 1455 WMI_TLV_HDR_SIZE + (params->num_dir * T2LM_MAX_NUM_TIDS * 1456 sizeof(wmi_tid_to_link_map)); 1457 return buf_len; 1458 } 1459 1460 static uint8_t *populate_link_control_tlv( 1461 uint8_t *buf_ptr, 1462 struct wmi_host_tid_to_link_map_params *params) 1463 { 1464 return buf_ptr; 1465 } 1466 1467 static void 1468 populate_fill_t2lm_timer_tlv(wmi_peer_tid_to_link_map_fixed_param *cmd, 1469 struct wmi_host_tid_to_link_map_params *params) 1470 { 1471 cmd->mapping_switch_time = params->mapping_switch_time; 1472 cmd->expected_duration = params->expected_duration; 1473 } 1474 #endif 1475 1476 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 1477 /** 1478 * extract_mlo_link_switch_request_event_tlv() - Extract fixed 1479 * params TLV from MLO link switch request WMI event. 1480 * @wmi_handle: wmi handle 1481 * @buf: Pointer to event buffer. 1482 * @req: MLO Link switch event parameters. 1483 * 1484 * Return: QDF_STATUS 1485 */ 1486 static QDF_STATUS 1487 extract_mlo_link_switch_request_event_tlv(struct wmi_unified *wmi_handle, 1488 void *buf, 1489 struct wlan_mlo_link_switch_req *req) 1490 { 1491 WMI_MLO_LINK_SWITCH_REQUEST_EVENTID_param_tlvs *param_buf = buf; 1492 wmi_mlo_link_switch_req_evt_fixed_param *ev; 1493 1494 if (!param_buf) { 1495 wmi_err_rl("buf is NULL"); 1496 return QDF_STATUS_E_NULL_VALUE; 1497 } 1498 1499 if (!req) { 1500 wmi_err_rl("req is NULL"); 1501 return QDF_STATUS_E_NULL_VALUE; 1502 } 1503 1504 ev = param_buf->fixed_param; 1505 req->vdev_id = ev->vdev_id; 1506 req->curr_ieee_link_id = ev->curr_ieee_link_id; 1507 req->new_ieee_link_id = ev->new_ieee_link_id; 1508 req->new_primary_freq = ev->new_primary_freq; 1509 req->new_phymode = ev->new_phymode; 1510 req->reason = ev->reason; 1511 1512 return QDF_STATUS_SUCCESS; 1513 } 1514 1515 static QDF_STATUS 1516 send_link_switch_request_cnf_cmd_tlv(wmi_unified_t wmi_handle, 1517 struct wlan_mlo_link_switch_cnf *params) 1518 { 1519 wmi_mlo_link_switch_cnf_fixed_param *cmd; 1520 wmi_buf_t buf; 1521 uint8_t *buf_ptr; 1522 QDF_STATUS ret = QDF_STATUS_SUCCESS; 1523 uint32_t buf_len; 1524 1525 buf_len = sizeof(wmi_mlo_link_switch_cnf_fixed_param); 1526 1527 buf = wmi_buf_alloc(wmi_handle, buf_len); 1528 if (!buf) { 1529 wmi_err("wmi buf alloc failed for vdev id %d while link state cmd send: ", 1530 params->vdev_id); 1531 return QDF_STATUS_E_NOMEM; 1532 } 1533 1534 buf_ptr = (uint8_t *)wmi_buf_data(buf); 1535 cmd = (wmi_mlo_link_switch_cnf_fixed_param *)buf_ptr; 1536 1537 WMITLV_SET_HDR( 1538 &cmd->tlv_header, 1539 WMITLV_TAG_STRUC_wmi_mlo_link_switch_cnf_fixed_param, 1540 WMITLV_GET_STRUCT_TLVLEN( 1541 wmi_mlo_link_switch_cnf_fixed_param)); 1542 1543 cmd->vdev_id = params->vdev_id; 1544 cmd->status = params->status; 1545 cmd->reason = params->reason; 1546 buf_ptr += sizeof(wmi_mlo_link_switch_cnf_fixed_param); 1547 wmi_mtrace(WMI_MLO_LINK_SWITCH_CONF_CMDID, cmd->vdev_id, 0); 1548 ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len, 1549 WMI_MLO_LINK_SWITCH_CONF_CMDID); 1550 if (ret) { 1551 wmi_err("Failed to send ml link switch cnf command to FW: %d vdev id %d", 1552 ret, cmd->vdev_id); 1553 wmi_buf_free(buf); 1554 } 1555 return ret; 1556 } 1557 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 1558 1559 static QDF_STATUS 1560 send_link_state_request_cmd_tlv(wmi_unified_t wmi_handle, 1561 struct wmi_host_link_state_params *params) 1562 { 1563 wmi_mlo_vdev_get_link_info_cmd_fixed_param *cmd; 1564 wmi_buf_t buf; 1565 uint8_t *buf_ptr; 1566 QDF_STATUS ret = QDF_STATUS_SUCCESS; 1567 uint32_t buf_len = 0; 1568 1569 buf_len = sizeof(wmi_mlo_vdev_get_link_info_cmd_fixed_param); 1570 1571 buf = wmi_buf_alloc(wmi_handle, buf_len); 1572 if (!buf) { 1573 wmi_err("wmi buf alloc failed for vdev id %d while link state cmd send: ", 1574 params->vdev_id); 1575 return QDF_STATUS_E_NOMEM; 1576 } 1577 1578 buf_ptr = (uint8_t *)wmi_buf_data(buf); 1579 cmd = (wmi_mlo_vdev_get_link_info_cmd_fixed_param *)buf_ptr; 1580 1581 WMITLV_SET_HDR( 1582 &cmd->tlv_header, 1583 WMITLV_TAG_STRUC_wmi_mlo_vdev_get_link_info_cmd_fixed_param, 1584 WMITLV_GET_STRUCT_TLVLEN( 1585 wmi_mlo_vdev_get_link_info_cmd_fixed_param)); 1586 1587 cmd->vdev_id = params->vdev_id; 1588 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->mld_mac, &cmd->mld_macaddr); 1589 buf_ptr += sizeof(wmi_mlo_vdev_get_link_info_cmd_fixed_param); 1590 wmi_mtrace(WMI_MLO_VDEV_GET_LINK_INFO_CMDID, cmd->vdev_id, 0); 1591 ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len, 1592 WMI_MLO_VDEV_GET_LINK_INFO_CMDID); 1593 if (ret) { 1594 wmi_err("Failed to send ml link state command to FW: %d vdev id %d", 1595 ret, cmd->vdev_id); 1596 wmi_buf_free(buf); 1597 } 1598 return ret; 1599 } 1600 1601 static QDF_STATUS 1602 extract_mlo_link_state_event_tlv(struct wmi_unified *wmi_handle, 1603 void *buf, 1604 struct ml_link_state_info_event *params) 1605 { 1606 WMI_MLO_VDEV_LINK_INFO_EVENTID_param_tlvs *param_buf; 1607 wmi_mlo_vdev_link_info_event_fixed_param *ev; 1608 wmi_mlo_vdev_link_info *link_info = NULL; 1609 int num_info = 0; 1610 uint8_t *mld_addr; 1611 uint32_t num_link_info = 0; 1612 1613 param_buf = (WMI_MLO_VDEV_LINK_INFO_EVENTID_param_tlvs *)buf; 1614 1615 if (!param_buf) { 1616 wmi_err_rl("Param_buf is NULL"); 1617 return QDF_STATUS_E_FAILURE; 1618 } 1619 1620 ev = (wmi_mlo_vdev_link_info_event_fixed_param *) 1621 param_buf->fixed_param; 1622 link_info = (wmi_mlo_vdev_link_info *)param_buf->mlo_vdev_link_info; 1623 1624 num_link_info = param_buf->num_mlo_vdev_link_info; 1625 params->status = ev->status; 1626 params->vdev_id = ev->vdev_id; 1627 params->hw_mode_index = ev->hw_mode_index; 1628 params->num_mlo_vdev_link_info = num_link_info; 1629 mld_addr = params->mldaddr.bytes; 1630 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->mld_macaddr, mld_addr); 1631 1632 if (params->num_mlo_vdev_link_info > WLAN_MAX_ML_BSS_LINKS) { 1633 wmi_err_rl("Invalid number of vdev link info"); 1634 return QDF_STATUS_E_FAILURE; 1635 } 1636 1637 for (num_info = 0; num_info < num_link_info; num_info++) { 1638 params->link_info[num_info].vdev_id = 1639 WMI_MLO_VDEV_LINK_INFO_GET_VDEVID(link_info->link_info); 1640 1641 params->link_info[num_info].link_id = 1642 WMI_MLO_VDEV_LINK_INFO_GET_LINKID(link_info->link_info); 1643 1644 params->link_info[num_info].link_status = 1645 WMI_MLO_VDEV_LINK_INFO_GET_LINK_STATUS(link_info->link_info); 1646 1647 params->link_info[num_info].chan_freq = 1648 link_info->chan_freq; 1649 1650 link_info++; 1651 } 1652 1653 return QDF_STATUS_SUCCESS; 1654 } 1655 1656 static QDF_STATUS send_mlo_peer_tid_to_link_map_cmd_tlv( 1657 wmi_unified_t wmi_handle, 1658 struct wmi_host_tid_to_link_map_params *params, 1659 bool t2lm_info) 1660 { 1661 wmi_peer_tid_to_link_map_fixed_param *cmd; 1662 wmi_tid_to_link_map *t2lm; 1663 wmi_buf_t buf; 1664 uint8_t *buf_ptr; 1665 QDF_STATUS ret = QDF_STATUS_SUCCESS; 1666 uint32_t buf_len = 0; 1667 uint8_t dir = 0; 1668 uint8_t tid_num = 0; 1669 1670 buf_len = find_buf_len_pref_link(params, t2lm_info); 1671 buf = wmi_buf_alloc(wmi_handle, buf_len); 1672 if (!buf) { 1673 wmi_err("wmi buf alloc failed for mlo_peer_mac: " 1674 QDF_MAC_ADDR_FMT, 1675 QDF_MAC_ADDR_REF(params->peer_macaddr)); 1676 return QDF_STATUS_E_NOMEM; 1677 } 1678 1679 buf_ptr = (uint8_t *)wmi_buf_data(buf); 1680 cmd = (wmi_peer_tid_to_link_map_fixed_param *)buf_ptr; 1681 1682 WMITLV_SET_HDR(&cmd->tlv_header, 1683 WMITLV_TAG_STRUC_wmi_peer_tid_to_link_map_fixed_param, 1684 WMITLV_GET_STRUCT_TLVLEN( 1685 wmi_peer_tid_to_link_map_fixed_param)); 1686 1687 cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target( 1688 wmi_handle, params->pdev_id); 1689 1690 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->link_macaddr); 1691 1692 buf_ptr += sizeof(wmi_peer_tid_to_link_map_fixed_param); 1693 populate_fill_t2lm_timer_tlv(cmd, params); 1694 1695 if (t2lm_info) { 1696 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 1697 (params->num_dir * T2LM_MAX_NUM_TIDS * 1698 sizeof(wmi_tid_to_link_map))); 1699 buf_ptr += sizeof(uint32_t); 1700 1701 for (dir = 0; dir < params->num_dir; dir++) { 1702 wmi_debug("Add T2LM TLV for peer: " QDF_MAC_ADDR_FMT " direction:%d", 1703 QDF_MAC_ADDR_REF(params->peer_macaddr), 1704 params->t2lm_info[dir].direction); 1705 1706 for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) { 1707 t2lm = (wmi_tid_to_link_map *)buf_ptr; 1708 1709 WMITLV_SET_HDR(&t2lm->tlv_header, 1710 WMITLV_TAG_STRUC_wmi_tid_to_link_map, 1711 WMITLV_GET_STRUCT_TLVLEN( 1712 wmi_tid_to_link_map)); 1713 1714 /* Populate TID number */ 1715 WMI_TID_TO_LINK_MAP_TID_NUM_SET( 1716 t2lm->tid_to_link_map_info, tid_num); 1717 1718 /* Populate the direction */ 1719 WMI_TID_TO_LINK_MAP_DIR_SET( 1720 t2lm->tid_to_link_map_info, 1721 params->t2lm_info[dir].direction); 1722 1723 /* Populate the default link mapping value */ 1724 WMI_TID_TO_LINK_MAP_DEFAULT_MAPPING_SET( 1725 t2lm->tid_to_link_map_info, 1726 params->t2lm_info[dir].default_link_mapping); 1727 1728 /* Populate the T2LM provisioned links for the 1729 * corresponding TID number. 1730 */ 1731 WMI_TID_TO_LINK_MAP_LINK_MASK_SET( 1732 t2lm->tid_to_link_map_info, 1733 params->t2lm_info[dir].t2lm_provisioned_links[tid_num]); 1734 1735 buf_ptr += sizeof(wmi_tid_to_link_map); 1736 1737 wmi_debug("Add T2LM TLV: tid_to_link_map_info:%x", 1738 t2lm->tid_to_link_map_info); 1739 } 1740 } 1741 } else { 1742 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 1743 buf_ptr = buf_ptr + WMI_TLV_HDR_SIZE; 1744 } 1745 1746 buf_ptr = populate_link_control_tlv(buf_ptr, params); 1747 wmi_mtrace(WMI_MLO_PEER_TID_TO_LINK_MAP_CMDID, cmd->pdev_id, 0); 1748 ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len, 1749 WMI_MLO_PEER_TID_TO_LINK_MAP_CMDID); 1750 if (ret) { 1751 wmi_err("Failed to send T2LM command to FW: %d mlo_peer_mac: " QDF_MAC_ADDR_FMT, 1752 ret, QDF_MAC_ADDR_REF(params->peer_macaddr)); 1753 wmi_buf_free(buf); 1754 } 1755 1756 return ret; 1757 } 1758 1759 static void update_t2lm_ie_info_params( 1760 wmi_mlo_ap_vdev_tid_to_link_map_ie_info * info, 1761 struct wlan_t2lm_info *params) 1762 { 1763 WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_DIR_SET( 1764 info->tid_to_link_map_ctrl, 1765 params->direction); 1766 1767 WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_DEF_LINK_SET( 1768 info->tid_to_link_map_ctrl, 1769 params->default_link_mapping); 1770 1771 info->map_switch_time = params->mapping_switch_time; 1772 WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_SWT_TIME_SET( 1773 info->tid_to_link_map_ctrl, 1774 params->mapping_switch_time_present); 1775 1776 info->expected_duration = params->expected_duration; 1777 WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_DUR_TIME_SET( 1778 info->tid_to_link_map_ctrl, 1779 params->expected_duration_present); 1780 1781 WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_LINK_MAP_SIZE_SET( 1782 info->tid_to_link_map_ctrl, 1783 params->link_mapping_size); 1784 1785 wmi_debug("tid_to_link_map_ctrl:%x map_switch_time:%d expected_duration:%d", 1786 info->tid_to_link_map_ctrl, info->map_switch_time, 1787 info->expected_duration); 1788 1789 /* Do not fill link mapping values when default mapping is set to 1 */ 1790 if (params->default_link_mapping) 1791 return; 1792 1793 WMI_MLO_VDEV_TID_TO_LINK_MAP_CTRL_LINK_MAP_PRE_SET( 1794 info->tid_to_link_map_ctrl, 0xff); 1795 1796 WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_0_SET( 1797 info->ieee_tid_0_1_link_map, 1798 params->ieee_link_map_tid[0]); 1799 1800 WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_1_SET( 1801 info->ieee_tid_0_1_link_map, 1802 params->ieee_link_map_tid[1]); 1803 1804 WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_2_SET( 1805 info->ieee_tid_2_3_link_map, 1806 params->ieee_link_map_tid[2]); 1807 1808 WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_3_SET( 1809 info->ieee_tid_2_3_link_map, 1810 params->ieee_link_map_tid[3]); 1811 1812 WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_4_SET( 1813 info->ieee_tid_4_5_link_map, 1814 params->ieee_link_map_tid[4]); 1815 1816 WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_5_SET( 1817 info->ieee_tid_4_5_link_map, 1818 params->ieee_link_map_tid[5]); 1819 1820 WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_6_SET( 1821 info->ieee_tid_6_7_link_map, 1822 params->ieee_link_map_tid[6]); 1823 1824 WMI_MLO_VDEV_TID_TO_LINK_MAP_IEEE_LINK_ID_7_SET( 1825 info->ieee_tid_6_7_link_map, 1826 params->ieee_link_map_tid[7]); 1827 1828 WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_0_SET( 1829 info->hw_tid_0_1_link_map, 1830 params->hw_link_map_tid[0]); 1831 1832 WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_1_SET( 1833 info->hw_tid_0_1_link_map, 1834 params->hw_link_map_tid[1]); 1835 1836 WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_2_SET( 1837 info->hw_tid_2_3_link_map, 1838 params->hw_link_map_tid[2]); 1839 1840 WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_3_SET( 1841 info->hw_tid_2_3_link_map, 1842 params->hw_link_map_tid[3]); 1843 1844 WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_4_SET( 1845 info->hw_tid_4_5_link_map, 1846 params->hw_link_map_tid[4]); 1847 1848 WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_5_SET( 1849 info->hw_tid_4_5_link_map, 1850 params->hw_link_map_tid[5]); 1851 1852 WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_6_SET( 1853 info->hw_tid_6_7_link_map, 1854 params->hw_link_map_tid[6]); 1855 1856 WMI_MLO_VDEV_TID_TO_LINK_MAP_HW_LINK_ID_7_SET( 1857 info->hw_tid_6_7_link_map, 1858 params->hw_link_map_tid[7]); 1859 1860 wmi_debug("tid_to_link_map_ctrl:%x", info->tid_to_link_map_ctrl); 1861 wmi_debug("ieee_link_map: tid_0_1:%x tid_2_3:%x tid_4_5:%x tid_6_7:%x", 1862 info->ieee_tid_0_1_link_map, info->ieee_tid_2_3_link_map, 1863 info->ieee_tid_4_5_link_map, info->ieee_tid_6_7_link_map); 1864 wmi_debug("hw_link_map: tid_0_1:%x tid_2_3:%x tid_4_5:%x tid_6_7:%x", 1865 info->hw_tid_0_1_link_map, info->hw_tid_2_3_link_map, 1866 info->hw_tid_4_5_link_map, info->hw_tid_6_7_link_map); 1867 } 1868 1869 static QDF_STATUS send_mlo_vdev_tid_to_link_map_cmd_tlv( 1870 wmi_unified_t wmi_handle, 1871 struct wmi_host_tid_to_link_map_ap_params *params) 1872 { 1873 wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param *cmd; 1874 wmi_mlo_ap_vdev_tid_to_link_map_ie_info *info; 1875 wmi_buf_t buf; 1876 uint8_t *buf_ptr; 1877 QDF_STATUS ret = QDF_STATUS_SUCCESS; 1878 uint32_t buf_len = 0; 1879 uint32_t num_info = 0; 1880 1881 if (params->num_t2lm_info > WLAN_MAX_T2LM_IE) { 1882 wmi_err("Failed to send T2LM command to FW for vdev id %d as t2lm info %d is greater than max %d", 1883 params->vdev_id, 1884 params->num_t2lm_info, 1885 WLAN_MAX_T2LM_IE); 1886 return QDF_STATUS_E_INVAL; 1887 } 1888 1889 buf_len = sizeof(wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param) + 1890 WMI_TLV_HDR_SIZE + (params->num_t2lm_info * 1891 sizeof(wmi_mlo_ap_vdev_tid_to_link_map_ie_info)); 1892 1893 buf = wmi_buf_alloc(wmi_handle, buf_len); 1894 if (!buf) { 1895 wmi_err("wmi buf alloc failed for vdev id %d while t2lm map cmd send: ", 1896 params->vdev_id); 1897 return QDF_STATUS_E_NOMEM; 1898 } 1899 1900 buf_ptr = (uint8_t *)wmi_buf_data(buf); 1901 cmd = (wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param *)buf_ptr; 1902 1903 WMITLV_SET_HDR( 1904 &cmd->tlv_header, 1905 WMITLV_TAG_STRUC_wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param, 1906 WMITLV_GET_STRUCT_TLVLEN( 1907 wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param)); 1908 1909 cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target( 1910 wmi_handle, params->pdev_id); 1911 cmd->vdev_id = params->vdev_id; 1912 cmd->disabled_link_bitmap = params->disabled_link_bitmap; 1913 wmi_debug("pdev_id:%d vdev_id:%d disabled_link_bitmap:%x num_t2lm_info:%d", 1914 cmd->pdev_id, cmd->vdev_id, cmd->disabled_link_bitmap, 1915 params->num_t2lm_info); 1916 1917 buf_ptr += sizeof(wmi_mlo_ap_vdev_tid_to_link_map_cmd_fixed_param); 1918 1919 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 1920 (params->num_t2lm_info * 1921 sizeof(wmi_mlo_ap_vdev_tid_to_link_map_ie_info))); 1922 buf_ptr += sizeof(uint32_t); 1923 1924 for (num_info = 0; num_info < params->num_t2lm_info; num_info++) { 1925 info = (wmi_mlo_ap_vdev_tid_to_link_map_ie_info *)buf_ptr; 1926 1927 WMITLV_SET_HDR( 1928 &info->tlv_header, 1929 WMITLV_TAG_STRUC_wmi_mlo_ap_vdev_tid_to_link_map_ie_info, 1930 WMITLV_GET_STRUCT_TLVLEN( 1931 wmi_mlo_ap_vdev_tid_to_link_map_ie_info)); 1932 update_t2lm_ie_info_params(info, ¶ms->info[num_info]); 1933 buf_ptr += sizeof(wmi_mlo_ap_vdev_tid_to_link_map_ie_info); 1934 } 1935 1936 wmi_mtrace(WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_CMDID, cmd->vdev_id, 0); 1937 ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len, 1938 WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_CMDID); 1939 if (ret) { 1940 wmi_err("Failed to send T2LM command to FW: %d vdev id %d", 1941 ret, cmd->vdev_id); 1942 wmi_buf_free(buf); 1943 } 1944 1945 return ret; 1946 } 1947 1948 static QDF_STATUS 1949 extract_mlo_vdev_tid_to_link_map_event_tlv( 1950 struct wmi_unified *wmi_handle, 1951 uint8_t *buf, 1952 struct mlo_vdev_host_tid_to_link_map_resp *params) 1953 { 1954 WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_EVENTID_param_tlvs *param_buf; 1955 wmi_mlo_ap_vdev_tid_to_link_map_evt_fixed_param *ev; 1956 1957 param_buf = (WMI_MLO_AP_VDEV_TID_TO_LINK_MAP_EVENTID_param_tlvs *)buf; 1958 if (!param_buf) { 1959 wmi_err_rl("Param_buf is NULL"); 1960 return QDF_STATUS_E_FAILURE; 1961 } 1962 1963 ev = (wmi_mlo_ap_vdev_tid_to_link_map_evt_fixed_param *) 1964 param_buf->fixed_param; 1965 1966 params->vdev_id = ev->vdev_id; 1967 params->status = ev->status_type; 1968 params->mapping_switch_tsf = ev->mapping_switch_tsf; 1969 1970 return QDF_STATUS_SUCCESS; 1971 } 1972 1973 static QDF_STATUS 1974 extract_mlo_vdev_bcast_tid_to_link_map_event_tlv( 1975 struct wmi_unified *wmi_handle, 1976 void *buf, 1977 struct mlo_bcast_t2lm_info *bcast_info) 1978 { 1979 WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs; 1980 wmi_mlo_bcast_t2lm_info *info; 1981 int i; 1982 1983 param_tlvs = (WMI_MGMT_RX_EVENTID_param_tlvs *)buf; 1984 if (!param_tlvs) { 1985 wmi_err(" MGMT RX param_tlvs is NULL"); 1986 return QDF_STATUS_E_INVAL; 1987 } 1988 1989 if (param_tlvs->num_mlo_bcast_t2lm_info > MAX_AP_MLDS_PER_LINK) { 1990 wmi_err("num_mlo_bcast_t2lm_info is greater than %d", 1991 MAX_AP_MLDS_PER_LINK); 1992 return QDF_STATUS_E_INVAL; 1993 } 1994 1995 info = param_tlvs->mlo_bcast_t2lm_info; 1996 if (!info) { 1997 wmi_debug("mlo_bcast_t2lm_info is not applicable"); 1998 return QDF_STATUS_SUCCESS; 1999 } 2000 2001 bcast_info->num_vdevs = param_tlvs->num_mlo_bcast_t2lm_info; 2002 wmi_debug("num_vdevs:%d", bcast_info->num_vdevs); 2003 for (i = 0; i < param_tlvs->num_mlo_bcast_t2lm_info; i++) { 2004 bcast_info->vdev_id[i] = 2005 WMI_MLO_BROADCAST_TID_TO_LINK_MAP_INFO_VDEV_ID_GET( 2006 info->vdev_id_expec_dur); 2007 2008 bcast_info->expected_duration[i] = 2009 WMI_MLO_BROADCAST_TID_TO_LINK_MAP_INFO_EXP_DUR_GET( 2010 info->vdev_id_expec_dur); 2011 wmi_debug("vdev_id:%d expected_duration:%d", 2012 bcast_info->vdev_id[i], 2013 bcast_info->expected_duration[i]); 2014 } 2015 2016 return QDF_STATUS_SUCCESS; 2017 } 2018 #else 2019 size_t peer_assoc_t2lm_params_size(struct peer_assoc_params *req) 2020 { 2021 return WMI_TLV_HDR_SIZE; 2022 } 2023 2024 uint8_t *peer_assoc_add_tid_to_link_map(uint8_t *buf_ptr, 2025 struct peer_assoc_params *req) 2026 { 2027 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 2028 return buf_ptr + WMI_TLV_HDR_SIZE; 2029 } 2030 #endif /* WLAN_FEATURE_11BE */ 2031 2032 #ifdef WLAN_MLO_MULTI_CHIP 2033 QDF_STATUS mlo_setup_cmd_send_tlv(struct wmi_unified *wmi_handle, 2034 struct wmi_mlo_setup_params *param) 2035 { 2036 QDF_STATUS ret; 2037 wmi_mlo_setup_cmd_fixed_param *cmd; 2038 wmi_buf_t buf; 2039 int32_t len; 2040 uint8_t *buf_ptr; 2041 uint32_t *partner_links; 2042 uint8_t idx; 2043 2044 if (param->num_valid_hw_links > MAX_LINK_IN_MLO) 2045 return QDF_STATUS_E_INVAL; 2046 2047 len = sizeof(*cmd) + 2048 (param->num_valid_hw_links * sizeof(uint32_t)) + 2049 WMI_TLV_HDR_SIZE; 2050 2051 buf = wmi_buf_alloc(wmi_handle, len); 2052 if (!buf) 2053 return QDF_STATUS_E_NOMEM; 2054 2055 cmd = (wmi_mlo_setup_cmd_fixed_param *)wmi_buf_data(buf); 2056 WMITLV_SET_HDR(&cmd->tlv_header, 2057 WMITLV_TAG_STRUC_wmi_mlo_setup_cmd_fixed_param, 2058 WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_setup_cmd_fixed_param)); 2059 2060 cmd->mld_group_id = param->mld_grp_id; 2061 cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target( 2062 wmi_handle, 2063 param->pdev_id); 2064 buf_ptr = (uint8_t *)cmd + sizeof(*cmd); 2065 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 2066 (sizeof(uint32_t) * param->num_valid_hw_links)); 2067 partner_links = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); 2068 for (idx = 0; idx < param->num_valid_hw_links; idx++) 2069 partner_links[idx] = param->partner_links[idx]; 2070 2071 wmi_mtrace(WMI_MLO_SETUP_CMDID, NO_SESSION, 0); 2072 ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_MLO_SETUP_CMDID); 2073 if (QDF_IS_STATUS_ERROR(ret)) { 2074 wmi_err("Failed to send MLO setup command ret = %d", ret); 2075 wmi_buf_free(buf); 2076 } 2077 2078 return ret; 2079 } 2080 2081 QDF_STATUS mlo_ready_cmd_send_tlv(struct wmi_unified *wmi_handle, 2082 struct wmi_mlo_ready_params *param) 2083 { 2084 QDF_STATUS ret; 2085 wmi_mlo_ready_cmd_fixed_param *cmd; 2086 wmi_buf_t buf; 2087 int32_t len; 2088 2089 len = sizeof(*cmd); 2090 2091 buf = wmi_buf_alloc(wmi_handle, len); 2092 if (!buf) 2093 return QDF_STATUS_E_NOMEM; 2094 2095 cmd = (wmi_mlo_ready_cmd_fixed_param *)wmi_buf_data(buf); 2096 WMITLV_SET_HDR(&cmd->tlv_header, 2097 WMITLV_TAG_STRUC_wmi_mlo_ready_cmd_fixed_param, 2098 WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_ready_cmd_fixed_param)); 2099 2100 cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target( 2101 wmi_handle, 2102 param->pdev_id); 2103 2104 wmi_mtrace(WMI_MLO_READY_CMDID, NO_SESSION, 0); 2105 ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_MLO_READY_CMDID); 2106 if (QDF_IS_STATUS_ERROR(ret)) { 2107 wmi_err("Failed to send MLO ready command ret = %d", ret); 2108 wmi_buf_free(buf); 2109 } 2110 2111 return ret; 2112 } 2113 2114 QDF_STATUS mlo_teardown_cmd_send_tlv(struct wmi_unified *wmi_handle, 2115 struct wmi_mlo_teardown_params *param) 2116 { 2117 QDF_STATUS ret; 2118 wmi_mlo_teardown_fixed_param *cmd; 2119 wmi_buf_t buf; 2120 int32_t len; 2121 2122 len = sizeof(*cmd); 2123 2124 buf = wmi_buf_alloc(wmi_handle, len); 2125 if (!buf) 2126 return QDF_STATUS_E_NOMEM; 2127 2128 cmd = (wmi_mlo_teardown_fixed_param *)wmi_buf_data(buf); 2129 WMITLV_SET_HDR(&cmd->tlv_header, 2130 WMITLV_TAG_STRUC_wmi_mlo_teardown_fixed_param, 2131 WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_teardown_fixed_param)); 2132 2133 cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target( 2134 wmi_handle, 2135 param->pdev_id); 2136 switch (param->reason) { 2137 case WMI_HOST_MLO_TEARDOWN_REASON_SSR: 2138 case WMI_HOST_MLO_TEARDOWN_REASON_MODE1_SSR: 2139 cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON; 2140 break; 2141 case WMI_HOST_MLO_TEARDOWN_REASON_DOWN: 2142 default: 2143 cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON + 1; 2144 break; 2145 } 2146 2147 cmd->trigger_umac_reset = param->umac_reset; 2148 2149 wmi_mtrace(WMI_MLO_TEARDOWN_CMDID, NO_SESSION, 0); 2150 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 2151 WMI_MLO_TEARDOWN_CMDID); 2152 if (QDF_IS_STATUS_ERROR(ret)) { 2153 wmi_err("Failed to send MLO Teardown command ret = %d", ret); 2154 wmi_buf_free(buf); 2155 } 2156 2157 return ret; 2158 } 2159 2160 QDF_STATUS 2161 extract_mlo_setup_cmpl_event_tlv(struct wmi_unified *wmi_handle, 2162 uint8_t *buf, 2163 struct wmi_mlo_setup_complete_params *params) 2164 { 2165 WMI_MLO_SETUP_COMPLETE_EVENTID_param_tlvs *param_buf; 2166 wmi_mlo_setup_complete_event_fixed_param *ev; 2167 2168 param_buf = (WMI_MLO_SETUP_COMPLETE_EVENTID_param_tlvs *)buf; 2169 if (!param_buf) { 2170 wmi_err_rl("Param_buf is NULL"); 2171 return QDF_STATUS_E_FAILURE; 2172 } 2173 ev = (wmi_mlo_setup_complete_event_fixed_param *)param_buf->fixed_param; 2174 2175 params->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host( 2176 wmi_handle, 2177 ev->pdev_id); 2178 if (!ev->status) 2179 params->status = WMI_HOST_MLO_SETUP_STATUS_SUCCESS; 2180 else 2181 params->status = WMI_HOST_MLO_SETUP_STATUS_FAILURE; 2182 2183 params->max_ml_peer_ids = ev->max_ml_peer_ids; 2184 2185 return QDF_STATUS_SUCCESS; 2186 } 2187 2188 QDF_STATUS 2189 extract_mlo_teardown_cmpl_event_tlv(struct wmi_unified *wmi_handle, 2190 uint8_t *buf, 2191 struct wmi_mlo_teardown_cmpl_params *params) 2192 { 2193 WMI_MLO_TEARDOWN_COMPLETE_EVENTID_param_tlvs *param_buf; 2194 wmi_mlo_teardown_complete_fixed_param *ev; 2195 2196 param_buf = (WMI_MLO_TEARDOWN_COMPLETE_EVENTID_param_tlvs *)buf; 2197 if (!param_buf) { 2198 wmi_err_rl("Param_buf is NULL"); 2199 return QDF_STATUS_E_FAILURE; 2200 } 2201 ev = (wmi_mlo_teardown_complete_fixed_param *)param_buf->fixed_param; 2202 2203 params->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host( 2204 wmi_handle, 2205 ev->pdev_id); 2206 if (!ev->status) 2207 params->status = WMI_HOST_MLO_TEARDOWN_STATUS_SUCCESS; 2208 else 2209 params->status = WMI_HOST_MLO_TEARDOWN_STATUS_FAILURE; 2210 2211 return QDF_STATUS_SUCCESS; 2212 } 2213 2214 static void wmi_11be_attach_mlo_setup_tlv(wmi_unified_t wmi_handle) 2215 { 2216 struct wmi_ops *ops = wmi_handle->ops; 2217 2218 ops->mlo_setup_cmd_send = mlo_setup_cmd_send_tlv; 2219 ops->mlo_teardown_cmd_send = mlo_teardown_cmd_send_tlv; 2220 ops->mlo_ready_cmd_send = mlo_ready_cmd_send_tlv; 2221 ops->extract_mlo_setup_cmpl_event = extract_mlo_setup_cmpl_event_tlv; 2222 ops->extract_mlo_teardown_cmpl_event = 2223 extract_mlo_teardown_cmpl_event_tlv; 2224 } 2225 2226 #else /*WLAN_MLO_MULTI_CHIP*/ 2227 2228 static void wmi_11be_attach_mlo_setup_tlv(wmi_unified_t wmi_handle) 2229 {} 2230 2231 #endif /*WLAN_MLO_MULTI_CHIP*/ 2232 2233 /** 2234 * extract_mgmt_rx_ml_cu_params_tlv() - extract MGMT Critical Update params 2235 * from MGMT_RX_EVENT_ID 2236 * @wmi_handle: wmi handle 2237 * @evt_buf: pointer to event buffer 2238 * @cu_params: Pointer to MGMT Critical update parameters 2239 * 2240 * Return: QDF_STATUS_SUCCESS for success or error code 2241 */ 2242 static 2243 QDF_STATUS extract_mgmt_rx_ml_cu_params_tlv(wmi_unified_t wmi_handle, 2244 void *evt_buf, 2245 struct mlo_mgmt_ml_info *cu_params) 2246 { 2247 WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs; 2248 wmi_mgmt_ml_info *cu_params_tlv; 2249 wmi_mgmt_rx_hdr *ev_hdr; 2250 uint32_t num_bpcc_bufp; 2251 2252 param_tlvs = evt_buf; 2253 if (!param_tlvs) { 2254 wmi_err(" MGMT RX param_tlvs is NULL"); 2255 return QDF_STATUS_E_INVAL; 2256 } 2257 2258 ev_hdr = param_tlvs->hdr; 2259 if (!ev_hdr) { 2260 wmi_err("Rx event is NULL"); 2261 return QDF_STATUS_E_INVAL; 2262 } 2263 2264 if (!cu_params) { 2265 wmi_debug("MGMT Rx CU params is NULL"); 2266 return QDF_STATUS_E_INVAL; 2267 } 2268 2269 cu_params_tlv = param_tlvs->ml_info; 2270 if (!cu_params_tlv) { 2271 wmi_debug("mgmt_ml_info TLV is not sent by FW"); 2272 return QDF_STATUS_E_INVAL; 2273 } 2274 2275 cu_params->cu_vdev_map[0] = 2276 cu_params_tlv->cu_vdev_map_1 & CU_VDEV_MAP_MASK; 2277 cu_params->cu_vdev_map[1] = 2278 (cu_params_tlv->cu_vdev_map_1 >> 16) & CU_VDEV_MAP_MASK; 2279 cu_params->cu_vdev_map[2] = 2280 cu_params_tlv->cu_vdev_map_2 & CU_VDEV_MAP_MASK; 2281 cu_params->cu_vdev_map[3] = 2282 (cu_params_tlv->cu_vdev_map_2 >> 16) & CU_VDEV_MAP_MASK; 2283 cu_params->cu_vdev_map[4] = 2284 cu_params_tlv->cu_vdev_map_3 & CU_VDEV_MAP_MASK; 2285 cu_params->cu_vdev_map[5] = 2286 (cu_params_tlv->cu_vdev_map_3 >> 16) & CU_VDEV_MAP_MASK; 2287 2288 /* At present MAX_LINKS_SUPPORTED are 6. 2289 * cu_vdev_map_4 which required for links 2290 * 7 and 8 is unused. 2291 */ 2292 num_bpcc_bufp = param_tlvs->num_bpcc_bufp; 2293 if (param_tlvs->num_bpcc_bufp > sizeof(cu_params->vdev_bpcc)) { 2294 wmi_err("Invalid num_bpcc_bufp:%u", num_bpcc_bufp); 2295 return QDF_STATUS_E_INVAL; 2296 } 2297 qdf_mem_copy(cu_params->vdev_bpcc, param_tlvs->bpcc_bufp, 2298 num_bpcc_bufp); 2299 2300 qdf_trace_hex_dump(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 2301 param_tlvs->bpcc_bufp, num_bpcc_bufp); 2302 2303 return QDF_STATUS_SUCCESS; 2304 } 2305 2306 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE 2307 /** 2308 * send_peer_ptqm_migrate_cmd_tlv() - send PEER ptqm migrate command to fw 2309 * @wmi_handle: wmi handle 2310 * @param: pointer to hold peer ptqm migrate parameter 2311 * 2312 * Return: QDF_STATUS_SUCCESS for success else error code 2313 */ 2314 static QDF_STATUS send_peer_ptqm_migrate_cmd_tlv( 2315 wmi_unified_t wmi_handle, 2316 struct peer_ptqm_migrate_params *param) 2317 { 2318 /* Todo: copy send_peer_delete_all_cmd_tlv */ 2319 uint16_t i = 0; 2320 wmi_buf_t buf; 2321 uint8_t *buf_ptr; 2322 wmi_mlo_primary_link_peer_migration_fixed_param *cmd; 2323 uint32_t len = sizeof(*cmd); 2324 uint16_t num_entry = 0; 2325 uint16_t max_entry_per_cmd = 0, max_entry_cnt = 0; 2326 struct peer_ptqm_migrate_entry *param_list = param->peer_list; 2327 wmi_mlo_new_primary_link_peer_info *entry; 2328 uint32_t pending_cnt = param->num_peers; 2329 2330 /* Get max entries which can be send in a single WMI command. 2331 * If no. of entries is more than max entries supported, multiple 2332 * WMI commands will be send. 2333 */ 2334 max_entry_per_cmd = (wmi_get_max_msg_len(wmi_handle) - 2335 sizeof(*cmd) - WMI_TLV_HDR_SIZE) / 2336 (sizeof(wmi_mlo_new_primary_link_peer_info)); 2337 2338 if (param->num_peers > max_entry_per_cmd) 2339 max_entry_cnt = max_entry_per_cmd; 2340 else 2341 max_entry_cnt = param->num_peers; 2342 2343 wmi_debug("Setting max entry limit as %u", max_entry_cnt); 2344 while (pending_cnt > 0) { 2345 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; 2346 if (pending_cnt >= max_entry_cnt) 2347 num_entry = max_entry_cnt; 2348 else 2349 num_entry = pending_cnt; 2350 2351 len += num_entry * sizeof(wmi_mlo_new_primary_link_peer_info); 2352 buf = wmi_buf_alloc(wmi_handle, len); 2353 if (!buf) 2354 return QDF_STATUS_E_NOMEM; 2355 2356 buf_ptr = (uint8_t *)wmi_buf_data(buf); 2357 2358 cmd = (wmi_mlo_primary_link_peer_migration_fixed_param *) 2359 wmi_buf_data(buf); 2360 WMITLV_SET_HDR( 2361 &cmd->tlv_header, 2362 WMITLV_TAG_STRUC_wmi_mlo_primary_link_peer_migration_fixed_param, 2363 WMITLV_GET_STRUCT_TLVLEN 2364 (wmi_mlo_primary_link_peer_migration_fixed_param)); 2365 buf_ptr += sizeof(*cmd); 2366 cmd->vdev_id = param->vdev_id; 2367 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 2368 num_entry * sizeof(wmi_mlo_new_primary_link_peer_info)); 2369 buf_ptr += WMI_TLV_HDR_SIZE; 2370 entry = (wmi_mlo_new_primary_link_peer_info *)buf_ptr; 2371 for (i = 0; i < num_entry; i++) { 2372 WMITLV_SET_HDR(&entry[i].tlv_header, 2373 WMITLV_TAG_STRUC_wmi_mlo_new_primary_link_peer_info, 2374 WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_new_primary_link_peer_info)); 2375 WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_ML_PEER_ID_SET( 2376 entry[i].new_link_info, 2377 param_list[i].ml_peer_id); 2378 WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_HW_LINK_ID_SET( 2379 entry[i].new_link_info, 2380 param_list[i].hw_link_id); 2381 wmi_debug("i:%d, ml_peer_id:%d, hw_link_id:%d", 2382 i, entry[i].ml_peer_id, entry[i].hw_link_id); 2383 } 2384 2385 wmi_mtrace(WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_CMDID, 2386 cmd->vdev_id, 0); 2387 2388 if (wmi_unified_cmd_send(wmi_handle, buf, len, 2389 WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_CMDID)) { 2390 wmi_err("num_entries:%d failed!", 2391 pending_cnt); 2392 wmi_buf_free(buf); 2393 param->num_peers_failed = pending_cnt; 2394 return QDF_STATUS_E_FAILURE; 2395 } 2396 wmi_debug("num_entries:%d done!", 2397 num_entry); 2398 2399 pending_cnt -= num_entry; 2400 param_list += num_entry; 2401 } 2402 2403 return QDF_STATUS_SUCCESS; 2404 } 2405 2406 static QDF_STATUS 2407 extract_peer_ptqm_migrate_evt_param_tlv( 2408 struct wmi_unified *wmi_handle, 2409 uint8_t *buf, 2410 struct peer_ptqm_migrate_event_params *params) 2411 { 2412 WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_EVENTID_param_tlvs *param_buf; 2413 wmi_mlo_primary_link_peer_migration_compl_fixed_param *ev; 2414 2415 param_buf = 2416 (WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_EVENTID_param_tlvs *)buf; 2417 if (!param_buf) { 2418 wmi_err_rl("Param_buf is NULL"); 2419 return QDF_STATUS_E_FAILURE; 2420 } 2421 2422 if (!param_buf->primary_link_peer_migration_status) { 2423 wmi_err_rl("primary_link_peer_migration_status not present in event"); 2424 return QDF_STATUS_E_FAILURE; 2425 } 2426 2427 ev = (wmi_mlo_primary_link_peer_migration_compl_fixed_param *) 2428 param_buf->fixed_param; 2429 2430 params->vdev_id = ev->vdev_id; 2431 params->num_peers = param_buf->num_primary_link_peer_migration_status; 2432 2433 return QDF_STATUS_SUCCESS; 2434 } 2435 2436 static QDF_STATUS 2437 extract_peer_entry_ptqm_migrate_evt_param_tlv( 2438 struct wmi_unified *wmi_handle, 2439 uint8_t *buf, 2440 uint32_t index, 2441 struct peer_entry_ptqm_migrate_event_params *params) 2442 { 2443 WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_EVENTID_param_tlvs *param_buf; 2444 2445 param_buf = 2446 (WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_EVENTID_param_tlvs *)buf; 2447 if (!param_buf) { 2448 wmi_err_rl("Param_buf is NULL"); 2449 return QDF_STATUS_E_FAILURE; 2450 } 2451 2452 if (index > param_buf->num_primary_link_peer_migration_status) { 2453 wmi_err_rl("Index greater than total peer entries"); 2454 return QDF_STATUS_E_FAILURE; 2455 } 2456 2457 if (!param_buf->primary_link_peer_migration_status) { 2458 wmi_err_rl("primary_link_peer_migration_status not present in event"); 2459 return QDF_STATUS_E_FAILURE; 2460 } 2461 2462 params->ml_peer_id = 2463 WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_STATUS_ML_PEER_ID_GET( 2464 param_buf->primary_link_peer_migration_status[index].status_info); 2465 2466 params->status = 2467 WMI_MLO_PRIMARY_LINK_PEER_MIGRATION_STATUS_STATUS_GET( 2468 param_buf->primary_link_peer_migration_status[index].status_info); 2469 return QDF_STATUS_SUCCESS; 2470 } 2471 #endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */ 2472 2473 void wmi_11be_attach_tlv(wmi_unified_t wmi_handle) 2474 { 2475 struct wmi_ops *ops = wmi_handle->ops; 2476 2477 wmi_11be_attach_mlo_setup_tlv(wmi_handle); 2478 ops->extract_mlo_link_set_active_resp = 2479 extract_mlo_link_set_active_resp_tlv; 2480 ops->send_mlo_link_set_active_cmd = 2481 send_mlo_link_set_active_cmd_tlv; 2482 #ifdef WLAN_FEATURE_11BE 2483 ops->send_mlo_peer_tid_to_link_map = 2484 send_mlo_peer_tid_to_link_map_cmd_tlv; 2485 ops->send_mlo_vdev_tid_to_link_map = 2486 send_mlo_vdev_tid_to_link_map_cmd_tlv; 2487 ops->send_mlo_link_state_request = 2488 send_link_state_request_cmd_tlv; 2489 ops->extract_mlo_vdev_tid_to_link_map_event = 2490 extract_mlo_vdev_tid_to_link_map_event_tlv; 2491 ops->extract_mlo_vdev_bcast_tid_to_link_map_event = 2492 extract_mlo_vdev_bcast_tid_to_link_map_event_tlv; 2493 ops->extract_mlo_link_state_event = 2494 extract_mlo_link_state_event_tlv; 2495 #endif /* WLAN_FEATURE_11BE */ 2496 ops->extract_mgmt_rx_ml_cu_params = 2497 extract_mgmt_rx_ml_cu_params_tlv; 2498 ops->send_mlo_link_removal_cmd = send_mlo_link_removal_cmd_tlv; 2499 ops->extract_mlo_link_removal_evt_fixed_param = 2500 extract_mlo_link_removal_evt_fixed_param_tlv; 2501 ops->extract_mlo_link_removal_tbtt_update = 2502 extract_mlo_link_removal_tbtt_update_tlv; 2503 ops->extract_mgmt_rx_mlo_link_removal_info = 2504 extract_mgmt_rx_mlo_link_removal_info_tlv; 2505 ops->extract_mlo_link_disable_request_evt_param = 2506 extract_mlo_link_disable_request_evt_param_tlv; 2507 ops->send_mlo_vdev_pause = 2508 send_mlo_vdev_pause_cmd_tlv; 2509 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE 2510 ops->send_peer_ptqm_migrate_cmd = send_peer_ptqm_migrate_cmd_tlv; 2511 ops->extract_peer_ptqm_migrate_event = extract_peer_ptqm_migrate_evt_param_tlv; 2512 ops->extract_peer_entry_ptqm_migrate_event = extract_peer_entry_ptqm_migrate_evt_param_tlv; 2513 #endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */ 2514 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 2515 ops->extract_mlo_link_switch_request_event = 2516 extract_mlo_link_switch_request_event_tlv; 2517 ops->send_mlo_link_switch_req_cnf_cmd = 2518 send_link_switch_request_cnf_cmd_tlv; 2519 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 2520 } 2521