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