1 /*
2 * Copyright (c) 2013-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 /**
19 * DOC: Implement API's specific to roaming component.
20 */
21
22 #include <wmi_unified_priv.h>
23 #include <wmi_unified_roam_api.h>
24 #include <wmi_unified_roam_param.h>
25 #include "wmi.h"
26 #include "wlan_roam_debug.h"
27 #include "ol_defines.h"
28 #include "wlan_cm_roam_api.h"
29 #include "wlan_mlme_api.h"
30 #include "wlan_crypto_global_api.h"
31
32 #define WMI_MAC_TO_PDEV_MAP(x) ((x) + (1))
33 #define WMI_PDEV_TO_MAC_MAP(x) ((x) - (1))
34
35 #ifdef FEATURE_LFR_SUBNET_DETECTION
36 /**
37 * send_set_gateway_params_cmd_tlv() - set gateway parameters
38 * @wmi_handle: wmi handle
39 * @req: gateway parameter update request structure
40 *
41 * This function reads the incoming @req and fill in the destination
42 * WMI structure and sends down the gateway configs down to the firmware
43 *
44 * Return: QDF_STATUS
45 */
send_set_gateway_params_cmd_tlv(wmi_unified_t wmi_handle,struct gateway_update_req_param * req)46 static QDF_STATUS send_set_gateway_params_cmd_tlv(wmi_unified_t wmi_handle,
47 struct gateway_update_req_param *req)
48 {
49 wmi_roam_subnet_change_config_fixed_param *cmd;
50 wmi_buf_t buf;
51 QDF_STATUS ret;
52 int len = sizeof(*cmd);
53
54 buf = wmi_buf_alloc(wmi_handle, len);
55 if (!buf)
56 return QDF_STATUS_E_NOMEM;
57
58 cmd = (wmi_roam_subnet_change_config_fixed_param *)wmi_buf_data(buf);
59 WMITLV_SET_HDR(&cmd->tlv_header,
60 WMITLV_TAG_STRUC_wmi_roam_subnet_change_config_fixed_param,
61 WMITLV_GET_STRUCT_TLVLEN(
62 wmi_roam_subnet_change_config_fixed_param));
63
64 cmd->vdev_id = req->vdev_id;
65 qdf_mem_copy(&cmd->inet_gw_ip_v4_addr, req->ipv4_addr,
66 QDF_IPV4_ADDR_SIZE);
67 qdf_mem_copy(&cmd->inet_gw_ip_v6_addr, req->ipv6_addr,
68 QDF_IPV6_ADDR_SIZE);
69 WMI_CHAR_ARRAY_TO_MAC_ADDR(req->gw_mac_addr.bytes,
70 &cmd->inet_gw_mac_addr);
71 cmd->max_retries = req->max_retries;
72 cmd->timeout = req->timeout;
73 cmd->num_skip_subnet_change_detection_bssid_list = 0;
74 cmd->flag = 0;
75 if (req->ipv4_addr_type)
76 WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED(cmd->flag);
77
78 if (req->ipv6_addr_type)
79 WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED(cmd->flag);
80
81 wmi_mtrace(WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID, cmd->vdev_id, 0);
82 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
83 WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID);
84 if (QDF_IS_STATUS_ERROR(ret)) {
85 wmi_err("Failed to send gw config parameter to fw, ret: %d",
86 ret);
87 wmi_buf_free(buf);
88 }
89
90 return ret;
91 }
92
wmi_lfr_subnet_detection_attach_tlv(struct wmi_unified * wmi_handle)93 void wmi_lfr_subnet_detection_attach_tlv(struct wmi_unified *wmi_handle)
94 {
95 struct wmi_ops *ops = wmi_handle->ops;
96
97 ops->send_set_gateway_params_cmd = send_set_gateway_params_cmd_tlv;
98 }
99 #endif /* FEATURE_LFR_SUBNET_DETECTION */
100
101 #ifdef FEATURE_RSSI_MONITOR
102 /**
103 * send_set_rssi_monitoring_cmd_tlv() - set rssi monitoring
104 * @wmi_handle: wmi handle
105 * @req: rssi monitoring request structure
106 *
107 * This function reads the incoming @req and fill in the destination
108 * WMI structure and send down the rssi monitoring configs down to the firmware
109 *
110 * Return: 0 on success; error number otherwise
111 */
send_set_rssi_monitoring_cmd_tlv(wmi_unified_t wmi_handle,struct rssi_monitor_param * req)112 static QDF_STATUS send_set_rssi_monitoring_cmd_tlv(wmi_unified_t wmi_handle,
113 struct rssi_monitor_param *req)
114 {
115 wmi_rssi_breach_monitor_config_fixed_param *cmd;
116 wmi_buf_t buf;
117 QDF_STATUS ret;
118 uint32_t len = sizeof(*cmd);
119
120 buf = wmi_buf_alloc(wmi_handle, len);
121 if (!buf)
122 return QDF_STATUS_E_NOMEM;
123
124 cmd = (wmi_rssi_breach_monitor_config_fixed_param *)wmi_buf_data(buf);
125 WMITLV_SET_HDR(&cmd->tlv_header,
126 WMITLV_TAG_STRUC_wmi_rssi_breach_monitor_config_fixed_param,
127 WMITLV_GET_STRUCT_TLVLEN(
128 wmi_rssi_breach_monitor_config_fixed_param));
129
130 cmd->vdev_id = req->vdev_id;
131 cmd->request_id = req->request_id;
132 cmd->lo_rssi_reenable_hysteresis = 0;
133 cmd->hi_rssi_reenable_histeresis = 0;
134 cmd->min_report_interval = 0;
135 cmd->max_num_report = 1;
136 if (req->control) {
137 /* enable one threshold for each min/max */
138 cmd->enabled_bitmap = 0x09;
139 cmd->low_rssi_breach_threshold[0] = req->min_rssi;
140 cmd->hi_rssi_breach_threshold[0] = req->max_rssi;
141 } else {
142 cmd->enabled_bitmap = 0;
143 cmd->low_rssi_breach_threshold[0] = 0;
144 cmd->hi_rssi_breach_threshold[0] = 0;
145 }
146
147 wmi_mtrace(WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID, cmd->vdev_id, 0);
148 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
149 WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID);
150 if (QDF_IS_STATUS_ERROR(ret)) {
151 wmi_err("Failed to send WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID");
152 wmi_buf_free(buf);
153 }
154
155 wmi_debug("Sent WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID to FW");
156
157 return ret;
158 }
159
wmi_rssi_monitor_attach_tlv(struct wmi_unified * wmi_handle)160 void wmi_rssi_monitor_attach_tlv(struct wmi_unified *wmi_handle)
161 {
162 struct wmi_ops *ops = wmi_handle->ops;
163
164 ops->send_set_rssi_monitoring_cmd = send_set_rssi_monitoring_cmd_tlv;
165 }
166 #endif /* FEATURE_RSSI_MONITOR */
167
168 /**
169 * send_roam_scan_offload_rssi_thresh_cmd_tlv() - set scan offload
170 * rssi threshold
171 * @wmi_handle: wmi handle
172 * @roam_req: Roaming request buffer
173 *
174 * Send WMI_ROAM_SCAN_RSSI_THRESHOLD TLV to firmware
175 *
176 * Return: QDF status
177 */
send_roam_scan_offload_rssi_thresh_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_roam_offload_scan_rssi_params * roam_req)178 static QDF_STATUS send_roam_scan_offload_rssi_thresh_cmd_tlv(
179 wmi_unified_t wmi_handle,
180 struct wlan_roam_offload_scan_rssi_params *roam_req)
181 {
182 wmi_buf_t buf = NULL;
183 QDF_STATUS status;
184 int len;
185 uint8_t *buf_ptr;
186 wmi_roam_scan_rssi_threshold_fixed_param *rssi_threshold_fp;
187 wmi_roam_scan_extended_threshold_param *ext_thresholds = NULL;
188 wmi_roam_earlystop_rssi_thres_param *early_stop_thresholds = NULL;
189 wmi_roam_dense_thres_param *dense_thresholds = NULL;
190 wmi_roam_bg_scan_roaming_param *bg_scan_params = NULL;
191 wmi_roam_data_rssi_roaming_param *data_rssi_param = NULL;
192
193 len = sizeof(wmi_roam_scan_rssi_threshold_fixed_param);
194 len += WMI_TLV_HDR_SIZE; /* TLV for ext_thresholds*/
195 len += sizeof(wmi_roam_scan_extended_threshold_param);
196 len += WMI_TLV_HDR_SIZE;
197 len += sizeof(wmi_roam_earlystop_rssi_thres_param);
198 len += WMI_TLV_HDR_SIZE; /* TLV for dense thresholds*/
199 len += sizeof(wmi_roam_dense_thres_param);
200 len += WMI_TLV_HDR_SIZE; /* TLV for BG Scan*/
201 len += sizeof(wmi_roam_bg_scan_roaming_param);
202 len += WMI_TLV_HDR_SIZE; /* TLV for data RSSI*/
203 len += sizeof(wmi_roam_data_rssi_roaming_param);
204 buf = wmi_buf_alloc(wmi_handle, len);
205 if (!buf)
206 return QDF_STATUS_E_NOMEM;
207
208 buf_ptr = (uint8_t *)wmi_buf_data(buf);
209 rssi_threshold_fp =
210 (wmi_roam_scan_rssi_threshold_fixed_param *)buf_ptr;
211 WMITLV_SET_HDR(
212 &rssi_threshold_fp->tlv_header,
213 WMITLV_TAG_STRUC_wmi_roam_scan_rssi_threshold_fixed_param,
214 WMITLV_GET_STRUCT_TLVLEN
215 (wmi_roam_scan_rssi_threshold_fixed_param));
216 /* fill in threshold values */
217 rssi_threshold_fp->vdev_id = roam_req->vdev_id;
218 rssi_threshold_fp->roam_scan_rssi_thresh = roam_req->rssi_thresh;
219 rssi_threshold_fp->roam_rssi_thresh_diff = roam_req->rssi_thresh_diff;
220 rssi_threshold_fp->hirssi_scan_max_count =
221 roam_req->hi_rssi_scan_max_count;
222 rssi_threshold_fp->hirssi_scan_delta =
223 roam_req->hi_rssi_scan_rssi_delta;
224 rssi_threshold_fp->hirssi_upper_bound = roam_req->hi_rssi_scan_rssi_ub;
225 rssi_threshold_fp->rssi_thresh_offset_5g =
226 roam_req->rssi_thresh_offset_5g;
227 rssi_threshold_fp->flags = roam_req->flags;
228
229 buf_ptr += sizeof(wmi_roam_scan_rssi_threshold_fixed_param);
230 WMITLV_SET_HDR(buf_ptr,
231 WMITLV_TAG_ARRAY_STRUC,
232 sizeof(wmi_roam_scan_extended_threshold_param));
233 buf_ptr += WMI_TLV_HDR_SIZE;
234 ext_thresholds = (wmi_roam_scan_extended_threshold_param *)buf_ptr;
235
236 ext_thresholds->penalty_threshold_5g = roam_req->penalty_threshold_5g;
237 if (roam_req->raise_rssi_thresh_5g >= WMI_NOISE_FLOOR_DBM_DEFAULT)
238 ext_thresholds->boost_threshold_5g =
239 roam_req->boost_threshold_5g;
240
241 ext_thresholds->boost_algorithm_5g =
242 WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR;
243 ext_thresholds->boost_factor_5g = roam_req->raise_factor_5g;
244 ext_thresholds->penalty_algorithm_5g =
245 WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR;
246 ext_thresholds->penalty_factor_5g = roam_req->drop_factor_5g;
247 ext_thresholds->max_boost_5g = roam_req->max_raise_rssi_5g;
248 ext_thresholds->max_penalty_5g = roam_req->max_drop_rssi_5g;
249 ext_thresholds->good_rssi_threshold = roam_req->good_rssi_threshold;
250
251 WMITLV_SET_HDR(&ext_thresholds->tlv_header,
252 WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param,
253 WMITLV_GET_STRUCT_TLVLEN
254 (wmi_roam_scan_extended_threshold_param));
255 buf_ptr += sizeof(wmi_roam_scan_extended_threshold_param);
256 WMITLV_SET_HDR(buf_ptr,
257 WMITLV_TAG_ARRAY_STRUC,
258 sizeof(wmi_roam_earlystop_rssi_thres_param));
259 buf_ptr += WMI_TLV_HDR_SIZE;
260 early_stop_thresholds = (wmi_roam_earlystop_rssi_thres_param *)buf_ptr;
261 early_stop_thresholds->roam_earlystop_thres_min =
262 roam_req->roam_earlystop_thres_min;
263 early_stop_thresholds->roam_earlystop_thres_max =
264 roam_req->roam_earlystop_thres_max;
265 WMITLV_SET_HDR(&early_stop_thresholds->tlv_header,
266 WMITLV_TAG_STRUC_wmi_roam_earlystop_rssi_thres_param,
267 WMITLV_GET_STRUCT_TLVLEN
268 (wmi_roam_earlystop_rssi_thres_param));
269
270 buf_ptr += sizeof(wmi_roam_earlystop_rssi_thres_param);
271 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
272 sizeof(wmi_roam_dense_thres_param));
273 buf_ptr += WMI_TLV_HDR_SIZE;
274 dense_thresholds = (wmi_roam_dense_thres_param *)buf_ptr;
275 dense_thresholds->roam_dense_rssi_thres_offset =
276 roam_req->dense_rssi_thresh_offset;
277 dense_thresholds->roam_dense_min_aps = roam_req->dense_min_aps_cnt;
278 dense_thresholds->roam_dense_traffic_thres =
279 roam_req->traffic_threshold;
280 dense_thresholds->roam_dense_status = roam_req->initial_dense_status;
281 WMITLV_SET_HDR(&dense_thresholds->tlv_header,
282 WMITLV_TAG_STRUC_wmi_roam_dense_thres_param,
283 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_dense_thres_param));
284
285 buf_ptr += sizeof(wmi_roam_dense_thres_param);
286 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
287 sizeof(wmi_roam_bg_scan_roaming_param));
288 buf_ptr += WMI_TLV_HDR_SIZE;
289 bg_scan_params = (wmi_roam_bg_scan_roaming_param *)buf_ptr;
290 bg_scan_params->roam_bg_scan_bad_rssi_thresh =
291 roam_req->bg_scan_bad_rssi_thresh;
292 bg_scan_params->roam_bg_scan_client_bitmap =
293 roam_req->bg_scan_client_bitmap;
294 bg_scan_params->bad_rssi_thresh_offset_2g =
295 roam_req->roam_bad_rssi_thresh_offset_2g;
296
297 bg_scan_params->flags = 0;
298 if (roam_req->roam_bad_rssi_thresh_offset_2g)
299 bg_scan_params->flags |= WMI_ROAM_BG_SCAN_FLAGS_2G_TO_5G_ONLY;
300 WMITLV_SET_HDR(&bg_scan_params->tlv_header,
301 WMITLV_TAG_STRUC_wmi_roam_bg_scan_roaming_param,
302 WMITLV_GET_STRUCT_TLVLEN
303 (wmi_roam_bg_scan_roaming_param));
304
305 buf_ptr += sizeof(wmi_roam_bg_scan_roaming_param);
306 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
307 sizeof(wmi_roam_data_rssi_roaming_param));
308 buf_ptr += WMI_TLV_HDR_SIZE;
309 data_rssi_param = (wmi_roam_data_rssi_roaming_param *)buf_ptr;
310 data_rssi_param->flags =
311 roam_req->roam_data_rssi_threshold_triggers;
312 data_rssi_param->roam_data_rssi_thres =
313 roam_req->roam_data_rssi_threshold;
314 data_rssi_param->rx_inactivity_ms =
315 roam_req->rx_data_inactivity_time;
316 WMITLV_SET_HDR(&data_rssi_param->tlv_header,
317 WMITLV_TAG_STRUC_wmi_roam_data_rssi_roaming_param,
318 WMITLV_GET_STRUCT_TLVLEN
319 (wmi_roam_data_rssi_roaming_param));
320 wmi_debug("vdev %d Data rssi threshold: %d, triggers: 0x%x, rx time: %d, rssi_thresh:%d",
321 rssi_threshold_fp->vdev_id,
322 data_rssi_param->roam_data_rssi_thres,
323 data_rssi_param->flags,
324 data_rssi_param->rx_inactivity_ms,
325 rssi_threshold_fp->roam_scan_rssi_thresh);
326
327 wmi_mtrace(WMI_ROAM_SCAN_RSSI_THRESHOLD, NO_SESSION, 0);
328 status = wmi_unified_cmd_send(wmi_handle, buf,
329 len, WMI_ROAM_SCAN_RSSI_THRESHOLD);
330 if (QDF_IS_STATUS_ERROR(status)) {
331 wmi_err("cmd WMI_ROAM_SCAN_RSSI_THRESHOLD returned Error %d",
332 status);
333 wmi_buf_free(buf);
334 }
335
336 return status;
337 }
338
339 /**
340 * send_roam_scan_offload_scan_period_cmd_tlv() - set roam offload scan period
341 * @wmi_handle: wmi handle
342 * @param: roam scan parameters to be sent to firmware
343 *
344 * Send WMI_ROAM_SCAN_PERIOD parameters to fw.
345 *
346 * Return: QDF status
347 */
348 static QDF_STATUS
send_roam_scan_offload_scan_period_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_roam_scan_period_params * param)349 send_roam_scan_offload_scan_period_cmd_tlv(
350 wmi_unified_t wmi_handle,
351 struct wlan_roam_scan_period_params *param)
352 {
353 QDF_STATUS status;
354 wmi_buf_t buf = NULL;
355 int len;
356 uint8_t *buf_ptr;
357 wmi_roam_scan_period_fixed_param *scan_period_fp;
358
359 /* Send scan period values */
360 len = sizeof(wmi_roam_scan_period_fixed_param);
361 buf = wmi_buf_alloc(wmi_handle, len);
362 if (!buf)
363 return QDF_STATUS_E_NOMEM;
364
365 buf_ptr = (uint8_t *)wmi_buf_data(buf);
366 scan_period_fp = (wmi_roam_scan_period_fixed_param *)buf_ptr;
367 WMITLV_SET_HDR(&scan_period_fp->tlv_header,
368 WMITLV_TAG_STRUC_wmi_roam_scan_period_fixed_param,
369 WMITLV_GET_STRUCT_TLVLEN
370 (wmi_roam_scan_period_fixed_param));
371 /* fill in scan period values */
372 scan_period_fp->vdev_id = param->vdev_id;
373 scan_period_fp->roam_scan_period = param->scan_period;
374 scan_period_fp->roam_scan_age = param->scan_age;
375 scan_period_fp->inactivity_time_period =
376 param->roam_scan_inactivity_time;
377 scan_period_fp->roam_inactive_count =
378 param->roam_inactive_data_packet_count;
379 /* Firmware expects the full scan period in msec whereas host
380 * provides the same in seconds.
381 * Convert it to msec and send to firmware
382 */
383 scan_period_fp->roam_full_scan_period = param->full_scan_period * 1000;
384
385 wmi_debug("roam_scan_period=%d, roam_scan_age=%d, full_scan_period= %u",
386 scan_period_fp->roam_scan_period,
387 scan_period_fp->roam_scan_age,
388 scan_period_fp->roam_full_scan_period);
389
390 wmi_debug("inactiviy time:%d inactive cnt:%d",
391 scan_period_fp->inactivity_time_period,
392 scan_period_fp->roam_inactive_count);
393
394 wmi_mtrace(WMI_ROAM_SCAN_PERIOD, NO_SESSION, 0);
395 status = wmi_unified_cmd_send(wmi_handle, buf, len,
396 WMI_ROAM_SCAN_PERIOD);
397 if (QDF_IS_STATUS_ERROR(status)) {
398 wmi_buf_free(buf);
399 return status;
400 }
401
402 return QDF_STATUS_SUCCESS;
403 }
404
send_roam_mawc_params_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_roam_mawc_params * params)405 static QDF_STATUS send_roam_mawc_params_cmd_tlv(
406 wmi_unified_t wmi_handle,
407 struct wlan_roam_mawc_params *params)
408 {
409 wmi_buf_t buf = NULL;
410 QDF_STATUS status;
411 int len;
412 uint8_t *buf_ptr;
413 wmi_roam_configure_mawc_cmd_fixed_param *wmi_roam_mawc_params;
414
415 len = sizeof(*wmi_roam_mawc_params);
416 buf = wmi_buf_alloc(wmi_handle, len);
417 if (!buf)
418 return QDF_STATUS_E_NOMEM;
419
420 buf_ptr = (uint8_t *)wmi_buf_data(buf);
421 wmi_roam_mawc_params =
422 (wmi_roam_configure_mawc_cmd_fixed_param *)buf_ptr;
423 WMITLV_SET_HDR(&wmi_roam_mawc_params->tlv_header,
424 WMITLV_TAG_STRUC_wmi_roam_configure_mawc_cmd_fixed_param,
425 WMITLV_GET_STRUCT_TLVLEN
426 (wmi_roam_configure_mawc_cmd_fixed_param));
427 wmi_roam_mawc_params->vdev_id = params->vdev_id;
428 if (params->enable)
429 wmi_roam_mawc_params->enable = 1;
430 else
431 wmi_roam_mawc_params->enable = 0;
432 wmi_roam_mawc_params->traffic_load_threshold =
433 params->traffic_load_threshold;
434 wmi_roam_mawc_params->best_ap_rssi_threshold =
435 params->best_ap_rssi_threshold;
436 wmi_roam_mawc_params->rssi_stationary_high_adjust =
437 params->rssi_stationary_high_adjust;
438 wmi_roam_mawc_params->rssi_stationary_low_adjust =
439 params->rssi_stationary_low_adjust;
440 wmi_debug("MAWC roam en=%d, vdev=%d, tr=%d, ap=%d, high=%d, low=%d",
441 wmi_roam_mawc_params->enable, wmi_roam_mawc_params->vdev_id,
442 wmi_roam_mawc_params->traffic_load_threshold,
443 wmi_roam_mawc_params->best_ap_rssi_threshold,
444 wmi_roam_mawc_params->rssi_stationary_high_adjust,
445 wmi_roam_mawc_params->rssi_stationary_low_adjust);
446
447 wmi_mtrace(WMI_ROAM_CONFIGURE_MAWC_CMDID, NO_SESSION, 0);
448 status = wmi_unified_cmd_send(wmi_handle, buf,
449 len, WMI_ROAM_CONFIGURE_MAWC_CMDID);
450 if (QDF_IS_STATUS_ERROR(status)) {
451 wmi_err("WMI_ROAM_CONFIGURE_MAWC_CMDID failed, Error %d",
452 status);
453 wmi_buf_free(buf);
454 return status;
455 }
456
457 return QDF_STATUS_SUCCESS;
458 }
459
460 /**
461 * send_roam_scan_filter_cmd_tlv() - Filter to be applied while roaming
462 * @wmi_handle: wmi handle
463 * @roam_req: Request which contains the filters
464 *
465 * There are filters such as allowlist, denylist and preferred
466 * list that need to be applied to the scan results to form the
467 * probable candidates for roaming.
468 *
469 * Return: Return success upon successfully passing the
470 * parameters to the firmware, otherwise failure.
471 */
send_roam_scan_filter_cmd_tlv(wmi_unified_t wmi_handle,struct roam_scan_filter_params * roam_req)472 static QDF_STATUS send_roam_scan_filter_cmd_tlv(wmi_unified_t wmi_handle,
473 struct roam_scan_filter_params *roam_req)
474 {
475 wmi_buf_t buf = NULL;
476 QDF_STATUS status;
477 uint32_t i;
478 uint32_t len, blist_len = 0;
479 uint8_t *buf_ptr;
480 wmi_roam_filter_fixed_param *roam_filter;
481 uint8_t *bssid_src_ptr = NULL;
482 wmi_mac_addr *bssid_dst_ptr = NULL;
483 wmi_ssid *ssid_ptr = NULL;
484 uint32_t *bssid_preferred_factor_ptr = NULL;
485 wmi_roam_lca_disallow_config_tlv_param *blist_param;
486 wmi_roam_rssi_rejection_oce_config_param *rssi_rej;
487
488 len = sizeof(wmi_roam_filter_fixed_param);
489
490 len += WMI_TLV_HDR_SIZE;
491 if (roam_req->num_bssid_deny_list)
492 len += roam_req->num_bssid_deny_list * sizeof(wmi_mac_addr);
493 len += WMI_TLV_HDR_SIZE;
494 if (roam_req->num_ssid_allow_list)
495 len += roam_req->num_ssid_allow_list * sizeof(wmi_ssid);
496 len += 2 * WMI_TLV_HDR_SIZE;
497 if (roam_req->num_bssid_preferred_list) {
498 len += (roam_req->num_bssid_preferred_list *
499 sizeof(wmi_mac_addr));
500 len += roam_req->num_bssid_preferred_list * sizeof(uint32_t);
501 }
502 len += WMI_TLV_HDR_SIZE;
503 if (roam_req->lca_disallow_config_present) {
504 len += sizeof(*blist_param);
505 blist_len = sizeof(*blist_param);
506 }
507
508 len += WMI_TLV_HDR_SIZE;
509 if (roam_req->num_rssi_rejection_ap)
510 len += roam_req->num_rssi_rejection_ap * sizeof(*rssi_rej);
511
512 buf = wmi_buf_alloc(wmi_handle, len);
513 if (!buf)
514 return QDF_STATUS_E_NOMEM;
515
516 buf_ptr = (u_int8_t *)wmi_buf_data(buf);
517 roam_filter = (wmi_roam_filter_fixed_param *)buf_ptr;
518 WMITLV_SET_HDR(&roam_filter->tlv_header,
519 WMITLV_TAG_STRUC_wmi_roam_filter_fixed_param,
520 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_filter_fixed_param));
521 /* fill in fixed values */
522 roam_filter->vdev_id = roam_req->vdev_id;
523 roam_filter->flags = 0;
524 roam_filter->op_bitmap = roam_req->op_bitmap;
525 roam_filter->num_bssid_black_list = roam_req->num_bssid_deny_list;
526 roam_filter->num_ssid_white_list = roam_req->num_ssid_allow_list;
527 roam_filter->num_bssid_preferred_list =
528 roam_req->num_bssid_preferred_list;
529 roam_filter->num_rssi_rejection_ap =
530 roam_req->num_rssi_rejection_ap;
531 roam_filter->delta_rssi = roam_req->delta_rssi;
532 buf_ptr += sizeof(wmi_roam_filter_fixed_param);
533
534 WMITLV_SET_HDR((buf_ptr),
535 WMITLV_TAG_ARRAY_FIXED_STRUC,
536 (roam_req->num_bssid_deny_list * sizeof(wmi_mac_addr)));
537 bssid_src_ptr = (uint8_t *)&roam_req->bssid_avoid_list;
538 bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE);
539 for (i = 0; i < roam_req->num_bssid_deny_list; i++) {
540 WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr, bssid_dst_ptr);
541 bssid_src_ptr += ATH_MAC_LEN;
542 bssid_dst_ptr++;
543 }
544 buf_ptr += WMI_TLV_HDR_SIZE +
545 (roam_req->num_bssid_deny_list * sizeof(wmi_mac_addr));
546 WMITLV_SET_HDR((buf_ptr),
547 WMITLV_TAG_ARRAY_FIXED_STRUC,
548 (roam_req->num_ssid_allow_list * sizeof(wmi_ssid)));
549 ssid_ptr = (wmi_ssid *)(buf_ptr + WMI_TLV_HDR_SIZE);
550 for (i = 0; i < roam_req->num_ssid_allow_list; i++) {
551 qdf_mem_copy(&ssid_ptr->ssid,
552 &roam_req->ssid_allowed_list[i].ssid,
553 roam_req->ssid_allowed_list[i].length);
554 ssid_ptr->ssid_len = roam_req->ssid_allowed_list[i].length;
555 ssid_ptr++;
556 }
557 buf_ptr += WMI_TLV_HDR_SIZE + (roam_req->num_ssid_allow_list *
558 sizeof(wmi_ssid));
559 WMITLV_SET_HDR((buf_ptr),
560 WMITLV_TAG_ARRAY_FIXED_STRUC,
561 (roam_req->num_bssid_preferred_list * sizeof(wmi_mac_addr)));
562 bssid_src_ptr = (uint8_t *)&roam_req->bssid_favored;
563 bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE);
564 for (i = 0; i < roam_req->num_bssid_preferred_list; i++) {
565 WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr,
566 (wmi_mac_addr *)bssid_dst_ptr);
567 bssid_src_ptr += ATH_MAC_LEN;
568 bssid_dst_ptr++;
569 }
570 buf_ptr += WMI_TLV_HDR_SIZE +
571 (roam_req->num_bssid_preferred_list * sizeof(wmi_mac_addr));
572 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
573 (roam_req->num_bssid_preferred_list * sizeof(uint32_t)));
574 bssid_preferred_factor_ptr = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
575 for (i = 0; i < roam_req->num_bssid_preferred_list; i++) {
576 *bssid_preferred_factor_ptr =
577 roam_req->bssid_favored_factor[i];
578 bssid_preferred_factor_ptr++;
579 }
580 buf_ptr += WMI_TLV_HDR_SIZE +
581 (roam_req->num_bssid_preferred_list * sizeof(uint32_t));
582
583 WMITLV_SET_HDR(buf_ptr,
584 WMITLV_TAG_ARRAY_STRUC, blist_len);
585 buf_ptr += WMI_TLV_HDR_SIZE;
586 if (roam_req->lca_disallow_config_present) {
587 blist_param =
588 (wmi_roam_lca_disallow_config_tlv_param *)buf_ptr;
589 WMITLV_SET_HDR(&blist_param->tlv_header,
590 WMITLV_TAG_STRUC_wmi_roam_lca_disallow_config_tlv_param,
591 WMITLV_GET_STRUCT_TLVLEN(
592 wmi_roam_lca_disallow_config_tlv_param));
593
594 blist_param->disallow_duration = roam_req->disallow_duration;
595 blist_param->rssi_channel_penalization =
596 roam_req->rssi_channel_penalization;
597 blist_param->num_disallowed_aps = roam_req->num_disallowed_aps;
598 blist_param->disallow_lca_enable_source_bitmap =
599 (WMI_ROAM_LCA_DISALLOW_SOURCE_PER |
600 WMI_ROAM_LCA_DISALLOW_SOURCE_BACKGROUND);
601 buf_ptr += (sizeof(wmi_roam_lca_disallow_config_tlv_param));
602 }
603
604 WMITLV_SET_HDR(buf_ptr,
605 WMITLV_TAG_ARRAY_STRUC,
606 (roam_req->num_rssi_rejection_ap * sizeof(*rssi_rej)));
607 buf_ptr += WMI_TLV_HDR_SIZE;
608 for (i = 0; i < roam_req->num_rssi_rejection_ap; i++) {
609 rssi_rej =
610 (wmi_roam_rssi_rejection_oce_config_param *)buf_ptr;
611
612 WMITLV_SET_HDR(&rssi_rej->tlv_header,
613 WMITLV_TAG_STRUC_wmi_roam_rssi_rejection_oce_config_param,
614 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_rssi_rejection_oce_config_param));
615
616 WMI_CHAR_ARRAY_TO_MAC_ADDR(
617 roam_req->rssi_rejection_ap[i].bssid.bytes,
618 &rssi_rej->bssid);
619 rssi_rej->remaining_disallow_duration =
620 roam_req->rssi_rejection_ap[i].reject_duration;
621 rssi_rej->requested_rssi =
622 (int32_t)roam_req->rssi_rejection_ap[i].expected_rssi;
623 buf_ptr +=
624 (sizeof(wmi_roam_rssi_rejection_oce_config_param));
625 }
626
627 wmi_mtrace(WMI_ROAM_FILTER_CMDID, NO_SESSION, 0);
628 status = wmi_unified_cmd_send(wmi_handle, buf,
629 len, WMI_ROAM_FILTER_CMDID);
630 if (QDF_IS_STATUS_ERROR(status)) {
631 wmi_err("cmd WMI_ROAM_FILTER_CMDID returned Error %d",
632 status);
633 wmi_buf_free(buf);
634 }
635
636 return status;
637 }
638
639 #ifdef FEATURE_WLAN_ESE
640 /**
641 * send_plm_stop_cmd_tlv() - plm stop request
642 * @wmi_handle: wmi handle
643 * @plm: plm request parameters
644 *
645 * This function request FW to stop PLM.
646 *
647 * Return: CDF status
648 */
send_plm_stop_cmd_tlv(wmi_unified_t wmi_handle,const struct plm_req_params * plm)649 static QDF_STATUS send_plm_stop_cmd_tlv(wmi_unified_t wmi_handle,
650 const struct plm_req_params *plm)
651 {
652 wmi_vdev_plmreq_stop_cmd_fixed_param *cmd;
653 int32_t len;
654 wmi_buf_t buf;
655 uint8_t *buf_ptr;
656 int ret;
657
658 len = sizeof(*cmd);
659 buf = wmi_buf_alloc(wmi_handle, len);
660 if (!buf)
661 return QDF_STATUS_E_NOMEM;
662
663 cmd = (wmi_vdev_plmreq_stop_cmd_fixed_param *)wmi_buf_data(buf);
664
665 buf_ptr = (uint8_t *)cmd;
666
667 WMITLV_SET_HDR(&cmd->tlv_header,
668 WMITLV_TAG_STRUC_wmi_vdev_plmreq_stop_cmd_fixed_param,
669 WMITLV_GET_STRUCT_TLVLEN
670 (wmi_vdev_plmreq_stop_cmd_fixed_param));
671
672 cmd->vdev_id = plm->vdev_id;
673
674 cmd->meas_token = plm->meas_token;
675 wmi_debug("vdev %d meas token %d", cmd->vdev_id, cmd->meas_token);
676
677 wmi_mtrace(WMI_VDEV_PLMREQ_STOP_CMDID, cmd->vdev_id, 0);
678 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
679 WMI_VDEV_PLMREQ_STOP_CMDID);
680 if (ret) {
681 wmi_err("Failed to send plm stop wmi cmd");
682 wmi_buf_free(buf);
683 return QDF_STATUS_E_FAILURE;
684 }
685
686 return QDF_STATUS_SUCCESS;
687 }
688
689 /**
690 * send_plm_start_cmd_tlv() - plm start request
691 * @wmi_handle: wmi handle
692 * @plm: plm request parameters
693 *
694 * This function request FW to start PLM.
695 *
696 * Return: CDF status
697 */
send_plm_start_cmd_tlv(wmi_unified_t wmi_handle,const struct plm_req_params * plm)698 static QDF_STATUS send_plm_start_cmd_tlv(wmi_unified_t wmi_handle,
699 const struct plm_req_params *plm)
700 {
701 wmi_vdev_plmreq_start_cmd_fixed_param *cmd;
702 uint32_t *channel_list;
703 int32_t len;
704 wmi_buf_t buf;
705 uint8_t *buf_ptr;
706 uint8_t count;
707 int ret;
708
709 /* TLV place holder for channel_list */
710 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
711 len += sizeof(uint32_t) * plm->plm_num_ch;
712
713 buf = wmi_buf_alloc(wmi_handle, len);
714 if (!buf)
715 return QDF_STATUS_E_NOMEM;
716
717 cmd = (wmi_vdev_plmreq_start_cmd_fixed_param *)wmi_buf_data(buf);
718
719 buf_ptr = (uint8_t *)cmd;
720
721 WMITLV_SET_HDR(&cmd->tlv_header,
722 WMITLV_TAG_STRUC_wmi_vdev_plmreq_start_cmd_fixed_param,
723 WMITLV_GET_STRUCT_TLVLEN
724 (wmi_vdev_plmreq_start_cmd_fixed_param));
725
726 cmd->vdev_id = plm->vdev_id;
727
728 cmd->meas_token = plm->meas_token;
729 cmd->dialog_token = plm->diag_token;
730 cmd->number_bursts = plm->num_bursts;
731 cmd->burst_interval = WMI_SEC_TO_MSEC(plm->burst_int);
732 cmd->off_duration = plm->meas_duration;
733 cmd->burst_cycle = plm->burst_len;
734 cmd->tx_power = plm->desired_tx_pwr;
735 WMI_CHAR_ARRAY_TO_MAC_ADDR(plm->mac_addr.bytes, &cmd->dest_mac);
736 cmd->num_chans = plm->plm_num_ch;
737
738 buf_ptr += sizeof(wmi_vdev_plmreq_start_cmd_fixed_param);
739
740 wmi_debug("vdev: %d measu token: %d dialog_token: %d number_bursts: %d burst_interval: %d off_duration: %d burst_cycle: %d tx_power: %d Number of channels: %d",
741 cmd->vdev_id, cmd->meas_token, cmd->dialog_token,
742 cmd->number_bursts, cmd->burst_interval, cmd->off_duration,
743 cmd->burst_cycle, cmd->tx_power, cmd->num_chans);
744
745 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
746 (cmd->num_chans * sizeof(uint32_t)));
747
748 buf_ptr += WMI_TLV_HDR_SIZE;
749 if (cmd->num_chans) {
750 channel_list = (uint32_t *)buf_ptr;
751 for (count = 0; count < cmd->num_chans; count++) {
752 channel_list[count] = plm->plm_ch_freq_list[count];
753 wmi_debug("Ch[%d]: %d MHz", count, channel_list[count]);
754 }
755 buf_ptr += cmd->num_chans * sizeof(uint32_t);
756 }
757
758 wmi_mtrace(WMI_VDEV_PLMREQ_START_CMDID, cmd->vdev_id, 0);
759 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
760 WMI_VDEV_PLMREQ_START_CMDID);
761 if (ret) {
762 wmi_err("Failed to send plm start wmi cmd");
763 wmi_buf_free(buf);
764 return QDF_STATUS_E_FAILURE;
765 }
766
767 return QDF_STATUS_SUCCESS;
768 }
769
wmi_ese_attach_tlv(wmi_unified_t wmi_handle)770 void wmi_ese_attach_tlv(wmi_unified_t wmi_handle)
771 {
772 struct wmi_ops *ops = wmi_handle->ops;
773
774 ops->send_plm_stop_cmd = send_plm_stop_cmd_tlv;
775 ops->send_plm_start_cmd = send_plm_start_cmd_tlv;
776 }
777 #endif /* FEATURE_WLAN_ESE */
778
779 /**
780 * convert_roam_trigger_reason() - Function to convert unified Roam trigger
781 * enum to TLV specific WMI_ROAM_TRIGGER_REASON_ID
782 * @trigger_reason: Roam trigger reason
783 *
784 * Return: WMI roam trigger reason
785 */
786 static uint32_t
convert_roam_trigger_reason(enum roam_trigger_reason trigger_reason)787 convert_roam_trigger_reason(enum roam_trigger_reason trigger_reason)
788 {
789 switch (trigger_reason) {
790 case ROAM_TRIGGER_REASON_NONE:
791 return WMI_ROAM_TRIGGER_REASON_NONE;
792 case ROAM_TRIGGER_REASON_PER:
793 return WMI_ROAM_TRIGGER_REASON_PER;
794 case ROAM_TRIGGER_REASON_BMISS:
795 return WMI_ROAM_TRIGGER_REASON_BMISS;
796 case ROAM_TRIGGER_REASON_LOW_RSSI:
797 return WMI_ROAM_TRIGGER_REASON_LOW_RSSI;
798 case ROAM_TRIGGER_REASON_HIGH_RSSI:
799 return WMI_ROAM_TRIGGER_REASON_HIGH_RSSI;
800 case ROAM_TRIGGER_REASON_PERIODIC:
801 return WMI_ROAM_TRIGGER_REASON_PERIODIC;
802 case ROAM_TRIGGER_REASON_MAWC:
803 return WMI_ROAM_TRIGGER_REASON_MAWC;
804 case ROAM_TRIGGER_REASON_DENSE:
805 return WMI_ROAM_TRIGGER_REASON_DENSE;
806 case ROAM_TRIGGER_REASON_BACKGROUND:
807 return WMI_ROAM_TRIGGER_REASON_BACKGROUND;
808 case ROAM_TRIGGER_REASON_FORCED:
809 return WMI_ROAM_TRIGGER_REASON_FORCED;
810 case ROAM_TRIGGER_REASON_BTM:
811 return WMI_ROAM_TRIGGER_REASON_BTM;
812 case ROAM_TRIGGER_REASON_UNIT_TEST:
813 return WMI_ROAM_TRIGGER_REASON_UNIT_TEST;
814 case ROAM_TRIGGER_REASON_BSS_LOAD:
815 return WMI_ROAM_TRIGGER_REASON_BSS_LOAD;
816 case ROAM_TRIGGER_REASON_DEAUTH:
817 return WMI_ROAM_TRIGGER_REASON_DEAUTH;
818 case ROAM_TRIGGER_REASON_IDLE:
819 return WMI_ROAM_TRIGGER_REASON_IDLE;
820 case ROAM_TRIGGER_REASON_STA_KICKOUT:
821 return WMI_ROAM_TRIGGER_REASON_STA_KICKOUT;
822 case ROAM_TRIGGER_REASON_ESS_RSSI:
823 return WMI_ROAM_TRIGGER_REASON_ESS_RSSI;
824 case ROAM_TRIGGER_REASON_WTC_BTM:
825 return WMI_ROAM_TRIGGER_REASON_WTC_BTM;
826 case ROAM_TRIGGER_REASON_PMK_TIMEOUT:
827 return WMI_ROAM_TRIGGER_REASON_PMK_TIMEOUT;
828 case ROAM_TRIGGER_REASON_BTC:
829 return WMI_ROAM_TRIGGER_REASON_BTC;
830 case ROAM_TRIGGER_REASON_MAX:
831 return WMI_ROAM_TRIGGER_REASON_MAX;
832 default:
833 return WMI_ROAM_TRIGGER_REASON_NONE;
834 }
835 }
836
837 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD)
wmi_get_roam_event_reason_string(uint32_t reason)838 static char *wmi_get_roam_event_reason_string(uint32_t reason)
839 {
840 switch (reason) {
841 case WMI_ROAM_REASON_INVALID:
842 return "Default";
843 case WMI_ROAM_REASON_BETTER_AP:
844 return "Better AP";
845 case WMI_ROAM_REASON_BMISS:
846 return "BMISS";
847 case WMI_ROAM_REASON_LOW_RSSI:
848 return "Low Rssi";
849 case WMI_ROAM_REASON_SUITABLE_AP:
850 return "Suitable AP";
851 case WMI_ROAM_REASON_HO_FAILED:
852 return "Hand-off Failed";
853 case WMI_ROAM_REASON_INVOKE_ROAM_FAIL:
854 return "Roam Invoke failed";
855 case WMI_ROAM_REASON_RSO_STATUS:
856 return "RSO status";
857 case WMI_ROAM_REASON_BTM:
858 return "BTM";
859 case WMI_ROAM_REASON_DEAUTH:
860 return "Deauth";
861 default:
862 return "Invalid";
863 }
864
865 return "Invalid";
866 }
867
868 static enum roam_reason
wmi_convert_fw_reason_to_cm_reason(uint32_t reason)869 wmi_convert_fw_reason_to_cm_reason(uint32_t reason)
870 {
871 switch (reason) {
872 case WMI_ROAM_REASON_INVALID:
873 return ROAM_REASON_INVALID;
874 case WMI_ROAM_REASON_BETTER_AP:
875 return ROAM_REASON_BETTER_AP;
876 case WMI_ROAM_REASON_BMISS:
877 return ROAM_REASON_BMISS;
878 case WMI_ROAM_REASON_LOW_RSSI:
879 return ROAM_REASON_LOW_RSSI;
880 case WMI_ROAM_REASON_SUITABLE_AP:
881 return ROAM_REASON_SUITABLE_AP;
882 case WMI_ROAM_REASON_HO_FAILED:
883 return ROAM_REASON_HO_FAILED;
884 case WMI_ROAM_REASON_INVOKE_ROAM_FAIL:
885 return ROAM_REASON_INVOKE_ROAM_FAIL;
886 case WMI_ROAM_REASON_RSO_STATUS:
887 return ROAM_REASON_RSO_STATUS;
888 case WMI_ROAM_REASON_BTM:
889 return ROAM_REASON_BTM;
890 case WMI_ROAM_REASON_DEAUTH:
891 return ROAM_REASON_DEAUTH;
892 default:
893 return ROAM_REASON_INVALID;
894 }
895
896 return ROAM_REASON_INVALID;
897 }
898
899 static enum cm_roam_notif
wmi_convert_fw_notif_to_cm_notif(uint32_t fw_notif)900 wmi_convert_fw_notif_to_cm_notif(uint32_t fw_notif)
901 {
902 switch (fw_notif) {
903 case WMI_ROAM_NOTIF_ROAM_START:
904 return CM_ROAM_NOTIF_ROAM_START;
905 case WMI_ROAM_NOTIF_ROAM_ABORT:
906 return CM_ROAM_NOTIF_ROAM_ABORT;
907 case WMI_ROAM_NOTIF_ROAM_REASSOC:
908 return CM_ROAM_NOTIF_ROAM_REASSOC;
909 case WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS:
910 return CM_ROAM_NOTIF_SCAN_MODE_SUCCESS;
911 case WMI_ROAM_NOTIF_SCAN_MODE_FAIL:
912 return CM_ROAM_NOTIF_SCAN_MODE_FAIL;
913 case WMI_ROAM_NOTIF_DISCONNECT:
914 return CM_ROAM_NOTIF_DISCONNECT;
915 case WMI_ROAM_NOTIF_SUBNET_CHANGED:
916 return CM_ROAM_NOTIF_SUBNET_CHANGED;
917 case WMI_ROAM_NOTIF_SCAN_START:
918 return CM_ROAM_NOTIF_SCAN_START;
919 case WMI_ROAM_NOTIF_DEAUTH_RECV:
920 return CM_ROAM_NOTIF_DEAUTH_RECV;
921 case WMI_ROAM_NOTIF_DISASSOC_RECV:
922 return CM_ROAM_NOTIF_DISASSOC_RECV;
923 case WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS_WITH_HO_FAIL:
924 return CM_ROAM_NOTIF_HO_FAIL;
925 case WMI_ROAM_NOTIF_SCAN_END:
926 return CM_ROAM_NOTIF_SCAN_END;
927 default:
928 return CM_ROAM_NOTIF_INVALID;
929 }
930
931 return CM_ROAM_NOTIF_INVALID;
932 }
933
934 static void
wmi_extract_pdev_hw_mode_trans_ind(wmi_pdev_hw_mode_transition_event_fixed_param * fixed_param,wmi_pdev_set_hw_mode_response_vdev_mac_entry * vdev_mac_entry,struct cm_hw_mode_trans_ind * hw_mode_trans_ind)935 wmi_extract_pdev_hw_mode_trans_ind(
936 wmi_pdev_hw_mode_transition_event_fixed_param *fixed_param,
937 wmi_pdev_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry,
938 struct cm_hw_mode_trans_ind *hw_mode_trans_ind)
939 {
940 uint32_t i;
941
942 if (fixed_param->num_vdev_mac_entries > MAX_VDEV_SUPPORTED) {
943 wmi_err("Number of Vdev mac entries %d exceeded max vdev supported %d",
944 fixed_param->num_vdev_mac_entries,
945 MAX_VDEV_SUPPORTED);
946 return;
947 }
948 hw_mode_trans_ind->old_hw_mode_index = fixed_param->old_hw_mode_index;
949 hw_mode_trans_ind->new_hw_mode_index = fixed_param->new_hw_mode_index;
950 hw_mode_trans_ind->num_vdev_mac_entries =
951 fixed_param->num_vdev_mac_entries;
952 wmi_debug("old_hw_mode_index:%d new_hw_mode_index:%d entries=%d",
953 fixed_param->old_hw_mode_index,
954 fixed_param->new_hw_mode_index,
955 fixed_param->num_vdev_mac_entries);
956
957 if (!vdev_mac_entry) {
958 wmi_err("Invalid vdev_mac_entry");
959 return;
960 }
961
962 /* Store the vdev-mac map in WMA and send to policy manager */
963 for (i = 0; i < fixed_param->num_vdev_mac_entries; i++) {
964 uint32_t vdev_id, mac_id, pdev_id;
965
966 vdev_id = vdev_mac_entry[i].vdev_id;
967 pdev_id = vdev_mac_entry[i].pdev_id;
968
969 if (pdev_id == OL_TXRX_PDEV_ID) {
970 wmi_err("soc level id received for mac id");
971 return;
972 }
973 if (vdev_id >= WLAN_MAX_VDEVS) {
974 wmi_err("vdev_id: %d is invalid, max_bssid: %d",
975 vdev_id, WLAN_MAX_VDEVS);
976 return;
977 }
978
979 mac_id = WMI_PDEV_TO_MAC_MAP(vdev_mac_entry[i].pdev_id);
980
981 hw_mode_trans_ind->vdev_mac_map[i].vdev_id = vdev_id;
982 hw_mode_trans_ind->vdev_mac_map[i].mac_id = mac_id;
983
984 wmi_debug("vdev_id:%d mac_id:%d", vdev_id, mac_id);
985 }
986 }
987
988 /**
989 * extract_roam_event_tlv() - Extract the roam event
990 * @wmi_handle: wmi handle
991 * @evt_buf: Pointer to the event buffer
992 * @len: Data length
993 * @roam_event: Roam event data
994 */
995 static QDF_STATUS
extract_roam_event_tlv(wmi_unified_t wmi_handle,void * evt_buf,uint32_t len,struct roam_offload_roam_event * roam_event)996 extract_roam_event_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t len,
997 struct roam_offload_roam_event *roam_event)
998 {
999 QDF_STATUS status = QDF_STATUS_SUCCESS;
1000 wmi_roam_event_fixed_param *wmi_event = NULL;
1001 WMI_ROAM_EVENTID_param_tlvs *param_buf = NULL;
1002 struct cm_hw_mode_trans_ind *hw_mode_trans_ind;
1003 wmi_pdev_hw_mode_transition_event_fixed_param *hw_mode_trans_param;
1004
1005 if (!evt_buf) {
1006 wmi_debug("Empty roam_sync_event param buf");
1007 status = QDF_STATUS_E_FAILURE;
1008 goto end;
1009 }
1010
1011 param_buf = (WMI_ROAM_EVENTID_param_tlvs *)evt_buf;
1012 if (!param_buf) {
1013 wmi_debug("received null buf from target");
1014 status = QDF_STATUS_E_FAILURE;
1015 goto end;
1016 }
1017
1018 wmi_event = param_buf->fixed_param;
1019 if (!wmi_event) {
1020 wmi_debug("received null event data from target");
1021 status = QDF_STATUS_E_FAILURE;
1022 goto end;
1023 }
1024 roam_event->vdev_id = wmi_event->vdev_id;
1025
1026 if (roam_event->vdev_id >= WLAN_MAX_VDEVS) {
1027 wmi_err("Invalid vdev id from firmware: %u",
1028 roam_event->vdev_id);
1029 return -EINVAL;
1030 }
1031 hw_mode_trans_param = param_buf->hw_mode_transition_fixed_param;
1032 if (hw_mode_trans_param &&
1033 hw_mode_trans_param->num_vdev_mac_entries >
1034 param_buf->num_wmi_pdev_set_hw_mode_response_vdev_mac_mapping) {
1035 wmi_debug("invalid vdev mac entries %d %d",
1036 hw_mode_trans_param->num_vdev_mac_entries,
1037 param_buf->num_wmi_pdev_set_hw_mode_response_vdev_mac_mapping);
1038 return QDF_STATUS_E_FAILURE;
1039 }
1040
1041 roam_event->reason =
1042 wmi_convert_fw_reason_to_cm_reason(wmi_event->reason);
1043 roam_event->rssi = wmi_event->rssi;
1044 roam_event->notif = wmi_convert_fw_notif_to_cm_notif(wmi_event->notif);
1045 roam_event->notif_params = wmi_event->notif_params;
1046 roam_event->notif_params1 = wmi_event->notif_params1;
1047
1048 wlan_roam_debug_log(roam_event->vdev_id, DEBUG_ROAM_EVENT,
1049 DEBUG_INVALID_PEER_ID, NULL, NULL,
1050 roam_event->reason,
1051 (roam_event->reason == WMI_ROAM_REASON_INVALID) ?
1052 roam_event->notif : roam_event->rssi);
1053
1054 DPTRACE(qdf_dp_trace_record_event(QDF_DP_TRACE_EVENT_RECORD,
1055 roam_event->vdev_id,
1056 QDF_TRACE_DEFAULT_PDEV_ID,
1057 QDF_PROTO_TYPE_EVENT,
1058 QDF_ROAM_EVENTID));
1059
1060 wmi_debug("FW_ROAM_EVT: Reason:%s[%d], Notif %x for vdevid %x, rssi %d, params %d, params1 %d",
1061 wmi_get_roam_event_reason_string(roam_event->reason),
1062 roam_event->reason,
1063 roam_event->notif, roam_event->vdev_id, roam_event->rssi,
1064 roam_event->notif_params, roam_event->notif_params1);
1065
1066 if (param_buf->hw_mode_transition_fixed_param) {
1067 hw_mode_trans_ind = qdf_mem_malloc(sizeof(*hw_mode_trans_ind));
1068 if (!hw_mode_trans_ind) {
1069 status = QDF_STATUS_E_NOMEM;
1070 goto end;
1071 }
1072 wmi_extract_pdev_hw_mode_trans_ind(
1073 param_buf->hw_mode_transition_fixed_param,
1074 param_buf->wmi_pdev_set_hw_mode_response_vdev_mac_mapping,
1075 hw_mode_trans_ind);
1076 roam_event->hw_mode_trans_ind = hw_mode_trans_ind;
1077 }
1078
1079 if (wmi_event->notif_params1)
1080 roam_event->deauth_disassoc_frame =
1081 param_buf->deauth_disassoc_frame;
1082 end:
1083 return status;
1084 }
1085 #endif /* WLAN_FEATURE_HOST_ROAM || WLAN_FEATURE_ROAM_OFFLOAD */
1086
1087 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
1088 /* send_set_ric_req_cmd_tlv() - set ric request element
1089 * @wmi_handle: wmi handle
1090 * @msg: message
1091 * @is_add_ts: is addts required
1092 *
1093 * This function sets ric request element for 11r roaming.
1094 *
1095 * Return: CDF status
1096 */
send_set_ric_req_cmd_tlv(wmi_unified_t wmi_handle,void * msg,uint8_t is_add_ts)1097 static QDF_STATUS send_set_ric_req_cmd_tlv(wmi_unified_t wmi_handle,
1098 void *msg, uint8_t is_add_ts)
1099 {
1100 wmi_ric_request_fixed_param *cmd;
1101 wmi_ric_tspec *tspec_param;
1102 wmi_buf_t buf;
1103 uint8_t *buf_ptr;
1104 struct mac_tspec_ie *tspec_ie = NULL;
1105 int32_t len = sizeof(wmi_ric_request_fixed_param) +
1106 WMI_TLV_HDR_SIZE + sizeof(wmi_ric_tspec);
1107
1108 buf = wmi_buf_alloc(wmi_handle, len);
1109 if (!buf)
1110 return QDF_STATUS_E_NOMEM;
1111
1112 buf_ptr = (uint8_t *)wmi_buf_data(buf);
1113
1114 cmd = (wmi_ric_request_fixed_param *)buf_ptr;
1115 WMITLV_SET_HDR(&cmd->tlv_header,
1116 WMITLV_TAG_STRUC_wmi_ric_request_fixed_param,
1117 WMITLV_GET_STRUCT_TLVLEN(wmi_ric_request_fixed_param));
1118 if (is_add_ts)
1119 cmd->vdev_id = ((struct add_ts_param *)msg)->vdev_id;
1120 else
1121 cmd->vdev_id = ((struct del_ts_params *)msg)->sessionId;
1122 cmd->num_ric_request = 1;
1123 cmd->is_add_ric = is_add_ts;
1124
1125 buf_ptr += sizeof(wmi_ric_request_fixed_param);
1126 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, sizeof(wmi_ric_tspec));
1127
1128 buf_ptr += WMI_TLV_HDR_SIZE;
1129 tspec_param = (wmi_ric_tspec *)buf_ptr;
1130 WMITLV_SET_HDR(&tspec_param->tlv_header,
1131 WMITLV_TAG_STRUC_wmi_ric_tspec,
1132 WMITLV_GET_STRUCT_TLVLEN(wmi_ric_tspec));
1133
1134 if (is_add_ts)
1135 tspec_ie = &(((struct add_ts_param *)msg)->tspec);
1136 else
1137 tspec_ie = &(((struct del_ts_params *)msg)->delTsInfo.tspec);
1138 if (tspec_ie) {
1139 /* Fill the tsinfo in the format expected by firmware */
1140 #ifndef ANI_LITTLE_BIT_ENDIAN
1141 qdf_mem_copy(((uint8_t *)&tspec_param->ts_info) + 1,
1142 ((uint8_t *)&tspec_ie->tsinfo) + 1, 2);
1143 #else
1144 qdf_mem_copy(((uint8_t *)&tspec_param->ts_info),
1145 ((uint8_t *)&tspec_ie->tsinfo) + 1, 2);
1146 #endif /* ANI_LITTLE_BIT_ENDIAN */
1147
1148 tspec_param->nominal_msdu_size = tspec_ie->nomMsduSz;
1149 tspec_param->maximum_msdu_size = tspec_ie->maxMsduSz;
1150 tspec_param->min_service_interval = tspec_ie->minSvcInterval;
1151 tspec_param->max_service_interval = tspec_ie->maxSvcInterval;
1152 tspec_param->inactivity_interval = tspec_ie->inactInterval;
1153 tspec_param->suspension_interval = tspec_ie->suspendInterval;
1154 tspec_param->svc_start_time = tspec_ie->svcStartTime;
1155 tspec_param->min_data_rate = tspec_ie->minDataRate;
1156 tspec_param->mean_data_rate = tspec_ie->meanDataRate;
1157 tspec_param->peak_data_rate = tspec_ie->peakDataRate;
1158 tspec_param->max_burst_size = tspec_ie->maxBurstSz;
1159 tspec_param->delay_bound = tspec_ie->delayBound;
1160 tspec_param->min_phy_rate = tspec_ie->minPhyRate;
1161 tspec_param->surplus_bw_allowance = tspec_ie->surplusBw;
1162 tspec_param->medium_time = 0;
1163 }
1164 wmi_debug("Set RIC Req is_add_ts: %d", is_add_ts);
1165
1166 wmi_mtrace(WMI_ROAM_SET_RIC_REQUEST_CMDID, cmd->vdev_id, 0);
1167 if (wmi_unified_cmd_send(wmi_handle, buf, len,
1168 WMI_ROAM_SET_RIC_REQUEST_CMDID)) {
1169 wmi_err("Failed to send vdev Set RIC Req command");
1170 if (is_add_ts)
1171 ((struct add_ts_param *)msg)->status =
1172 QDF_STATUS_E_FAILURE;
1173 wmi_buf_free(buf);
1174 return QDF_STATUS_E_FAILURE;
1175 }
1176
1177 return QDF_STATUS_SUCCESS;
1178 }
1179
1180 /**
1181 * send_process_roam_synch_complete_cmd_tlv() - roam synch complete command to
1182 * fw.
1183 * @wmi_handle: wmi handle
1184 * @vdev_id: vdev id
1185 *
1186 * This function sends roam synch complete event to fw.
1187 *
1188 * Return: QDF STATUS
1189 */
1190 static QDF_STATUS
send_process_roam_synch_complete_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id)1191 send_process_roam_synch_complete_cmd_tlv(wmi_unified_t wmi_handle,
1192 uint8_t vdev_id)
1193 {
1194 wmi_roam_synch_complete_fixed_param *cmd;
1195 wmi_buf_t wmi_buf;
1196 uint8_t *buf_ptr;
1197 uint16_t len;
1198 len = sizeof(wmi_roam_synch_complete_fixed_param);
1199
1200 wmi_buf = wmi_buf_alloc(wmi_handle, len);
1201 if (!wmi_buf)
1202 return QDF_STATUS_E_NOMEM;
1203
1204 cmd = (wmi_roam_synch_complete_fixed_param *)wmi_buf_data(wmi_buf);
1205 buf_ptr = (uint8_t *)cmd;
1206 WMITLV_SET_HDR(&cmd->tlv_header,
1207 WMITLV_TAG_STRUC_wmi_roam_synch_complete_fixed_param,
1208 WMITLV_GET_STRUCT_TLVLEN
1209 (wmi_roam_synch_complete_fixed_param));
1210 cmd->vdev_id = vdev_id;
1211 wmi_mtrace(WMI_ROAM_SYNCH_COMPLETE, cmd->vdev_id, 0);
1212 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
1213 WMI_ROAM_SYNCH_COMPLETE)) {
1214 wmi_err("Failed to send roam synch confirmation");
1215 wmi_buf_free(wmi_buf);
1216 return QDF_STATUS_E_FAILURE;
1217 }
1218
1219 return QDF_STATUS_SUCCESS;
1220 }
1221
1222 /**
1223 * send_roam_invoke_cmd_tlv() - send roam invoke command to fw.
1224 * @wmi_handle: wma handle
1225 * @roaminvoke: roam invoke command
1226 *
1227 * Send roam invoke command to fw for fastreassoc.
1228 *
1229 * Return: CDF STATUS
1230 */
send_roam_invoke_cmd_tlv(wmi_unified_t wmi_handle,struct roam_invoke_req * roaminvoke)1231 static QDF_STATUS send_roam_invoke_cmd_tlv(wmi_unified_t wmi_handle,
1232 struct roam_invoke_req *roaminvoke)
1233 {
1234 wmi_roam_invoke_cmd_fixed_param *cmd;
1235 wmi_buf_t wmi_buf;
1236 u_int8_t *buf_ptr;
1237 u_int16_t len, args_tlv_len;
1238 uint32_t *channel_list;
1239 wmi_mac_addr *bssid_list;
1240 wmi_tlv_buf_len_param *buf_len_tlv;
1241
1242 args_tlv_len = (4 * WMI_TLV_HDR_SIZE) + sizeof(uint32_t) +
1243 sizeof(wmi_mac_addr) + sizeof(wmi_tlv_buf_len_param) +
1244 roundup(roaminvoke->frame_len, sizeof(uint32_t));
1245 len = sizeof(wmi_roam_invoke_cmd_fixed_param) + args_tlv_len;
1246 wmi_buf = wmi_buf_alloc(wmi_handle, len);
1247 if (!wmi_buf)
1248 return QDF_STATUS_E_NOMEM;
1249
1250 cmd = (wmi_roam_invoke_cmd_fixed_param *)wmi_buf_data(wmi_buf);
1251 buf_ptr = (u_int8_t *)cmd;
1252 WMITLV_SET_HDR(&cmd->tlv_header,
1253 WMITLV_TAG_STRUC_wmi_roam_invoke_cmd_fixed_param,
1254 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_invoke_cmd_fixed_param));
1255 cmd->vdev_id = roaminvoke->vdev_id;
1256 cmd->flags |= (1 << WMI_ROAM_INVOKE_FLAG_REPORT_FAILURE);
1257 if (roaminvoke->is_same_bssid)
1258 cmd->flags |= (1 << WMI_ROAM_INVOKE_FLAG_NO_NULL_FRAME_TO_AP);
1259
1260 if (roaminvoke->frame_len) {
1261 cmd->roam_scan_mode = WMI_ROAM_INVOKE_SCAN_MODE_SKIP;
1262 /* packing 1 beacon/probe_rsp frame with WMI cmd */
1263 cmd->num_buf = 1;
1264 } else {
1265 cmd->roam_scan_mode = WMI_ROAM_INVOKE_SCAN_MODE_FIXED_CH;
1266 cmd->num_buf = 0;
1267 }
1268
1269 cmd->roam_ap_sel_mode = 0;
1270 cmd->roam_delay = 0;
1271 cmd->num_chan = 1;
1272 cmd->num_bssid = 1;
1273
1274 if (roaminvoke->forced_roaming) {
1275 cmd->num_chan = 0;
1276 cmd->num_bssid = 0;
1277 cmd->roam_scan_mode = WMI_ROAM_INVOKE_SCAN_MODE_CACHE_MAP;
1278 cmd->flags |=
1279 (1 << WMI_ROAM_INVOKE_FLAG_FULL_SCAN_IF_NO_CANDIDATE);
1280 cmd->reason = ROAM_INVOKE_REASON_NUD_FAILURE;
1281 } else if (qdf_is_macaddr_broadcast(&roaminvoke->target_bssid)) {
1282 cmd->num_chan = 0;
1283 cmd->num_bssid = 0;
1284 cmd->roam_scan_mode = WMI_ROAM_INVOKE_SCAN_MODE_CACHE_MAP;
1285 cmd->flags |=
1286 (1 << WMI_ROAM_INVOKE_FLAG_FULL_SCAN_IF_NO_CANDIDATE) |
1287 (1 << WMI_ROAM_INVOKE_FLAG_SELECT_CANDIDATE_CONSIDER_SCORE);
1288 cmd->reason = ROAM_INVOKE_REASON_USER_SPACE;
1289 } else {
1290 cmd->reason = ROAM_INVOKE_REASON_USER_SPACE;
1291 }
1292
1293 buf_ptr += sizeof(wmi_roam_invoke_cmd_fixed_param);
1294 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1295 (sizeof(u_int32_t)));
1296 channel_list = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
1297 *channel_list = roaminvoke->ch_freq;
1298 buf_ptr += sizeof(uint32_t) + WMI_TLV_HDR_SIZE;
1299 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
1300 (sizeof(wmi_mac_addr)));
1301 bssid_list = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE);
1302 WMI_CHAR_ARRAY_TO_MAC_ADDR(roaminvoke->target_bssid.bytes, bssid_list);
1303
1304 /* move to next tlv i.e. bcn_prb_buf_list */
1305 buf_ptr += WMI_TLV_HDR_SIZE + sizeof(wmi_mac_addr);
1306
1307 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
1308 sizeof(wmi_tlv_buf_len_param));
1309
1310 buf_len_tlv = (wmi_tlv_buf_len_param *)(buf_ptr + WMI_TLV_HDR_SIZE);
1311 WMITLV_SET_HDR(&buf_len_tlv->tlv_header,
1312 WMITLV_TAG_STRUC_wmi_tlv_buf_len_param,
1313 WMITLV_GET_STRUCT_TLVLEN(wmi_tlv_buf_len_param));
1314 buf_len_tlv->buf_len = roaminvoke->frame_len;
1315
1316 /* move to next tlv i.e. bcn_prb_frm */
1317 buf_ptr += WMI_TLV_HDR_SIZE + sizeof(wmi_tlv_buf_len_param);
1318 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
1319 roundup(roaminvoke->frame_len, sizeof(uint32_t)));
1320
1321 /* copy frame after the header */
1322 qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE,
1323 roaminvoke->frame_buf,
1324 roaminvoke->frame_len);
1325
1326 wmi_debug("flag:%d, MODE:%d, ap:%d, dly:%d, n_ch:%d, n_bssid:%d, ch_freq:%d, is_same_bss:%d",
1327 cmd->flags, cmd->roam_scan_mode,
1328 cmd->roam_ap_sel_mode, cmd->roam_delay,
1329 cmd->num_chan, cmd->num_bssid, roaminvoke->ch_freq,
1330 roaminvoke->is_same_bssid);
1331
1332 wmi_mtrace(WMI_ROAM_INVOKE_CMDID, cmd->vdev_id, 0);
1333 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
1334 WMI_ROAM_INVOKE_CMDID)) {
1335 wmi_err("Failed to send roam invoke command");
1336 wmi_buf_free(wmi_buf);
1337 return QDF_STATUS_E_FAILURE;
1338 }
1339
1340 return QDF_STATUS_SUCCESS;
1341 }
1342
1343 /**
1344 * convert_control_roam_trigger_reason_bitmap() - Convert roam trigger bitmap
1345 *
1346 * @trigger_reason_bitmap: Roam trigger reason bitmap received from upper layers
1347 *
1348 * Converts the controlled roam trigger reason bitmap of
1349 * type @roam_control_trigger_reason to firmware trigger
1350 * reason bitmap as defined in
1351 * trigger_reason_bitmask @wmi_roam_enable_disable_trigger_reason_fixed_param
1352 *
1353 * Return: trigger_reason_bitmask as defined in
1354 * wmi_roam_enable_disable_trigger_reason_fixed_param
1355 */
1356 static uint32_t
convert_control_roam_trigger_reason_bitmap(uint32_t trigger_reason_bitmap)1357 convert_control_roam_trigger_reason_bitmap(uint32_t trigger_reason_bitmap)
1358 {
1359 uint32_t fw_trigger_bitmap = 0, all_bitmap;
1360
1361 /* Enable the complete trigger bitmap when all bits are set in
1362 * the control config bitmap
1363 */
1364 all_bitmap = BIT(ROAM_TRIGGER_REASON_MAX) - 1;
1365 if (trigger_reason_bitmap == all_bitmap)
1366 return BIT(WMI_ROAM_TRIGGER_EXT_REASON_MAX) - 1;
1367
1368 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_NONE))
1369 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_NONE);
1370
1371 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_PER))
1372 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_PER);
1373
1374 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BMISS))
1375 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BMISS);
1376
1377 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_LOW_RSSI))
1378 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_LOW_RSSI);
1379
1380 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_HIGH_RSSI))
1381 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_HIGH_RSSI);
1382
1383 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_PERIODIC))
1384 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_PERIODIC);
1385
1386 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_MAWC))
1387 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_MAWC);
1388
1389 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_DENSE))
1390 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_DENSE);
1391
1392 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BACKGROUND))
1393 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BACKGROUND);
1394
1395 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_FORCED))
1396 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_FORCED);
1397
1398 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BTM))
1399 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BTM);
1400
1401 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_UNIT_TEST))
1402 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_UNIT_TEST);
1403
1404 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BSS_LOAD))
1405 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BSS_LOAD);
1406
1407 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_DEAUTH))
1408 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_DEAUTH);
1409
1410 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_IDLE))
1411 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_IDLE);
1412
1413 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_STA_KICKOUT))
1414 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_STA_KICKOUT);
1415
1416 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_ESS_RSSI))
1417 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_ESS_RSSI);
1418
1419 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_WTC_BTM))
1420 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_WTC_BTM);
1421
1422 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_PMK_TIMEOUT))
1423 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_PMK_TIMEOUT);
1424
1425 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BTC))
1426 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BTC);
1427
1428 return fw_trigger_bitmap;
1429 }
1430
1431 /**
1432 * get_internal_mandatory_roam_triggers() - Internal triggers to be added
1433 *
1434 * Return: the bitmap of mandatory triggers to be sent to firmware but not given
1435 * by user.
1436 */
1437 static uint32_t
get_internal_mandatory_roam_triggers(void)1438 get_internal_mandatory_roam_triggers(void)
1439 {
1440 return BIT(WMI_ROAM_TRIGGER_REASON_FORCED);
1441 }
1442
1443 /**
1444 * convert_roam_trigger_scan_mode() - Function to convert unified Roam trigger
1445 * scan mode enum to TLV specific ROAM_TRIGGER_SCAN_MODE
1446 * @scan_freq_scheme: scan freq scheme coming from userspace
1447 *
1448 * Return: ROAM_TRIGGER_SCAN_MODE
1449 */
1450 static WMI_ROAM_TRIGGER_SCAN_MODE
convert_roam_trigger_scan_mode(enum roam_scan_freq_scheme scan_freq_scheme)1451 convert_roam_trigger_scan_mode(enum roam_scan_freq_scheme scan_freq_scheme)
1452 {
1453 switch (scan_freq_scheme) {
1454 case ROAM_SCAN_FREQ_SCHEME_NO_SCAN:
1455 return ROAM_TRIGGER_SCAN_MODE_NO_SCAN_DISCONNECTION;
1456 case ROAM_SCAN_FREQ_SCHEME_PARTIAL_SCAN:
1457 return ROAM_TRIGGER_SCAN_MODE_PARTIAL;
1458 case ROAM_SCAN_FREQ_SCHEME_FULL_SCAN:
1459 return ROAM_TRIGGER_SCAN_MODE_FULL;
1460 default:
1461 return ROAM_TRIGGER_SCAN_MODE_NONE;
1462 }
1463 }
1464
1465 /**
1466 * wmi_fill_default_roam_trigger_parameters() - Fill the default parameters
1467 * for wmi_configure_roam_trigger_parameters tlv.
1468 * @roam_trigger_params: pointer to wmi_configure_roam_trigger_parameters tlv
1469 * to be filled.
1470 * @roam_trigger: Roam trigger reason
1471 *
1472 * Return: None
1473 */
wmi_fill_default_roam_trigger_parameters(wmi_configure_roam_trigger_parameters * roam_trigger_params,uint32_t roam_trigger)1474 static void wmi_fill_default_roam_trigger_parameters(
1475 wmi_configure_roam_trigger_parameters *roam_trigger_params,
1476 uint32_t roam_trigger)
1477 {
1478 WMITLV_SET_HDR(&roam_trigger_params->tlv_header,
1479 WMITLV_TAG_STRUC_wmi_configure_roam_trigger_parameters,
1480 WMITLV_GET_STRUCT_TLVLEN(wmi_configure_roam_trigger_parameters));
1481
1482 roam_trigger_params->trigger_reason = roam_trigger;
1483 roam_trigger_params->enable = 1;
1484 roam_trigger_params->scan_mode = ROAM_TRIGGER_SCAN_MODE_NONE;
1485 roam_trigger_params->trigger_rssi_threshold =
1486 ROAM_MAX_CFG_VALUE;
1487 roam_trigger_params->cand_ap_min_rssi_threshold =
1488 ROAM_MAX_CFG_VALUE;
1489 roam_trigger_params->cand_ap_min_rssi_threshold_5g =
1490 ROAM_MAX_CFG_VALUE;
1491 roam_trigger_params->cand_ap_min_rssi_threshold_6g =
1492 ROAM_MAX_CFG_VALUE;
1493 roam_trigger_params->roam_score_delta_percentage =
1494 ROAM_MAX_CFG_VALUE;
1495 roam_trigger_params->reason_code = ROAM_MAX_CFG_VALUE;
1496 }
1497
wmi_fill_score_delta_params(wmi_configure_roam_trigger_parameters * roam_trigger_params,struct wlan_roam_triggers * triggers,uint8_t trig_index)1498 static void wmi_fill_score_delta_params(
1499 wmi_configure_roam_trigger_parameters *roam_trigger_params,
1500 struct wlan_roam_triggers *triggers,
1501 uint8_t trig_index)
1502 {
1503 enum roam_trigger_reason trig_reason;
1504
1505 if (trig_index >= NUM_OF_ROAM_TRIGGERS)
1506 return;
1507
1508 trig_reason =
1509 triggers->score_delta_param[trig_index].trigger_reason;
1510 wmi_fill_default_roam_trigger_parameters(
1511 roam_trigger_params,
1512 convert_roam_trigger_reason(trig_reason));
1513 roam_trigger_params->roam_score_delta_percentage =
1514 triggers->score_delta_param[trig_index].roam_score_delta;
1515
1516 wmi_debug("RSO_CFG: Score delta per: %d converted trig_reason: %d",
1517 roam_trigger_params->roam_score_delta_percentage,
1518 convert_roam_trigger_reason(trig_reason));
1519
1520 }
1521
wmi_fill_min_rssi_params(wmi_configure_roam_trigger_parameters * roam_trigger_params,struct wlan_roam_triggers * triggers,uint8_t trig_index)1522 static void wmi_fill_min_rssi_params(
1523 wmi_configure_roam_trigger_parameters *roam_trigger_params,
1524 struct wlan_roam_triggers *triggers,
1525 uint8_t trig_index)
1526 {
1527 enum roam_trigger_reason trig_reason;
1528
1529 if (trig_index >= NUM_OF_ROAM_MIN_RSSI)
1530 return;
1531
1532 trig_reason =
1533 triggers->min_rssi_params[trig_index].trigger_reason;
1534 wmi_fill_default_roam_trigger_parameters(
1535 roam_trigger_params,
1536 convert_roam_trigger_reason(trig_reason));
1537 roam_trigger_params->cand_ap_min_rssi_threshold =
1538 triggers->min_rssi_params[trig_index].min_rssi;
1539 roam_trigger_params->cand_ap_min_rssi_threshold_5g =
1540 triggers->min_rssi_params[trig_index].min_rssi;
1541 roam_trigger_params->cand_ap_min_rssi_threshold_6g =
1542 triggers->min_rssi_params[trig_index].min_rssi;
1543
1544 wmi_debug("RSO_CFG: Min rssi thresh: %d converted trig_reason: %d",
1545 roam_trigger_params->cand_ap_min_rssi_threshold,
1546 convert_roam_trigger_reason(trig_reason));
1547 }
1548
1549 /**
1550 * send_set_roam_trigger_cmd_tlv() - send set roam triggers to fw
1551 * @wmi_handle: wmi handle
1552 * @triggers: roam trigger bitmap to be enabled
1553 *
1554 * Send WMI_ROAM_ENABLE_DISABLE_TRIGGER_REASON_CMDID to fw.
1555 *
1556 * Return: QDF_STATUS
1557 */
send_set_roam_trigger_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_roam_triggers * triggers)1558 static QDF_STATUS send_set_roam_trigger_cmd_tlv(wmi_unified_t wmi_handle,
1559 struct wlan_roam_triggers *triggers)
1560 {
1561 wmi_buf_t buf;
1562 wmi_roam_enable_disable_trigger_reason_fixed_param *cmd;
1563 uint32_t len = sizeof(*cmd);
1564 int ret;
1565 uint8_t *buf_ptr;
1566 wmi_configure_roam_trigger_parameters
1567 *roam_trigger_parameters;
1568 uint32_t num_triggers_enabled = 0;
1569 uint32_t roam_scan_scheme_bitmap = triggers->roam_scan_scheme_bitmap;
1570 uint32_t total_tlv_len = 0;
1571
1572 if (BIT(ROAM_TRIGGER_REASON_PER) & roam_scan_scheme_bitmap)
1573 num_triggers_enabled++;
1574
1575 if (BIT(ROAM_TRIGGER_REASON_BTC) & roam_scan_scheme_bitmap)
1576 num_triggers_enabled++;
1577
1578 if (BIT(ROAM_TRIGGER_REASON_BMISS) & roam_scan_scheme_bitmap)
1579 num_triggers_enabled++;
1580
1581 if (BIT(ROAM_TRIGGER_REASON_LOW_RSSI) & roam_scan_scheme_bitmap)
1582 num_triggers_enabled++;
1583
1584 if (BIT(ROAM_TRIGGER_REASON_BTM) & roam_scan_scheme_bitmap)
1585 num_triggers_enabled++;
1586
1587 if (BIT(ROAM_TRIGGER_REASON_BSS_LOAD) & roam_scan_scheme_bitmap)
1588 num_triggers_enabled++;
1589
1590 if (wmi_service_enabled(wmi_handle,
1591 wmi_service_configure_roam_trigger_param_support))
1592 total_tlv_len += (NUM_OF_ROAM_TRIGGERS + NUM_OF_ROAM_MIN_RSSI) *
1593 sizeof(wmi_configure_roam_trigger_parameters);
1594
1595 total_tlv_len += 2 * sizeof(wmi_configure_roam_trigger_parameters) +
1596 num_triggers_enabled *
1597 sizeof(wmi_configure_roam_trigger_parameters);
1598 len += WMI_TLV_HDR_SIZE + total_tlv_len;
1599
1600 buf = wmi_buf_alloc(wmi_handle, len);
1601 if (!buf) {
1602 wmi_err("Failed to allocate wmi buffer");
1603 return QDF_STATUS_E_NOMEM;
1604 }
1605
1606 buf_ptr = (uint8_t *)wmi_buf_data(buf);
1607
1608 cmd = (wmi_roam_enable_disable_trigger_reason_fixed_param *)
1609 wmi_buf_data(buf);
1610 WMITLV_SET_HDR(&cmd->tlv_header,
1611 WMITLV_TAG_STRUC_wmi_roam_enable_disable_trigger_reason_fixed_param,
1612 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_enable_disable_trigger_reason_fixed_param));
1613
1614 cmd->vdev_id = triggers->vdev_id;
1615 cmd->trigger_reason_bitmask =
1616 convert_control_roam_trigger_reason_bitmap(triggers->trigger_bitmap);
1617 wmi_debug("RSO_CFG: Received trigger bitmap: 0x%x converted trigger_bitmap: 0x%x",
1618 triggers->trigger_bitmap, cmd->trigger_reason_bitmask);
1619 cmd->trigger_reason_bitmask |= get_internal_mandatory_roam_triggers();
1620 wmi_debug("RSO_CFG: vdev id: %d final trigger_bitmap: 0x%x roam_scan_scheme:0x%x num_triggers_enabled:%d",
1621 cmd->vdev_id, cmd->trigger_reason_bitmask,
1622 roam_scan_scheme_bitmap, num_triggers_enabled);
1623
1624 buf_ptr += sizeof(wmi_roam_enable_disable_trigger_reason_fixed_param);
1625 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, total_tlv_len);
1626 buf_ptr += WMI_TLV_HDR_SIZE;
1627
1628 roam_trigger_parameters =
1629 (wmi_configure_roam_trigger_parameters *)buf_ptr;
1630
1631 WMITLV_SET_HDR(&roam_trigger_parameters->tlv_header,
1632 WMITLV_TAG_STRUC_wmi_configure_roam_trigger_parameters,
1633 WMITLV_GET_STRUCT_TLVLEN(
1634 wmi_configure_roam_trigger_parameters));
1635 roam_trigger_parameters->trigger_reason =
1636 WMI_ROAM_TRIGGER_REASON_WTC_BTM;
1637 if (triggers->vendor_btm_param.user_roam_reason == 0)
1638 roam_trigger_parameters->enable = 1;
1639 roam_trigger_parameters->scan_mode = convert_roam_trigger_scan_mode(
1640 triggers->vendor_btm_param.scan_freq_scheme);
1641 roam_trigger_parameters->trigger_rssi_threshold =
1642 triggers->vendor_btm_param.connected_rssi_threshold;
1643 roam_trigger_parameters->cand_ap_min_rssi_threshold =
1644 triggers->vendor_btm_param.candidate_rssi_threshold_2g;
1645 roam_trigger_parameters->cand_ap_min_rssi_threshold_5g =
1646 triggers->vendor_btm_param.candidate_rssi_threshold_5g;
1647 roam_trigger_parameters->cand_ap_min_rssi_threshold_6g =
1648 triggers->vendor_btm_param.candidate_rssi_threshold_6g;
1649 roam_trigger_parameters->roam_score_delta_percentage =
1650 triggers->roam_score_delta;
1651 roam_trigger_parameters->reason_code =
1652 triggers->vendor_btm_param.user_roam_reason;
1653
1654 roam_trigger_parameters++;
1655
1656 if (wmi_service_enabled(wmi_handle,
1657 wmi_service_configure_roam_trigger_param_support)) {
1658 wmi_fill_score_delta_params(roam_trigger_parameters,
1659 triggers,
1660 IDLE_ROAM_TRIGGER);
1661 if (cmd->trigger_reason_bitmask &
1662 BIT(WMI_ROAM_TRIGGER_REASON_IDLE))
1663 roam_trigger_parameters->enable = 1;
1664 else
1665 roam_trigger_parameters->enable = 0;
1666
1667 roam_trigger_parameters++;
1668
1669 wmi_fill_score_delta_params(roam_trigger_parameters,
1670 triggers,
1671 BTM_ROAM_TRIGGER);
1672 roam_trigger_parameters++;
1673
1674 wmi_fill_min_rssi_params(roam_trigger_parameters,
1675 triggers,
1676 DEAUTH_MIN_RSSI);
1677 roam_trigger_parameters++;
1678
1679 wmi_fill_min_rssi_params(roam_trigger_parameters,
1680 triggers,
1681 BMISS_MIN_RSSI);
1682 roam_trigger_parameters++;
1683
1684 wmi_fill_min_rssi_params(roam_trigger_parameters,
1685 triggers,
1686 MIN_RSSI_2G_TO_5G_ROAM);
1687 roam_trigger_parameters++;
1688 }
1689
1690 wmi_fill_default_roam_trigger_parameters(
1691 roam_trigger_parameters,
1692 WMI_ROAM_TRIGGER_REASON_PMK_TIMEOUT);
1693
1694 if (cmd->trigger_reason_bitmask &
1695 BIT(WMI_ROAM_TRIGGER_REASON_PMK_TIMEOUT))
1696 roam_trigger_parameters->enable = 1;
1697 else
1698 roam_trigger_parameters->enable = 0;
1699
1700 roam_trigger_parameters->roam_score_delta_percentage = 0;
1701 roam_trigger_parameters++;
1702
1703 if (num_triggers_enabled == 0)
1704 goto send;
1705
1706 if (BIT(ROAM_TRIGGER_REASON_PER) & roam_scan_scheme_bitmap) {
1707 wmi_fill_default_roam_trigger_parameters(
1708 roam_trigger_parameters,
1709 WMI_ROAM_TRIGGER_REASON_PER);
1710 roam_trigger_parameters->scan_mode =
1711 ROAM_TRIGGER_SCAN_MODE_PARTIAL;
1712
1713 roam_trigger_parameters++;
1714 }
1715
1716 if (BIT(ROAM_TRIGGER_REASON_BTC) & roam_scan_scheme_bitmap) {
1717 wmi_fill_default_roam_trigger_parameters(
1718 roam_trigger_parameters,
1719 WMI_ROAM_TRIGGER_REASON_BTC);
1720 roam_trigger_parameters->scan_mode =
1721 ROAM_TRIGGER_SCAN_MODE_PARTIAL;
1722
1723 roam_trigger_parameters++;
1724 }
1725
1726 if (BIT(ROAM_TRIGGER_REASON_BMISS) & roam_scan_scheme_bitmap) {
1727 wmi_fill_default_roam_trigger_parameters(
1728 roam_trigger_parameters,
1729 WMI_ROAM_TRIGGER_REASON_BMISS);
1730 roam_trigger_parameters->scan_mode =
1731 ROAM_TRIGGER_SCAN_MODE_PARTIAL;
1732
1733 roam_trigger_parameters++;
1734 }
1735
1736 if (BIT(ROAM_TRIGGER_REASON_LOW_RSSI) & roam_scan_scheme_bitmap) {
1737 wmi_fill_default_roam_trigger_parameters(
1738 roam_trigger_parameters,
1739 WMI_ROAM_TRIGGER_REASON_LOW_RSSI);
1740 roam_trigger_parameters->scan_mode =
1741 ROAM_TRIGGER_SCAN_MODE_PARTIAL;
1742
1743 roam_trigger_parameters++;
1744 }
1745
1746 if (BIT(ROAM_TRIGGER_REASON_BTM) & roam_scan_scheme_bitmap) {
1747 wmi_fill_default_roam_trigger_parameters(
1748 roam_trigger_parameters,
1749 WMI_ROAM_TRIGGER_REASON_BTM);
1750 roam_trigger_parameters->scan_mode =
1751 ROAM_TRIGGER_SCAN_MODE_PARTIAL;
1752
1753 roam_trigger_parameters++;
1754 }
1755
1756 if (BIT(ROAM_TRIGGER_REASON_BSS_LOAD) & roam_scan_scheme_bitmap) {
1757 wmi_fill_default_roam_trigger_parameters(
1758 roam_trigger_parameters,
1759 WMI_ROAM_TRIGGER_REASON_BSS_LOAD);
1760 roam_trigger_parameters->scan_mode =
1761 ROAM_TRIGGER_SCAN_MODE_PARTIAL;
1762
1763 roam_trigger_parameters++;
1764 }
1765
1766 send:
1767 wmi_mtrace(WMI_ROAM_ENABLE_DISABLE_TRIGGER_REASON_CMDID,
1768 triggers->vdev_id, 0);
1769 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1770 WMI_ROAM_ENABLE_DISABLE_TRIGGER_REASON_CMDID);
1771 if (QDF_IS_STATUS_ERROR(ret)) {
1772 wmi_err("Failed to send set roam triggers command ret = %d",
1773 ret);
1774 wmi_buf_free(buf);
1775 }
1776 return ret;
1777 }
1778
1779 /**
1780 * send_vdev_set_pcl_cmd_tlv() - Send WMI_VDEV_SET_PCL_CMDID to FW
1781 * @wmi_handle: wmi handle
1782 * @params: Set VDEV PCL params
1783 *
1784 * WMI_VDEV_SET_PCL_CMDID provides the Preferred Channel List (PCL) to WLAN
1785 * firmware. The roaming module is the consumer of this information
1786 * in the WLAN firmware. The channel list will be used when a VDEV needs
1787 * to migrate to a new channel without host driver involvement. An example of
1788 * this behavior is Legacy Fast Roaming (LFR 3.0).
1789 *
1790 * WMI_VDEV_SET_PCL_CMDID will carry only the weight list and not the actual
1791 * channel list. The weights corresponds to the channels sent in
1792 * WMI_SCAN_CHAN_LIST_CMDID. The channels from PCL would be having a higher
1793 * weightage compared to the non PCL channels.
1794 *
1795 * When roaming is enabled on STA 1, PDEV pcl will be sent. When STA2 is
1796 * up, VDEV pcl will be sent on STA 1 after calculating pcl again applying
1797 * the bandmask and VDEV pcl will be sent for STA2. When one of the STA
1798 * is disconnected, PDEV pcl will be sent on the other STA again.
1799 *
1800 * Return: Success if the cmd is sent successfully to the firmware
1801 */
1802 static QDF_STATUS
send_vdev_set_pcl_cmd_tlv(wmi_unified_t wmi_handle,struct set_pcl_cmd_params * params)1803 send_vdev_set_pcl_cmd_tlv(wmi_unified_t wmi_handle,
1804 struct set_pcl_cmd_params *params)
1805 {
1806 wmi_vdev_set_pcl_cmd_fixed_param *cmd;
1807 wmi_buf_t buf;
1808 uint8_t *buf_ptr;
1809 uint32_t *ch_weight, i;
1810 size_t len;
1811 uint32_t chan_len;
1812
1813 chan_len = params->weights->saved_num_chan;
1814 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + (chan_len * sizeof(uint32_t));
1815
1816 buf = wmi_buf_alloc(wmi_handle, len);
1817 if (!buf)
1818 return QDF_STATUS_E_NOMEM;
1819
1820 cmd = (wmi_vdev_set_pcl_cmd_fixed_param *)wmi_buf_data(buf);
1821 buf_ptr = (uint8_t *)cmd;
1822 WMITLV_SET_HDR(&cmd->tlv_header,
1823 WMITLV_TAG_STRUC_wmi_vdev_set_pcl_cmd_fixed_param,
1824 WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_set_pcl_cmd_fixed_param));
1825 cmd->vdev_id = params->vdev_id;
1826 buf_ptr += sizeof(wmi_vdev_set_pcl_cmd_fixed_param);
1827
1828 /* Channel weights uint32 Array TLV */
1829 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1830 (chan_len * sizeof(uint32_t)));
1831 ch_weight = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
1832 for (i = 0; i < chan_len; i++)
1833 ch_weight[i] = params->weights->weighed_valid_list[i];
1834
1835 wmi_mtrace(WMI_VDEV_SET_PCL_CMDID, params->vdev_id, 0);
1836 if (wmi_unified_cmd_send(wmi_handle, buf, len,
1837 WMI_VDEV_SET_PCL_CMDID)) {
1838 wmi_err("Failed to send WMI_VDEV_SET_PCL_CMDID");
1839 wmi_buf_free(buf);
1840 return QDF_STATUS_E_FAILURE;
1841 }
1842
1843 return QDF_STATUS_SUCCESS;
1844 }
1845
1846 /**
1847 * extract_roam_btm_response_stats_tlv() - Extract the btm rsp stats
1848 * from the WMI_ROAM_STATS_EVENTID
1849 * @wmi_handle: wmi handle
1850 * @evt_buf: Pointer to the event buffer
1851 * @dst: Pointer to destination structure to fill data
1852 * @idx: TLV id
1853 */
1854 static QDF_STATUS
extract_roam_btm_response_stats_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct roam_btm_response_data * dst,uint8_t idx)1855 extract_roam_btm_response_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf,
1856 struct roam_btm_response_data *dst,
1857 uint8_t idx)
1858 {
1859 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf;
1860 wmi_roam_btm_response_info *src_data = NULL;
1861
1862 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf;
1863
1864 if (!param_buf || !param_buf->roam_btm_response_info ||
1865 !param_buf->num_roam_btm_response_info ||
1866 idx >= param_buf->num_roam_btm_response_info) {
1867 wmi_debug("Empty btm response param buf");
1868 return QDF_STATUS_SUCCESS;
1869 }
1870
1871 src_data = ¶m_buf->roam_btm_response_info[idx];
1872 if (!src_data->timestamp)
1873 return QDF_STATUS_SUCCESS;
1874
1875 dst->present = true;
1876 dst->btm_status = src_data->btm_status;
1877 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_data->target_bssid,
1878 dst->target_bssid.bytes);
1879 dst->vsie_reason = src_data->vsie_reason;
1880 dst->timestamp = src_data->timestamp;
1881 dst->btm_resp_dialog_token = src_data->btm_resp_dialog_token;
1882 dst->btm_delay = src_data->btm_resp_bss_termination_delay;
1883 dst->band = WMI_ROAM_BTM_RESP_MLO_BAND_INFO_GET(src_data->info);
1884 if (dst->band != WMI_MLO_BAND_NO_MLO)
1885 dst->is_mlo = true;
1886
1887 return QDF_STATUS_SUCCESS;
1888 }
1889
1890 /**
1891 * extract_roam_initial_info_tlv() - Extract the roam initial info
1892 * from the WMI_ROAM_STATS_EVENTID
1893 * @wmi_handle: wmi handle
1894 * @evt_buf: Pointer to the event buffer
1895 * @dst: Pointer to destination structure to fill data
1896 * @idx: TLV id
1897 */
1898 static QDF_STATUS
extract_roam_initial_info_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct roam_initial_data * dst,uint8_t idx)1899 extract_roam_initial_info_tlv(wmi_unified_t wmi_handle, void *evt_buf,
1900 struct roam_initial_data *dst, uint8_t idx)
1901 {
1902 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf;
1903 wmi_roam_initial_info *src_data = NULL;
1904
1905 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf;
1906
1907 if (!param_buf || !param_buf->roam_initial_info ||
1908 !param_buf->num_roam_initial_info ||
1909 idx >= param_buf->num_roam_initial_info) {
1910 wmi_debug("Empty roam_initial_info param buf");
1911 return QDF_STATUS_SUCCESS;
1912 }
1913
1914 src_data = ¶m_buf->roam_initial_info[idx];
1915
1916 dst->present = true;
1917 dst->roam_full_scan_count = src_data->roam_full_scan_count;
1918 dst->rssi_th = src_data->rssi_th;
1919 dst->cu_th = src_data->cu_th;
1920 dst->fw_cancel_timer_bitmap = src_data->timer_canceled;
1921
1922 return QDF_STATUS_SUCCESS;
1923 }
1924
1925 /**
1926 * extract_roam_msg_info_tlv() - Extract the roam message info
1927 * from the WMI_ROAM_STATS_EVENTID
1928 * @wmi_handle: wmi handle
1929 * @evt_buf: Pointer to the event buffer
1930 * @dst: Pointer to destination structure to fill data
1931 * @idx: TLV id
1932 */
1933 static QDF_STATUS
extract_roam_msg_info_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct roam_msg_info * dst,uint8_t idx)1934 extract_roam_msg_info_tlv(wmi_unified_t wmi_handle, void *evt_buf,
1935 struct roam_msg_info *dst, uint8_t idx)
1936 {
1937 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf;
1938 wmi_roam_msg_info *src_data = NULL;
1939
1940 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf;
1941
1942 if (!param_buf || !param_buf->roam_msg_info ||
1943 !param_buf->num_roam_msg_info ||
1944 idx >= param_buf->num_roam_msg_info)
1945 return QDF_STATUS_SUCCESS;
1946
1947 src_data = ¶m_buf->roam_msg_info[idx];
1948
1949 dst->present = true;
1950 dst->timestamp = src_data->timestamp;
1951 dst->msg_id = src_data->msg_id;
1952 dst->msg_param1 = src_data->msg_param1;
1953 dst->msg_param2 = src_data->msg_param2;
1954
1955 return QDF_STATUS_SUCCESS;
1956 }
1957
1958 static enum wlan_roam_frame_subtype
wmi_get_converted_roam_eapol_subtype(WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE eapol_subtype)1959 wmi_get_converted_roam_eapol_subtype(
1960 WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE eapol_subtype)
1961 {
1962 switch (eapol_subtype) {
1963 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_M1:
1964 return ROAM_FRAME_SUBTYPE_M1;
1965 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_M2:
1966 return ROAM_FRAME_SUBTYPE_M2;
1967 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_M3:
1968 return ROAM_FRAME_SUBTYPE_M3;
1969 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_M4:
1970 return ROAM_FRAME_SUBTYPE_M4;
1971 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_GTK_M1:
1972 return ROAM_FRAME_SUBTYPE_GTK_M1;
1973 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_GTK_M2:
1974 return ROAM_FRAME_SUBTYPE_GTK_M2;
1975 default:
1976 break;
1977 }
1978
1979 return 0;
1980 }
1981
1982 static enum qdf_dp_tx_rx_status
wmi_get_converted_tx_status(WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_STATUS roam_tx_status)1983 wmi_get_converted_tx_status(
1984 WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_STATUS roam_tx_status)
1985 {
1986 switch (roam_tx_status) {
1987 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_STATUS_ACK:
1988 return QDF_TX_RX_STATUS_OK;
1989 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_STATUS_NO_ACK:
1990 return QDF_TX_RX_STATUS_NO_ACK;
1991 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_STATUS_TX_FAIL:
1992 return QDF_TX_RX_STATUS_DROP;
1993 default:
1994 break;
1995 }
1996
1997 return QDF_TX_RX_STATUS_INVALID;
1998 }
1999
2000 #define WLAN_FC0_SUBTYPE_SHIFT 4
2001 #define WLAN_FRAME_INFO_TYPE_OFFSET 0
2002 #define WLAN_FRAME_INFO_SUBTYPE_OFFSET 2
2003 #define WLAN_FRAME_INFO_RESP_OFFSET 6
2004 #define WLAN_FRAME_INFO_AUTH_ALG_OFFSET 7
2005 #define WLAN_FRAME_INFO_SEQ_NUM_OFFSET 16
2006
2007 /**
2008 * extract_roam_frame_info_tlv() - Extract the frame exchanges during roaming
2009 * info from the WMI_ROAM_STATS_EVENTID
2010 * @wmi_handle: wmi handle
2011 * @evt_buf: Pointer to the event buffer
2012 * @dst: Pointer to destination structure to fill data
2013 * @frame_idx: TLV id
2014 * @num_frames: Number of Frame TLVs to be extracted
2015 */
2016 static QDF_STATUS
extract_roam_frame_info_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct roam_frame_stats * dst,uint8_t frame_idx,uint8_t num_frames)2017 extract_roam_frame_info_tlv(wmi_unified_t wmi_handle, void *evt_buf,
2018 struct roam_frame_stats *dst, uint8_t frame_idx,
2019 uint8_t num_frames)
2020 {
2021 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf;
2022 wmi_roam_frame_info *src_data = NULL;
2023 struct roam_frame_info *dst_buf;
2024 uint8_t i, subtype;
2025
2026 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf;
2027
2028 if (!param_buf || !param_buf->roam_frame_info ||
2029 !param_buf->num_roam_frame_info ||
2030 (frame_idx + num_frames) > param_buf->num_roam_frame_info) {
2031 wmi_err("Empty roam_frame_info param buf frame_idx:%d num_frames:%d",
2032 frame_idx, num_frames);
2033 return QDF_STATUS_SUCCESS;
2034 }
2035
2036 src_data = ¶m_buf->roam_frame_info[frame_idx];
2037
2038 if (num_frames > WLAN_ROAM_MAX_FRAME_INFO)
2039 num_frames = WLAN_ROAM_MAX_FRAME_INFO;
2040
2041 dst->num_frame = num_frames;
2042 dst_buf = dst->frame_info;
2043 for (i = 0; i < num_frames; i++) {
2044 dst_buf->timestamp = src_data->timestamp;
2045 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_data->bssid,
2046 dst_buf->bssid.bytes);
2047 dst_buf->type = WMI_GET_BITS(src_data->frame_info,
2048 WLAN_FRAME_INFO_TYPE_OFFSET, 2);
2049
2050 subtype = WMI_GET_BITS(src_data->frame_info,
2051 WLAN_FRAME_INFO_SUBTYPE_OFFSET, 4);
2052 if (dst_buf->type == WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT) {
2053 dst_buf->type = ROAM_FRAME_INFO_FRAME_TYPE_EXT;
2054 dst_buf->subtype =
2055 wmi_get_converted_roam_eapol_subtype(subtype);
2056 } else {
2057 dst_buf->subtype = subtype << WLAN_FC0_SUBTYPE_SHIFT;
2058 }
2059
2060 dst_buf->is_rsp = WMI_GET_BITS(src_data->frame_info,
2061 WLAN_FRAME_INFO_RESP_OFFSET, 1);
2062 dst_buf->seq_num = WMI_GET_BITS(src_data->frame_info,
2063 WLAN_FRAME_INFO_SEQ_NUM_OFFSET,
2064 16);
2065 dst_buf->status_code = src_data->status_code;
2066 if (dst_buf->type != WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT &&
2067 dst_buf->subtype == MGMT_SUBTYPE_AUTH)
2068 dst_buf->auth_algo =
2069 WMI_GET_BITS(src_data->frame_info,
2070 WLAN_FRAME_INFO_AUTH_ALG_OFFSET,
2071 4);
2072
2073 if (!dst_buf->is_rsp) {
2074 dst_buf->tx_status = wmi_get_converted_tx_status(
2075 src_data->status_code);
2076 /* wmi_roam_frame_info->status_code sent from the fw
2077 * denotes the tx_status of the transmitted frames.
2078 * To Do: Need a separate field for status code or
2079 * use existing field of wmi_roam_frame_info tlv
2080 * to send the tx status of transmitted frame from the
2081 * FW.
2082 */
2083 dst_buf->status_code = 0;
2084 }
2085
2086 dst_buf->retry_count = src_data->retry_count;
2087 dst_buf->rssi = (-1) * src_data->rssi_dbm_abs;
2088 dst_buf->assoc_id =
2089 WMI_GET_ASSOC_ID(src_data->frame_info_ext);
2090
2091 dst_buf->band =
2092 WMI_GET_MLO_BITMAP_BAND_INFO(src_data->frame_info_ext);
2093
2094 dst_buf++;
2095 src_data++;
2096 }
2097
2098 return QDF_STATUS_SUCCESS;
2099 }
2100
2101 /**
2102 * wmi_fill_data_synch_frame_event() - Fill the the roam sync data buffer using
2103 * synch frame event data
2104 * @rso_cfg: Source buffer
2105 * @roam_sync_ind: Buffer to be filled
2106 *
2107 * Firmware sends all the required information required for roam
2108 * synch propagation as TLV's and stored in param_buf. These
2109 * parameters are parsed and filled into the roam synch indication
2110 * buffer which will be used at different layers for propagation.
2111 *
2112 * Return: None
2113 */
2114 static void
wmi_fill_data_synch_frame_event(struct rso_config * rso_cfg,struct roam_offload_synch_ind * roam_sync_ind)2115 wmi_fill_data_synch_frame_event(struct rso_config *rso_cfg,
2116 struct roam_offload_synch_ind *roam_sync_ind)
2117 {
2118 uint8_t *bcn_probersp_ptr, *link_bcn_probersp_ptr;
2119 uint8_t *reassoc_rsp_ptr;
2120 uint8_t *reassoc_req_ptr;
2121
2122 /* Beacon/Probe Rsp data */
2123 roam_sync_ind->beacon_probe_resp_offset =
2124 sizeof(struct roam_offload_synch_ind);
2125 bcn_probersp_ptr = (uint8_t *)roam_sync_ind +
2126 roam_sync_ind->beacon_probe_resp_offset;
2127 roam_sync_ind->beacon_probe_resp_length =
2128 rso_cfg->roam_sync_frame_ind.bcn_probe_rsp_len;
2129 qdf_mem_copy(bcn_probersp_ptr,
2130 rso_cfg->roam_sync_frame_ind.bcn_probe_rsp,
2131 roam_sync_ind->beacon_probe_resp_length);
2132 qdf_mem_free(rso_cfg->roam_sync_frame_ind.bcn_probe_rsp);
2133 rso_cfg->roam_sync_frame_ind.bcn_probe_rsp = NULL;
2134
2135 /* Link beacon/probe rsp data */
2136 if (rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp) {
2137 roam_sync_ind->link_beacon_probe_resp_offset =
2138 sizeof(struct roam_offload_synch_ind) +
2139 roam_sync_ind->beacon_probe_resp_length;
2140 roam_sync_ind->link_beacon_probe_resp_length =
2141 rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp_len;
2142 roam_sync_ind->is_link_beacon =
2143 rso_cfg->roam_sync_frame_ind.is_link_beacon;
2144 link_bcn_probersp_ptr = (uint8_t *)roam_sync_ind +
2145 roam_sync_ind->link_beacon_probe_resp_offset;
2146 qdf_mem_copy(link_bcn_probersp_ptr,
2147 rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp,
2148 roam_sync_ind->link_beacon_probe_resp_length);
2149 qdf_mem_free(rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp);
2150 rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp = NULL;
2151 }
2152
2153 /* ReAssoc Rsp data */
2154 roam_sync_ind->reassoc_resp_offset =
2155 sizeof(struct roam_offload_synch_ind) +
2156 roam_sync_ind->beacon_probe_resp_length +
2157 roam_sync_ind->link_beacon_probe_resp_length;
2158 roam_sync_ind->reassoc_resp_length =
2159 rso_cfg->roam_sync_frame_ind.reassoc_rsp_len;
2160 reassoc_rsp_ptr = (uint8_t *)roam_sync_ind +
2161 roam_sync_ind->reassoc_resp_offset;
2162 qdf_mem_copy(reassoc_rsp_ptr,
2163 rso_cfg->roam_sync_frame_ind.reassoc_rsp,
2164 roam_sync_ind->reassoc_resp_length);
2165 qdf_mem_free(rso_cfg->roam_sync_frame_ind.reassoc_rsp);
2166 rso_cfg->roam_sync_frame_ind.reassoc_rsp = NULL;
2167
2168 /* ReAssoc Req data */
2169 roam_sync_ind->reassoc_req_offset =
2170 sizeof(struct roam_offload_synch_ind) +
2171 roam_sync_ind->beacon_probe_resp_length +
2172 roam_sync_ind->link_beacon_probe_resp_length +
2173 roam_sync_ind->reassoc_resp_length;
2174 roam_sync_ind->reassoc_req_length =
2175 rso_cfg->roam_sync_frame_ind.reassoc_req_len;
2176 reassoc_req_ptr = (uint8_t *)roam_sync_ind +
2177 roam_sync_ind->reassoc_req_offset;
2178 qdf_mem_copy(reassoc_req_ptr,
2179 rso_cfg->roam_sync_frame_ind.reassoc_req,
2180 roam_sync_ind->reassoc_req_length);
2181 qdf_mem_free(rso_cfg->roam_sync_frame_ind.reassoc_req);
2182 rso_cfg->roam_sync_frame_ind.reassoc_req = NULL;
2183 }
2184
2185 /**
2186 * wmi_fill_data_synch_event() - Fill the the roam sync data buffer
2187 * using synch event data
2188 * @roam_sync_ind: Buffer to be filled
2189 * @param_buf: Source buffer
2190 *
2191 * Firmware sends all the required information required for roam
2192 * synch propagation as TLV's and stored in param_buf. These
2193 * parameters are parsed and filled into the roam synch indication
2194 * buffer which will be used at different layers for propagation.
2195 *
2196 * Return: None
2197 */
2198 static void
wmi_fill_data_synch_event(struct roam_offload_synch_ind * roam_sync_ind,WMI_ROAM_SYNCH_EVENTID_param_tlvs * param_buf)2199 wmi_fill_data_synch_event(struct roam_offload_synch_ind *roam_sync_ind,
2200 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf)
2201 {
2202 uint8_t *bcn_probersp_ptr;
2203 uint8_t *reassoc_rsp_ptr;
2204 uint8_t *reassoc_req_ptr;
2205 wmi_roam_synch_event_fixed_param *synch_event;
2206
2207 synch_event = param_buf->fixed_param;
2208
2209 /* Beacon/Probe Rsp data */
2210 roam_sync_ind->beacon_probe_resp_offset =
2211 sizeof(struct roam_offload_synch_ind);
2212 bcn_probersp_ptr = (uint8_t *)roam_sync_ind +
2213 roam_sync_ind->beacon_probe_resp_offset;
2214 roam_sync_ind->beacon_probe_resp_length =
2215 synch_event->bcn_probe_rsp_len;
2216 qdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame,
2217 roam_sync_ind->beacon_probe_resp_length);
2218 /*
2219 * Firmware doesn't support link beacon/Probe Rsp data in roam sync
2220 * event. It's always sent in sync_frame event
2221 */
2222 /* ReAssoc Rsp data */
2223 roam_sync_ind->reassoc_resp_offset =
2224 sizeof(struct roam_offload_synch_ind) +
2225 roam_sync_ind->beacon_probe_resp_length;
2226 roam_sync_ind->reassoc_resp_length = synch_event->reassoc_rsp_len;
2227 reassoc_rsp_ptr = (uint8_t *)roam_sync_ind +
2228 roam_sync_ind->reassoc_resp_offset;
2229 qdf_mem_copy(reassoc_rsp_ptr,
2230 param_buf->reassoc_rsp_frame,
2231 roam_sync_ind->reassoc_resp_length);
2232
2233 /* ReAssoc Req data */
2234 roam_sync_ind->reassoc_req_offset =
2235 sizeof(struct roam_offload_synch_ind) +
2236 roam_sync_ind->beacon_probe_resp_length +
2237 roam_sync_ind->reassoc_resp_length;
2238 roam_sync_ind->reassoc_req_length = synch_event->reassoc_req_len;
2239 reassoc_req_ptr = (uint8_t *)roam_sync_ind +
2240 roam_sync_ind->reassoc_req_offset;
2241 qdf_mem_copy(reassoc_req_ptr, param_buf->reassoc_req_frame,
2242 roam_sync_ind->reassoc_req_length);
2243 }
2244
2245 #ifdef WLAN_FEATURE_11BE_MLO
2246 #define STANDBY_VDEV_ID (0xFFFFFFFF)
2247 static QDF_STATUS
wmi_fill_roam_mlo_info(wmi_unified_t wmi_handle,WMI_ROAM_SYNCH_EVENTID_param_tlvs * param_buf,struct roam_offload_synch_ind * roam_sync_ind)2248 wmi_fill_roam_mlo_info(wmi_unified_t wmi_handle,
2249 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf,
2250 struct roam_offload_synch_ind *roam_sync_ind)
2251 {
2252 uint8_t i, mlo_max_allowed_links;
2253 wmi_roam_ml_setup_links_param *setup_links;
2254 wmi_roam_ml_key_material_param *ml_key_param;
2255 struct ml_setup_link_param *link;
2256 struct ml_key_material_param *key;
2257
2258 mlo_max_allowed_links =
2259 wlan_mlme_get_sta_mlo_conn_max_num(wmi_handle->soc->wmi_psoc);
2260 if (param_buf->num_setup_links_param) {
2261 if (param_buf->num_setup_links_param > mlo_max_allowed_links ||
2262 param_buf->num_setup_links_param > WLAN_MAX_ML_BSS_LINKS) {
2263 wmi_err("Number of links %d exceeded max vdev supported %d",
2264 param_buf->num_setup_links_param,
2265 mlo_max_allowed_links);
2266 return QDF_STATUS_E_INVAL;
2267 }
2268
2269 roam_sync_ind->num_setup_links =
2270 param_buf->num_setup_links_param;
2271 setup_links = param_buf->setup_links_param;
2272
2273 for (i = 0; i < roam_sync_ind->num_setup_links; i++) {
2274 link = &roam_sync_ind->ml_link[i];
2275 link->link_id = setup_links->link_id;
2276
2277 /*
2278 * setup_links->vdev_id == UINT32_MAX for standby link
2279 */
2280 link->vdev_id = WLAN_INVALID_VDEV_ID;
2281 if (setup_links->vdev_id != STANDBY_VDEV_ID)
2282 link->vdev_id = setup_links->vdev_id;
2283
2284 link->channel = setup_links->channel;
2285 link->flags = setup_links->flags;
2286
2287 WMI_MAC_ADDR_TO_CHAR_ARRAY(&setup_links->link_addr,
2288 link->link_addr.bytes);
2289 WMI_MAC_ADDR_TO_CHAR_ARRAY(&setup_links->self_link_addr,
2290 link->self_link_addr.bytes);
2291 wmi_debug("link_id: %u vdev_id: %u flags: 0x%x addr: " QDF_MAC_ADDR_FMT " self_addr:" QDF_MAC_ADDR_FMT,
2292 link->link_id, link->vdev_id,
2293 link->flags,
2294 QDF_MAC_ADDR_REF(link->link_addr.bytes),
2295 QDF_MAC_ADDR_REF(link->self_link_addr.bytes));
2296 wmi_debug("channel: %u mhz center_freq1: %u center_freq2: %u",
2297 link->channel.mhz,
2298 link->channel.band_center_freq1,
2299 link->channel.band_center_freq2);
2300 setup_links++;
2301 }
2302 }
2303
2304 if (!param_buf->num_ml_key_material)
2305 return QDF_STATUS_SUCCESS;
2306
2307 if (param_buf->num_ml_key_material > WLAN_MAX_ML_BSS_LINKS)
2308 param_buf->num_ml_key_material = WLAN_MAX_ML_BSS_LINKS;
2309
2310 roam_sync_ind->num_ml_key_material = param_buf->num_ml_key_material;
2311 ml_key_param = param_buf->ml_key_material;
2312
2313 for (i = 0; i < roam_sync_ind->num_ml_key_material; i++) {
2314 key = &roam_sync_ind->ml_key[i];
2315 key->link_id = ml_key_param->link_id;
2316 key->key_idx = ml_key_param->key_ix;
2317 key->key_cipher = ml_key_param->key_cipher;
2318 qdf_mem_copy(key->pn, ml_key_param->pn,
2319 WMI_MAX_PN_LEN);
2320 qdf_mem_copy(key->key_buff, ml_key_param->key_buff,
2321 WMI_MAX_KEY_LEN);
2322 wmi_debug("link_id: %u key_idx: %u key_cipher: %u",
2323 key->link_id, key->key_idx, key->key_cipher);
2324 ml_key_param++;
2325 }
2326
2327 return QDF_STATUS_SUCCESS;
2328 }
2329 #else
2330 static QDF_STATUS
wmi_fill_roam_mlo_info(wmi_unified_t wmi_handle,WMI_ROAM_SYNCH_EVENTID_param_tlvs * param_buf,struct roam_offload_synch_ind * roam_sync_ind)2331 wmi_fill_roam_mlo_info(wmi_unified_t wmi_handle,
2332 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf,
2333 struct roam_offload_synch_ind *roam_sync_ind)
2334 {
2335 return QDF_STATUS_SUCCESS;
2336 }
2337 #endif
2338
2339 static QDF_STATUS
wmi_fill_roam_sync_buffer(wmi_unified_t wmi_handle,struct wlan_objmgr_vdev * vdev,struct rso_config * rso_cfg,struct roam_offload_synch_ind * roam_sync_ind,WMI_ROAM_SYNCH_EVENTID_param_tlvs * param_buf)2340 wmi_fill_roam_sync_buffer(wmi_unified_t wmi_handle,
2341 struct wlan_objmgr_vdev *vdev,
2342 struct rso_config *rso_cfg,
2343 struct roam_offload_synch_ind *roam_sync_ind,
2344 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf)
2345 {
2346 wmi_roam_synch_event_fixed_param *synch_event;
2347 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2348 wmi_channel *chan = NULL;
2349 wmi_key_material *key;
2350 wmi_key_material_ext *key_ext;
2351 wmi_roam_fils_synch_tlv_param *fils_info;
2352 wmi_roam_pmk_cache_synch_tlv_param *pmk_cache_info;
2353 QDF_STATUS status = QDF_STATUS_E_FAILURE;
2354 uint8_t kck_len;
2355 uint8_t kek_len;
2356 struct roam_scan_candidate_frame roam_candidate = {0};
2357
2358 synch_event = param_buf->fixed_param;
2359 roam_sync_ind->roamed_vdev_id = synch_event->vdev_id;
2360 roam_sync_ind->auth_status = synch_event->auth_status;
2361 roam_sync_ind->roam_reason = synch_event->roam_reason;
2362 roam_sync_ind->rssi = -1 * synch_event->rssi;
2363 roam_sync_ind->is_beacon = synch_event->is_beacon;
2364
2365 WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid,
2366 roam_sync_ind->bssid.bytes);
2367 wmi_debug("roamed_vdev_id %d auth_status %d roam_reason %d rssi %d is_beacon %d",
2368 roam_sync_ind->roamed_vdev_id,
2369 roam_sync_ind->auth_status,
2370 roam_sync_ind->roam_reason,
2371 roam_sync_ind->rssi,
2372 roam_sync_ind->is_beacon);
2373
2374 cdp_update_roaming_peer_in_vdev(soc, synch_event->vdev_id,
2375 roam_sync_ind->bssid.bytes,
2376 synch_event->auth_status);
2377 /*
2378 * If lengths of bcn_probe_rsp, reassoc_req and reassoc_rsp are zero in
2379 * synch_event driver would have received bcn_probe_rsp, reassoc_req
2380 * and reassoc_rsp via the event WMI_ROAM_SYNCH_FRAME_EVENTID
2381 */
2382 if ((!synch_event->bcn_probe_rsp_len) &&
2383 (!synch_event->reassoc_req_len) &&
2384 (!synch_event->reassoc_rsp_len)) {
2385 if (!rso_cfg->roam_sync_frame_ind.bcn_probe_rsp) {
2386 wmi_err("LFR3: bcn_probe_rsp is NULL");
2387 QDF_ASSERT(rso_cfg->roam_sync_frame_ind.bcn_probe_rsp);
2388 wlan_cm_free_roam_synch_frame_ind(rso_cfg);
2389 return status;
2390 }
2391
2392 if (!rso_cfg->roam_sync_frame_ind.reassoc_rsp) {
2393 wmi_err("LFR3: reassoc_rsp is NULL");
2394 QDF_ASSERT(rso_cfg->roam_sync_frame_ind.reassoc_rsp);
2395 wlan_cm_free_roam_synch_frame_ind(rso_cfg);
2396 return status;
2397 }
2398 if (!rso_cfg->roam_sync_frame_ind.reassoc_req) {
2399 wmi_err("LFR3: reassoc_req is NULL");
2400 QDF_ASSERT(rso_cfg->roam_sync_frame_ind.reassoc_req);
2401 wlan_cm_free_roam_synch_frame_ind(rso_cfg);
2402 return status;
2403 }
2404 wmi_fill_data_synch_frame_event(rso_cfg, roam_sync_ind);
2405 } else {
2406 wmi_fill_data_synch_event(roam_sync_ind, param_buf);
2407
2408 roam_candidate.vdev_id = roam_sync_ind->roamed_vdev_id;
2409 roam_candidate.frame_length =
2410 roam_sync_ind->beacon_probe_resp_length;
2411 roam_candidate.frame = (uint8_t *)roam_sync_ind +
2412 roam_sync_ind->beacon_probe_resp_offset;
2413 roam_candidate.rssi = roam_sync_ind->rssi;
2414 roam_candidate.roam_offload_candidate_frm = false;
2415 wlan_cm_add_all_link_probe_rsp_to_scan_db(wlan_vdev_get_psoc(vdev),
2416 &roam_candidate);
2417 }
2418 chan = param_buf->chan;
2419 if (chan) {
2420 roam_sync_ind->chan_freq = chan->mhz;
2421 roam_sync_ind->phy_mode =
2422 wlan_cm_fw_to_host_phymode(WMI_GET_CHANNEL_MODE(chan));
2423 roam_sync_ind->chan = *chan;
2424 } else {
2425 roam_sync_ind->phy_mode = WLAN_PHYMODE_AUTO;
2426 }
2427
2428 key = param_buf->key;
2429 key_ext = param_buf->key_ext;
2430 if (key) {
2431 roam_sync_ind->kck_len = KCK_KEY_LEN;
2432 qdf_mem_copy(roam_sync_ind->kck, key->kck,
2433 KCK_KEY_LEN);
2434 roam_sync_ind->kek_len = KEK_KEY_LEN;
2435 qdf_mem_copy(roam_sync_ind->kek, key->kek,
2436 KEK_KEY_LEN);
2437 qdf_mem_copy(roam_sync_ind->replay_ctr,
2438 key->replay_counter, REPLAY_CTR_LEN);
2439 } else if (key_ext) {
2440 /*
2441 * key_ext carries key materials whose size
2442 * is greater than conventional 16bytes.
2443 */
2444 kck_len = key_ext->kck_len ?
2445 key_ext->kck_len : KCK_192BIT_KEY_LEN;
2446 kek_len = key_ext->kek_len ?
2447 key_ext->kek_len : KEK_256BIT_KEY_LEN;
2448
2449 roam_sync_ind->kck_len = kck_len;
2450 qdf_mem_copy(roam_sync_ind->kck,
2451 key_ext->key_buffer, kck_len);
2452
2453 roam_sync_ind->kek_len = kek_len;
2454 qdf_mem_copy(roam_sync_ind->kek,
2455 (key_ext->key_buffer + kck_len),
2456 kek_len);
2457
2458 qdf_mem_copy(roam_sync_ind->replay_ctr,
2459 (key_ext->key_buffer + kek_len + kck_len),
2460 REPLAY_CTR_LEN);
2461 }
2462
2463 wmi_debug("ROAM_SYNC kek_len %d kck_len %d",
2464 roam_sync_ind->kek_len,
2465 roam_sync_ind->kck_len);
2466
2467 if (param_buf->hw_mode_transition_fixed_param) {
2468 wmi_extract_pdev_hw_mode_trans_ind(
2469 param_buf->hw_mode_transition_fixed_param,
2470 param_buf->wmi_pdev_set_hw_mode_response_vdev_mac_mapping,
2471 &roam_sync_ind->hw_mode_trans_ind);
2472 roam_sync_ind->hw_mode_trans_present = true;
2473 } else {
2474 wmi_debug("hw_mode transition fixed param is NULL");
2475 }
2476
2477 fils_info = param_buf->roam_fils_synch_info;
2478 if (fils_info) {
2479 if ((fils_info->kek_len > MAX_KEK_LENGTH) ||
2480 (fils_info->pmk_len > MAX_PMK_LEN)) {
2481 wmi_err("Invalid kek_len %d or pmk_len %d",
2482 fils_info->kek_len,
2483 fils_info->pmk_len);
2484 wlan_cm_free_roam_synch_frame_ind(rso_cfg);
2485 return status;
2486 }
2487
2488 roam_sync_ind->kek_len = fils_info->kek_len;
2489 qdf_mem_copy(roam_sync_ind->kek, fils_info->kek,
2490 fils_info->kek_len);
2491
2492 roam_sync_ind->pmk_len = fils_info->pmk_len;
2493 qdf_mem_copy(roam_sync_ind->pmk, fils_info->pmk,
2494 fils_info->pmk_len);
2495
2496 qdf_mem_copy(roam_sync_ind->pmkid, fils_info->pmkid,
2497 PMKID_LEN);
2498
2499 roam_sync_ind->update_erp_next_seq_num =
2500 fils_info->update_erp_next_seq_num;
2501 roam_sync_ind->next_erp_seq_num =
2502 fils_info->next_erp_seq_num;
2503
2504 wmi_debug("Update ERP Seq Num %d, Next ERP Seq Num %d KEK len %d",
2505 roam_sync_ind->update_erp_next_seq_num,
2506 roam_sync_ind->next_erp_seq_num,
2507 roam_sync_ind->kek_len);
2508 }
2509
2510 pmk_cache_info = param_buf->roam_pmk_cache_synch_info;
2511 if (pmk_cache_info && (pmk_cache_info->pmk_len)) {
2512 if (pmk_cache_info->pmk_len > MAX_PMK_LEN) {
2513 wmi_err("Invalid pmk_len %d",
2514 pmk_cache_info->pmk_len);
2515 wlan_cm_free_roam_synch_frame_ind(rso_cfg);
2516 return status;
2517 }
2518
2519 roam_sync_ind->pmk_len = pmk_cache_info->pmk_len;
2520 qdf_mem_copy(roam_sync_ind->pmk,
2521 pmk_cache_info->pmk, pmk_cache_info->pmk_len);
2522 qdf_mem_copy(roam_sync_ind->pmkid,
2523 pmk_cache_info->pmkid, PMKID_LEN);
2524 }
2525
2526 status = wmi_fill_roam_mlo_info(wmi_handle, param_buf, roam_sync_ind);
2527 if (QDF_IS_STATUS_ERROR(status)) {
2528 wmi_err("Failed to fill roam mlo info");
2529 return status;
2530 }
2531 wlan_cm_free_roam_synch_frame_ind(rso_cfg);
2532 return QDF_STATUS_SUCCESS;
2533 }
2534
2535 /**
2536 * extract_roam_sync_event_tlv() - Extract the roam sync event
2537 * from the wmi_roam_synch_event_id
2538 * @wmi_handle: wmi handle
2539 * @evt_buf: Pointer to the event buffer
2540 * @len: Data length
2541 * @roam_sync_ind: Ptr to roam offload sync struct
2542 */
2543 static QDF_STATUS
extract_roam_sync_event_tlv(wmi_unified_t wmi_handle,void * evt_buf,uint32_t len,struct roam_offload_synch_ind ** roam_sync_ind)2544 extract_roam_sync_event_tlv(wmi_unified_t wmi_handle, void *evt_buf,
2545 uint32_t len,
2546 struct roam_offload_synch_ind **roam_sync_ind)
2547 {
2548 QDF_STATUS status = QDF_STATUS_SUCCESS;
2549 wmi_roam_synch_event_fixed_param *synch_event = NULL;
2550 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf = NULL;
2551 struct roam_offload_synch_ind *roam_sync = NULL;
2552 struct wlan_objmgr_vdev *vdev = NULL;
2553 struct wlan_objmgr_psoc *psoc = NULL;
2554 struct rso_config *rso_cfg;
2555 uint32_t roam_synch_data_len;
2556 uint32_t bcn_probe_rsp_len, link_bcn_probe_rsp_len;
2557 uint32_t reassoc_rsp_len;
2558 uint32_t reassoc_req_len;
2559 wmi_pdev_hw_mode_transition_event_fixed_param *hw_mode_trans_param;
2560
2561 if (!evt_buf) {
2562 wmi_debug("Empty roam_sync_event param buf");
2563 return QDF_STATUS_E_FAILURE;
2564 }
2565
2566 param_buf = (WMI_ROAM_SYNCH_EVENTID_param_tlvs *)evt_buf;
2567 if (!param_buf) {
2568 wmi_debug("received null buf from target");
2569 return QDF_STATUS_E_FAILURE;
2570 }
2571
2572 synch_event = param_buf->fixed_param;
2573 if (!synch_event) {
2574 wmi_debug("received null event data from target");
2575 return QDF_STATUS_E_FAILURE;
2576 }
2577 hw_mode_trans_param = param_buf->hw_mode_transition_fixed_param;
2578 if (hw_mode_trans_param &&
2579 hw_mode_trans_param->num_vdev_mac_entries >
2580 param_buf->num_wmi_pdev_set_hw_mode_response_vdev_mac_mapping) {
2581 wmi_debug("invalid vdev mac entries %d %d in roam sync",
2582 hw_mode_trans_param->num_vdev_mac_entries,
2583 param_buf->num_wmi_pdev_set_hw_mode_response_vdev_mac_mapping);
2584 return QDF_STATUS_E_FAILURE;
2585 }
2586
2587 if (synch_event->vdev_id >= WLAN_MAX_VDEVS) {
2588 wmi_err("received invalid vdev_id %d",
2589 synch_event->vdev_id);
2590 return QDF_STATUS_E_FAILURE;
2591 }
2592
2593 psoc = wmi_handle->soc->wmi_psoc;
2594 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, synch_event->vdev_id,
2595 WLAN_MLME_SB_ID);
2596 if (!vdev) {
2597 wmi_err("For vdev:%d object is NULL", synch_event->vdev_id);
2598 return QDF_STATUS_E_FAILURE;
2599 }
2600
2601 if (synch_event->bcn_probe_rsp_len >
2602 param_buf->num_bcn_probe_rsp_frame ||
2603 synch_event->reassoc_req_len >
2604 param_buf->num_reassoc_req_frame ||
2605 synch_event->reassoc_rsp_len >
2606 param_buf->num_reassoc_rsp_frame) {
2607 wmi_debug("Invalid sync payload: LEN bcn:%d, req:%d, rsp:%d, vdev:%d",
2608 synch_event->bcn_probe_rsp_len,
2609 synch_event->reassoc_req_len,
2610 synch_event->reassoc_rsp_len,
2611 synch_event->vdev_id);
2612 status = QDF_STATUS_E_FAILURE;
2613 goto abort_roam;
2614 }
2615
2616 rso_cfg = wlan_cm_get_rso_config(vdev);
2617 if (!rso_cfg) {
2618 status = QDF_STATUS_E_FAILURE;
2619 goto abort_roam;
2620 }
2621
2622 /*
2623 * All below length fields are unsigned and hence positive numbers.
2624 * Maximum number during the addition would be (3 * MAX_LIMIT(UINT32) +
2625 * few fixed fields).
2626 */
2627 wmi_debug("synch payload: LEN bcn:%d, req:%d, rsp:%d",
2628 synch_event->bcn_probe_rsp_len,
2629 synch_event->reassoc_req_len,
2630 synch_event->reassoc_rsp_len);
2631
2632 /*
2633 * If lengths of bcn_probe_rsp, reassoc_req and reassoc_rsp are zero in
2634 * synch_event driver would have received bcn_probe_rsp, reassoc_req
2635 * and reassoc_rsp via the event WMI_ROAM_SYNCH_FRAME_EVENTID
2636 */
2637 if ((!synch_event->bcn_probe_rsp_len) &&
2638 (!synch_event->reassoc_req_len) &&
2639 (!synch_event->reassoc_rsp_len)) {
2640 bcn_probe_rsp_len =
2641 rso_cfg->roam_sync_frame_ind.bcn_probe_rsp_len;
2642 link_bcn_probe_rsp_len =
2643 rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp_len;
2644 reassoc_req_len = rso_cfg->roam_sync_frame_ind.reassoc_req_len;
2645 reassoc_rsp_len = rso_cfg->roam_sync_frame_ind.reassoc_rsp_len;
2646
2647 roam_synch_data_len =
2648 bcn_probe_rsp_len + link_bcn_probe_rsp_len +
2649 reassoc_rsp_len + reassoc_req_len +
2650 sizeof(struct roam_offload_synch_ind);
2651
2652 wmi_debug("Updated synch payload: LEN bcn:%d, link bcn: %d req:%d, rsp:%d",
2653 bcn_probe_rsp_len,
2654 link_bcn_probe_rsp_len,
2655 reassoc_req_len,
2656 reassoc_rsp_len);
2657 } else {
2658 bcn_probe_rsp_len = synch_event->bcn_probe_rsp_len;
2659 reassoc_req_len = synch_event->reassoc_req_len;
2660 reassoc_rsp_len = synch_event->reassoc_rsp_len;
2661
2662 roam_synch_data_len = bcn_probe_rsp_len +
2663 reassoc_rsp_len + reassoc_req_len;
2664 roam_synch_data_len += sizeof(struct roam_offload_synch_ind);
2665 }
2666
2667 roam_sync = qdf_mem_malloc(roam_synch_data_len);
2668 if (!roam_sync) {
2669 QDF_ASSERT(roam_sync);
2670 status = QDF_STATUS_E_NOMEM;
2671 goto abort_roam;
2672 }
2673
2674 *roam_sync_ind = roam_sync;
2675 status = wmi_fill_roam_sync_buffer(wmi_handle, vdev, rso_cfg,
2676 roam_sync, param_buf);
2677
2678 abort_roam:
2679 if (QDF_IS_STATUS_ERROR(status)) {
2680 wmi_err("%d Failed to extract roam sync ind", status);
2681 wlan_cm_roam_state_change(wlan_vdev_get_pdev(vdev),
2682 synch_event->vdev_id,
2683 WLAN_ROAM_RSO_STOPPED,
2684 REASON_ROAM_SYNCH_FAILED);
2685 }
2686 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
2687 return status;
2688 }
2689
2690 /**
2691 * extract_roam_sync_frame_event_tlv() - Extract the roam sync frame event
2692 * from the wmi_roam_synch_event_id
2693 * @wmi_handle: wmi handle
2694 * @event: Pointer to the event buffer
2695 * @len: event buffer length
2696 * @frame_ptr: wmi sync frame event ptr
2697 */
2698 static QDF_STATUS
extract_roam_sync_frame_event_tlv(wmi_unified_t wmi_handle,void * event,uint32_t len,struct roam_synch_frame_ind * frame_ptr)2699 extract_roam_sync_frame_event_tlv(wmi_unified_t wmi_handle, void *event,
2700 uint32_t len,
2701 struct roam_synch_frame_ind *frame_ptr)
2702 {
2703 WMI_ROAM_SYNCH_FRAME_EVENTID_param_tlvs *param_buf = NULL;
2704 struct roam_synch_frame_ind *frame_ind;
2705 wmi_roam_synch_frame_event_fixed_param *frame_evt;
2706
2707 if (!event) {
2708 wmi_err("Event param null");
2709 return QDF_STATUS_E_NULL_VALUE;
2710 }
2711
2712 param_buf = (WMI_ROAM_SYNCH_FRAME_EVENTID_param_tlvs *)event;
2713 if (!param_buf) {
2714 wmi_err("received null buf from target");
2715 return QDF_STATUS_E_NULL_VALUE;
2716 }
2717
2718 frame_evt = param_buf->fixed_param;
2719 if (!frame_evt) {
2720 wmi_err("received null event data from target");
2721 return QDF_STATUS_E_NULL_VALUE;
2722 }
2723
2724 if (frame_evt->vdev_id >= WLAN_MAX_VDEVS) {
2725 wmi_err("received invalid vdev_id %d", frame_evt->vdev_id);
2726 return QDF_STATUS_E_FAILURE;
2727 }
2728
2729 /*
2730 * Firmware can send more than one roam synch frame event to host
2731 * driver. So Bcn_prb_rsp_len/reassoc_req_len/reassoc_rsp_len can be 0
2732 * in some of the events.
2733 */
2734 if (frame_evt->bcn_probe_rsp_len > param_buf->num_bcn_probe_rsp_frame ||
2735 frame_evt->reassoc_req_len > param_buf->num_reassoc_req_frame ||
2736 frame_evt->reassoc_rsp_len > param_buf->num_reassoc_rsp_frame ||
2737 (frame_evt->bcn_probe_rsp_len &&
2738 frame_evt->bcn_probe_rsp_len < sizeof(struct wlan_frame_hdr)) ||
2739 (frame_evt->reassoc_req_len &&
2740 frame_evt->reassoc_req_len < sizeof(struct wlan_frame_hdr)) ||
2741 (frame_evt->reassoc_rsp_len &&
2742 frame_evt->reassoc_rsp_len < sizeof(struct wlan_frame_hdr))) {
2743 wmi_err("fixed/actual len err: bcn:%d/%d req:%d/%d rsp:%d/%d",
2744 frame_evt->bcn_probe_rsp_len,
2745 param_buf->num_bcn_probe_rsp_frame,
2746 frame_evt->reassoc_req_len,
2747 param_buf->num_reassoc_req_frame,
2748 frame_evt->reassoc_rsp_len,
2749 param_buf->num_reassoc_rsp_frame);
2750 return QDF_STATUS_E_FAILURE;
2751 }
2752
2753 frame_ind = frame_ptr;
2754 frame_ind->vdev_id = frame_evt->vdev_id;
2755
2756 wmi_debug("synch frame payload: LEN %s bcn:%d, req:%d, rsp:%d",
2757 frame_evt->reassoc_rsp_len ? "Assoc" : "Link",
2758 frame_evt->bcn_probe_rsp_len,
2759 frame_evt->reassoc_req_len,
2760 frame_evt->reassoc_rsp_len);
2761
2762 if (frame_evt->bcn_probe_rsp_len &&
2763 frame_evt->reassoc_rsp_len) {
2764 frame_ind->bcn_probe_rsp_len = frame_evt->bcn_probe_rsp_len;
2765
2766 frame_ind->is_beacon = frame_evt->is_beacon;
2767
2768 frame_ind->bcn_probe_rsp =
2769 qdf_mem_malloc(frame_ind->bcn_probe_rsp_len);
2770 if (!frame_ind->bcn_probe_rsp) {
2771 QDF_ASSERT(frame_ind->bcn_probe_rsp);
2772 return QDF_STATUS_E_NOMEM;
2773 }
2774 qdf_mem_copy(frame_ind->bcn_probe_rsp,
2775 param_buf->bcn_probe_rsp_frame,
2776 frame_ind->bcn_probe_rsp_len);
2777 } else if (frame_evt->bcn_probe_rsp_len) {
2778 frame_ind->link_bcn_probe_rsp_len =
2779 frame_evt->bcn_probe_rsp_len;
2780
2781 frame_ind->is_link_beacon = frame_evt->is_beacon;
2782
2783 if (frame_ind->link_bcn_probe_rsp)
2784 qdf_mem_free(frame_ind->bcn_probe_rsp);
2785
2786 frame_ind->link_bcn_probe_rsp =
2787 qdf_mem_malloc(frame_ind->link_bcn_probe_rsp_len);
2788 if (!frame_ind->link_bcn_probe_rsp) {
2789 QDF_ASSERT(frame_ind->link_bcn_probe_rsp);
2790 return QDF_STATUS_E_NOMEM;
2791 }
2792 qdf_mem_copy(frame_ind->link_bcn_probe_rsp,
2793 param_buf->bcn_probe_rsp_frame,
2794 frame_ind->link_bcn_probe_rsp_len);
2795 }
2796
2797 if (frame_evt->reassoc_req_len) {
2798 frame_ind->reassoc_req_len = frame_evt->reassoc_req_len;
2799
2800 frame_ind->reassoc_req =
2801 qdf_mem_malloc(frame_ind->reassoc_req_len);
2802 if (!frame_ind->reassoc_req) {
2803 QDF_ASSERT(frame_ind->reassoc_req);
2804 return QDF_STATUS_E_NOMEM;
2805 }
2806 qdf_mem_copy(frame_ind->reassoc_req,
2807 param_buf->reassoc_req_frame,
2808 frame_ind->reassoc_req_len);
2809 }
2810
2811 if (frame_evt->reassoc_rsp_len) {
2812 frame_ind->reassoc_rsp_len = frame_evt->reassoc_rsp_len;
2813
2814 frame_ind->reassoc_rsp =
2815 qdf_mem_malloc(frame_ind->reassoc_rsp_len);
2816 if (!frame_ind->reassoc_rsp) {
2817 QDF_ASSERT(frame_ind->reassoc_rsp);
2818 return QDF_STATUS_E_NOMEM;
2819 }
2820 qdf_mem_copy(frame_ind->reassoc_rsp,
2821 param_buf->reassoc_rsp_frame,
2822 frame_ind->reassoc_rsp_len);
2823 }
2824
2825 return QDF_STATUS_SUCCESS;
2826 }
2827
wmi_get_reject_reason(uint32_t reason)2828 static enum dlm_reject_ap_reason wmi_get_reject_reason(uint32_t reason)
2829 {
2830 switch (reason) {
2831 case WMI_BL_REASON_NUD_FAILURE:
2832 return REASON_NUD_FAILURE;
2833 case WMI_BL_REASON_STA_KICKOUT:
2834 return REASON_STA_KICKOUT;
2835 case WMI_BL_REASON_ROAM_HO_FAILURE:
2836 return REASON_ROAM_HO_FAILURE;
2837 case WMI_BL_REASON_ASSOC_REJECT_POOR_RSSI:
2838 return REASON_ASSOC_REJECT_POOR_RSSI;
2839 case WMI_BL_REASON_ASSOC_REJECT_OCE:
2840 return REASON_ASSOC_REJECT_OCE;
2841 case WMI_BL_REASON_USERSPACE_BL:
2842 return REASON_USERSPACE_BL;
2843 case WMI_BL_REASON_USERSPACE_AVOID_LIST:
2844 return REASON_USERSPACE_AVOID_LIST;
2845 case WMI_BL_REASON_BTM_DIASSOC_IMMINENT:
2846 return REASON_BTM_DISASSOC_IMMINENT;
2847 case WMI_BL_REASON_BTM_BSS_TERMINATION:
2848 return REASON_BTM_BSS_TERMINATION;
2849 case WMI_BL_REASON_BTM_MBO_RETRY:
2850 return REASON_BTM_MBO_RETRY;
2851 case WMI_BL_REASON_REASSOC_RSSI_REJECT:
2852 return REASON_REASSOC_RSSI_REJECT;
2853 case WMI_BL_REASON_REASSOC_NO_MORE_STAS:
2854 return REASON_REASSOC_NO_MORE_STAS;
2855 default:
2856 return REASON_UNKNOWN;
2857 }
2858 }
2859
2860 static QDF_STATUS
extract_btm_denylist_event(wmi_unified_t wmi_handle,uint8_t * event,uint32_t len,struct roam_denylist_event ** list)2861 extract_btm_denylist_event(wmi_unified_t wmi_handle,
2862 uint8_t *event, uint32_t len,
2863 struct roam_denylist_event **list)
2864 {
2865 WMI_ROAM_BLACKLIST_EVENTID_param_tlvs *param_buf;
2866 wmi_roam_blacklist_event_fixed_param *resp_event;
2867 wmi_roam_blacklist_with_timeout_tlv_param *src_list;
2868 struct roam_denylist_timeout *roam_denylist;
2869 struct roam_denylist_event *dst_list;
2870 uint32_t num_entries, i;
2871
2872 param_buf = (WMI_ROAM_BLACKLIST_EVENTID_param_tlvs *)event;
2873 if (!param_buf) {
2874 wmi_err("Invalid event buffer");
2875 return QDF_STATUS_E_INVAL;
2876 }
2877
2878 resp_event = param_buf->fixed_param;
2879 if (!resp_event) {
2880 wmi_err("received null event data from target");
2881 return QDF_STATUS_E_INVAL;
2882 }
2883
2884 if (resp_event->vdev_id >= WLAN_MAX_VDEVS) {
2885 wmi_err("received invalid vdev_id %d", resp_event->vdev_id);
2886 return QDF_STATUS_E_INVAL;
2887 }
2888
2889 num_entries = param_buf->num_blacklist_with_timeout;
2890 if (num_entries == 0)
2891 return QDF_STATUS_SUCCESS;
2892
2893 if (num_entries > MAX_RSSI_AVOID_BSSID_LIST) {
2894 wmi_err("num blacklist entries:%d exceeds maximum value",
2895 num_entries);
2896 return QDF_STATUS_E_INVAL;
2897 }
2898
2899 src_list = param_buf->blacklist_with_timeout;
2900 if (len < (sizeof(*resp_event) + (num_entries * sizeof(*src_list)))) {
2901 wmi_err("Invalid length:%d", len);
2902 return QDF_STATUS_E_INVAL;
2903 }
2904
2905 dst_list = qdf_mem_malloc(sizeof(struct roam_denylist_event) +
2906 (sizeof(struct roam_denylist_timeout) *
2907 num_entries));
2908 if (!dst_list)
2909 return QDF_STATUS_E_NOMEM;
2910
2911 dst_list->vdev_id = resp_event->vdev_id;
2912 roam_denylist = &dst_list->roam_denylist[0];
2913 for (i = 0; i < num_entries; i++) {
2914 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_list->bssid,
2915 roam_denylist->bssid.bytes);
2916 roam_denylist->timeout = src_list->timeout;
2917 roam_denylist->received_time = src_list->timestamp;
2918 roam_denylist->original_timeout = src_list->original_timeout;
2919 roam_denylist->reject_reason =
2920 wmi_get_reject_reason(src_list->reason);
2921 roam_denylist->source = src_list->source;
2922 roam_denylist++;
2923 src_list++;
2924 }
2925
2926 dst_list->num_entries = num_entries;
2927 *list = dst_list;
2928
2929 return QDF_STATUS_SUCCESS;
2930 }
2931
2932 static QDF_STATUS
extract_vdev_disconnect_event_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint32_t data_len,struct vdev_disconnect_event_data * data)2933 extract_vdev_disconnect_event_tlv(wmi_unified_t wmi_handle,
2934 uint8_t *event, uint32_t data_len,
2935 struct vdev_disconnect_event_data *data)
2936 {
2937 WMI_VDEV_DISCONNECT_EVENTID_param_tlvs *param_buf;
2938 wmi_vdev_disconnect_event_fixed_param *roam_vdev_disc_ev;
2939
2940 param_buf = (WMI_VDEV_DISCONNECT_EVENTID_param_tlvs *)event;
2941
2942 roam_vdev_disc_ev = param_buf->fixed_param;
2943 if (!roam_vdev_disc_ev) {
2944 wmi_err("roam cap event is NULL");
2945 return QDF_STATUS_E_INVAL;
2946 }
2947
2948 if (roam_vdev_disc_ev->vdev_id >= WLAN_MAX_VDEVS) {
2949 wmi_err("Invalid vdev id %d", roam_vdev_disc_ev->vdev_id);
2950 return QDF_STATUS_E_INVAL;
2951 }
2952 data->vdev_id = roam_vdev_disc_ev->vdev_id;
2953 data->reason = roam_vdev_disc_ev->reason;
2954
2955 wmi_debug("Received disconnect roam event on vdev_id : %d, reason:%d",
2956 data->vdev_id, data->reason);
2957
2958 return QDF_STATUS_SUCCESS;
2959 }
2960
2961 static QDF_STATUS
extract_roam_scan_chan_list_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint32_t data_len,struct cm_roam_scan_ch_resp ** list)2962 extract_roam_scan_chan_list_tlv(wmi_unified_t wmi_handle,
2963 uint8_t *event, uint32_t data_len,
2964 struct cm_roam_scan_ch_resp **list)
2965 {
2966 WMI_ROAM_SCAN_CHANNEL_LIST_EVENTID_param_tlvs *param_buf;
2967 wmi_roam_scan_channel_list_event_fixed_param *fixed_param;
2968 struct cm_roam_scan_ch_resp *data;
2969 uint8_t i = 0, num_ch = 0;
2970
2971 param_buf = (WMI_ROAM_SCAN_CHANNEL_LIST_EVENTID_param_tlvs *)event;
2972 if (!param_buf) {
2973 wmi_err_rl("NULL event received from target");
2974 return -EINVAL;
2975 }
2976
2977 fixed_param = param_buf->fixed_param;
2978 if (!fixed_param) {
2979 wmi_err_rl(" NULL fixed param");
2980 return -EINVAL;
2981 }
2982
2983 if (fixed_param->vdev_id >= WLAN_MAX_VDEVS) {
2984 wmi_err_rl("Invalid vdev_id %d", fixed_param->vdev_id);
2985 return -EINVAL;
2986 }
2987
2988 num_ch = (param_buf->num_channel_list < CM_CFG_VALID_CHANNEL_LIST_LEN) ?
2989 param_buf->num_channel_list : CM_CFG_VALID_CHANNEL_LIST_LEN;
2990
2991 data = qdf_mem_malloc(sizeof(struct cm_roam_scan_ch_resp) +
2992 num_ch * sizeof(param_buf->channel_list[0]));
2993 if (!data)
2994 return -EINVAL;
2995
2996 data->chan_list = (uint32_t *)(data + 1);
2997 data->vdev_id = fixed_param->vdev_id;
2998 data->command_resp = fixed_param->command_response;
2999 data->num_channels = param_buf->num_channel_list;
3000
3001 for (i = 0; i < num_ch; i++)
3002 data->chan_list[i] = param_buf->channel_list[i];
3003
3004 *list = data;
3005 return QDF_STATUS_SUCCESS;
3006 }
3007
3008 static QDF_STATUS
extract_roam_stats_with_single_tlv(wmi_unified_t wmi_handle,uint8_t * evt_buf,struct roam_stats_event * stats_info)3009 extract_roam_stats_with_single_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf,
3010 struct roam_stats_event *stats_info)
3011 {
3012 QDF_STATUS status;
3013 uint8_t vdev_id = stats_info->vdev_id;
3014
3015 status = wmi_unified_extract_roam_scan_stats(
3016 wmi_handle, evt_buf, &stats_info->scan[0], 0, 0, 0);
3017 if (QDF_IS_STATUS_ERROR(status))
3018 wmi_debug("Roam scan stats extract failed vdev %d", vdev_id);
3019
3020 status = wmi_unified_extract_roam_11kv_stats(
3021 wmi_handle, evt_buf, &stats_info->data_11kv[0], 0, 0);
3022 if (QDF_IS_STATUS_ERROR(status))
3023 wmi_debug("Roam 11kv stats extract failed vdev %d", vdev_id);
3024
3025 status = wmi_unified_extract_roam_trigger_stats(
3026 wmi_handle, evt_buf, &stats_info->trigger[0], 0, 0);
3027 if (QDF_IS_STATUS_ERROR(status))
3028 wmi_debug("Extract roamtrigger stats failed vdev %d",
3029 vdev_id);
3030
3031 status = wmi_unified_extract_roam_btm_response(
3032 wmi_handle, evt_buf, &stats_info->btm_rsp[0], 0);
3033 if (QDF_IS_STATUS_ERROR(status))
3034 wmi_debug("Roam btm rsp stats extract fail vdev %d",
3035 vdev_id);
3036
3037 return QDF_STATUS_SUCCESS;
3038 }
3039
3040 /**
3041 * extract_roam_stats_event_tlv() - Extract the roam stats event
3042 * from the wmi_roam_stats_event_id
3043 * @wmi_handle: wmi handle
3044 * @evt_buf: Pointer to the event buffer
3045 * @len: Data length
3046 * @data: Double pointer to roam stats data
3047 */
3048 static QDF_STATUS
extract_roam_stats_event_tlv(wmi_unified_t wmi_handle,uint8_t * evt_buf,uint32_t len,struct roam_stats_event ** data)3049 extract_roam_stats_event_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf,
3050 uint32_t len,
3051 struct roam_stats_event **data)
3052 {
3053 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf;
3054 wmi_roam_stats_event_fixed_param *fixed_param;
3055 struct roam_stats_event *stats_info;
3056 struct roam_msg_info *roam_msg_info = NULL;
3057 uint8_t vdev_id, i, num_btm = 0, num_frames = 0;
3058 uint8_t num_tlv = 0, num_chan = 0, num_ap = 0, num_rpt = 0;
3059 uint8_t num_trigger_reason = 0;
3060 uint32_t rem_len;
3061 QDF_STATUS status;
3062
3063 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf;
3064 if (!param_buf) {
3065 wmi_err_rl("NULL event received from target");
3066 return QDF_STATUS_E_INVAL;
3067 }
3068
3069 fixed_param = param_buf->fixed_param;
3070 if (!fixed_param) {
3071 wmi_err_rl(" NULL fixed param");
3072 return QDF_STATUS_E_INVAL;
3073 }
3074
3075 vdev_id = fixed_param->vdev_id;
3076
3077 if (vdev_id >= WLAN_MAX_VDEVS) {
3078 wmi_err_rl("Invalid vdev_id %d", vdev_id);
3079 return QDF_STATUS_E_INVAL;
3080 }
3081
3082 num_tlv = fixed_param->roam_scan_trigger_count;
3083 if (num_tlv > MAX_ROAM_SCAN_STATS_TLV) {
3084 wmi_err_rl("Limiting roam triggers to 5");
3085 num_tlv = MAX_ROAM_SCAN_STATS_TLV;
3086 }
3087
3088 if (param_buf->roam_trigger_reason)
3089 num_trigger_reason = num_tlv;
3090 else
3091 num_trigger_reason = 0;
3092
3093 rem_len = len - sizeof(*fixed_param);
3094 if (rem_len < num_trigger_reason * sizeof(wmi_roam_trigger_reason)) {
3095 wmi_err_rl("Invalid roam trigger data");
3096 return QDF_STATUS_E_INVAL;
3097 }
3098
3099 rem_len -= num_trigger_reason * sizeof(wmi_roam_trigger_reason);
3100 if (rem_len < num_tlv * sizeof(wmi_roam_scan_info)) {
3101 wmi_err_rl("Invalid roam scan data");
3102 return QDF_STATUS_E_INVAL;
3103 }
3104
3105 rem_len -= num_tlv * sizeof(wmi_roam_scan_info);
3106 if (rem_len < num_tlv * sizeof(wmi_roam_result)) {
3107 wmi_err_rl("Invalid roam result data");
3108 return QDF_STATUS_E_INVAL;
3109 }
3110
3111 rem_len -= num_tlv * sizeof(wmi_roam_result);
3112 if (rem_len < (num_tlv * sizeof(wmi_roam_neighbor_report_info))) {
3113 wmi_err_rl("Invalid roam neighbor report data");
3114 return QDF_STATUS_E_INVAL;
3115 }
3116
3117 rem_len -= num_tlv * sizeof(wmi_roam_neighbor_report_info);
3118 if (rem_len < (param_buf->num_roam_scan_chan_info *
3119 sizeof(wmi_roam_scan_channel_info))) {
3120 wmi_err_rl("Invalid roam chan data num_tlv:%d",
3121 param_buf->num_roam_scan_chan_info);
3122 return QDF_STATUS_E_INVAL;
3123 }
3124
3125 rem_len -= param_buf->num_roam_scan_chan_info *
3126 sizeof(wmi_roam_scan_channel_info);
3127
3128 if (rem_len < (param_buf->num_roam_ap_info *
3129 sizeof(wmi_roam_ap_info))) {
3130 wmi_err_rl("Invalid roam ap data num_tlv:%d",
3131 param_buf->num_roam_ap_info);
3132 return QDF_STATUS_E_INVAL;
3133 }
3134
3135 rem_len -= param_buf->num_roam_ap_info * sizeof(wmi_roam_ap_info);
3136 if (rem_len < (param_buf->num_roam_neighbor_report_chan_info *
3137 sizeof(wmi_roam_neighbor_report_channel_info))) {
3138 wmi_err_rl("Invalid roam neigb rpt chan data num_tlv:%d",
3139 param_buf->num_roam_neighbor_report_chan_info);
3140 return QDF_STATUS_E_INVAL;
3141 }
3142
3143 rem_len -= param_buf->num_roam_neighbor_report_chan_info *
3144 sizeof(wmi_roam_neighbor_report_channel_info);
3145 if (rem_len < param_buf->num_roam_btm_response_info *
3146 sizeof(wmi_roam_btm_response_info)) {
3147 wmi_err_rl("Invalid btm rsp data");
3148 return QDF_STATUS_E_INVAL;
3149 }
3150
3151 rem_len -= param_buf->num_roam_btm_response_info *
3152 sizeof(wmi_roam_btm_response_info);
3153 if (rem_len < param_buf->num_roam_initial_info *
3154 sizeof(wmi_roam_initial_info)) {
3155 wmi_err_rl("Invalid Initial roam info");
3156 return QDF_STATUS_E_INVAL;
3157 }
3158
3159 rem_len -= param_buf->num_roam_initial_info *
3160 sizeof(wmi_roam_initial_info);
3161 if (rem_len < param_buf->num_roam_msg_info *
3162 sizeof(wmi_roam_msg_info)) {
3163 wmi_err_rl("Invalid roam msg info");
3164 return QDF_STATUS_E_INVAL;
3165 }
3166
3167 rem_len -= param_buf->num_roam_msg_info * sizeof(wmi_roam_msg_info);
3168 if (rem_len <
3169 param_buf->num_roam_frame_info * sizeof(wmi_roam_frame_info)) {
3170 wmi_err_rl("Invalid roam frame info");
3171 return QDF_STATUS_E_INVAL;
3172 }
3173
3174 stats_info = qdf_mem_malloc(sizeof(struct roam_stats_event));
3175 if (!stats_info) {
3176 status = QDF_STATUS_E_NOMEM;
3177 goto err;
3178 }
3179 *data = stats_info;
3180 qdf_mem_set(stats_info, sizeof(struct roam_stats_event), 0);
3181 stats_info->vdev_id = vdev_id;
3182 stats_info->num_roam_msg_info = param_buf->num_roam_msg_info;
3183 stats_info->num_tlv = num_tlv;
3184
3185 if (!num_tlv)
3186 extract_roam_stats_with_single_tlv(wmi_handle, evt_buf,
3187 stats_info);
3188
3189 for (i = 0; i < num_tlv; i++) {
3190 /*
3191 * Roam Trigger id and that specific roam trigger related
3192 * details.
3193 */
3194 status = wmi_unified_extract_roam_trigger_stats(wmi_handle,
3195 evt_buf,
3196 &stats_info->trigger[i], i,
3197 num_btm);
3198 if (QDF_IS_STATUS_ERROR(status)) {
3199 wmi_debug_rl("Extract roam trigger stats failed vdev %d at %d iteration",
3200 vdev_id, i);
3201 status = QDF_STATUS_E_INVAL;
3202 goto err;
3203 }
3204
3205 if (stats_info->trigger[i].trigger_reason ==
3206 WMI_ROAM_TRIGGER_REASON_BTM)
3207 num_btm += stats_info->trigger[i].btm_trig_data.candidate_list_count;
3208
3209 /* Roam scan related details - Scan channel, scan type .. */
3210 status = wmi_unified_extract_roam_scan_stats(wmi_handle,
3211 evt_buf,
3212 &stats_info->scan[i], i,
3213 num_chan, num_ap);
3214 if (QDF_IS_STATUS_ERROR(status)) {
3215 wmi_debug_rl("Roam scan stats extract failed vdev %d at %d iteration",
3216 vdev_id, i);
3217 status = QDF_STATUS_E_INVAL;
3218 goto err;
3219 }
3220 num_chan += stats_info->scan[i].num_chan;
3221 num_ap += stats_info->scan[i].num_ap;
3222 num_frames = stats_info->scan[i].frame_info_count;
3223
3224 /* Roam result - Success/Failure status, failure reason */
3225 status = wmi_unified_extract_roam_result_stats(wmi_handle,
3226 evt_buf,
3227 &stats_info->result[i], i);
3228 if (QDF_IS_STATUS_ERROR(status)) {
3229 wmi_debug_rl("Roam result stats extract failed vdev %d at %d iteration",
3230 vdev_id, i);
3231 status = QDF_STATUS_E_INVAL;
3232 goto err;
3233 }
3234
3235 if (num_frames) {
3236 status = wmi_unified_extract_roam_extract_frame_info(
3237 wmi_handle, evt_buf,
3238 &stats_info->frame_stats[i], i,
3239 num_frames);
3240 if (QDF_IS_STATUS_ERROR(status)) {
3241 wmi_debug_rl("Roam frame stats extract failed vdev %d at %d iteration",
3242 vdev_id, i);
3243 status = QDF_STATUS_E_INVAL;
3244 goto err;
3245 }
3246 }
3247
3248 /* BTM req/resp or Neighbor report/response info */
3249 status = wmi_unified_extract_roam_11kv_stats(
3250 wmi_handle,
3251 evt_buf,
3252 &stats_info->data_11kv[i],
3253 i, num_rpt);
3254 if (QDF_IS_STATUS_ERROR(status))
3255 wmi_debug_rl("Roam 11kv stats extract fail vdev %d iter %d",
3256 vdev_id, i);
3257
3258 if (stats_info->data_11kv[i].present)
3259 num_rpt += stats_info->data_11kv[i].num_freq;
3260
3261 /* BTM resp info */
3262 status = wmi_unified_extract_roam_btm_response(wmi_handle,
3263 evt_buf,
3264 &stats_info->btm_rsp[i],
3265 i);
3266 if (QDF_IS_STATUS_ERROR(status)) {
3267 wmi_debug_rl("Roam btm rsp stats extract fail vdev %d at %d iteration",
3268 vdev_id, i);
3269 status = QDF_STATUS_E_INVAL;
3270 goto err;
3271 }
3272
3273 /* Initial Roam info */
3274 status = wmi_unified_extract_roam_initial_info(wmi_handle,
3275 evt_buf,
3276 &stats_info->roam_init_info[i], i);
3277 if (QDF_IS_STATUS_ERROR(status)) {
3278 wmi_debug_rl("Initial roam stats extract fail vdev %d at %d iteration",
3279 vdev_id, i);
3280 status = QDF_STATUS_E_INVAL;
3281 goto err;
3282 }
3283 }
3284
3285 if (param_buf->roam_msg_info && param_buf->num_roam_msg_info) {
3286 roam_msg_info = qdf_mem_malloc(param_buf->num_roam_msg_info *
3287 sizeof(*roam_msg_info));
3288 if (!roam_msg_info) {
3289 status = QDF_STATUS_E_NOMEM;
3290 goto err;
3291 }
3292 stats_info->roam_msg_info = roam_msg_info;
3293 for (i = 0; i < param_buf->num_roam_msg_info; i++) {
3294 status = wmi_unified_extract_roam_msg_info(wmi_handle,
3295 evt_buf,
3296 &roam_msg_info[i], i);
3297 if (QDF_IS_STATUS_ERROR(status)) {
3298 wmi_err("roam msg stats extract fail vdev %d",
3299 vdev_id);
3300 status = QDF_STATUS_E_INVAL;
3301 goto err;
3302 }
3303 }
3304 }
3305 return QDF_STATUS_SUCCESS;
3306 err:
3307 if (stats_info) {
3308 if (roam_msg_info)
3309 qdf_mem_free(roam_msg_info);
3310 qdf_mem_free(stats_info);
3311 }
3312 return status;
3313 }
3314
3315 static QDF_STATUS
extract_auth_offload_event_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint32_t len,struct auth_offload_event * auth_event)3316 extract_auth_offload_event_tlv(wmi_unified_t wmi_handle,
3317 uint8_t *event, uint32_t len,
3318 struct auth_offload_event *auth_event)
3319 {
3320 wmi_roam_preauth_start_event_fixed_param *rso_auth_start_ev;
3321 WMI_ROAM_PREAUTH_START_EVENTID_param_tlvs *param_buf;
3322
3323 param_buf = (WMI_ROAM_PREAUTH_START_EVENTID_param_tlvs *) event;
3324
3325 rso_auth_start_ev = param_buf->fixed_param;
3326 if (!rso_auth_start_ev) {
3327 wmi_debug("received null event data from target");
3328 return QDF_STATUS_E_INVAL;
3329 }
3330
3331 if (rso_auth_start_ev->vdev_id > WLAN_MAX_VDEVS) {
3332 wmi_debug("received invalid vdev_id %d",
3333 rso_auth_start_ev->vdev_id);
3334 return QDF_STATUS_E_INVAL;
3335 }
3336
3337 auth_event->vdev_id = rso_auth_start_ev->vdev_id;
3338 auth_event->akm = rso_auth_start_ev->akm_suite_type;
3339
3340 WMI_MAC_ADDR_TO_CHAR_ARRAY(&rso_auth_start_ev->candidate_ap_bssid,
3341 auth_event->ap_bssid.bytes);
3342 WMI_MAC_ADDR_TO_CHAR_ARRAY(&rso_auth_start_ev->transmit_addr,
3343 auth_event->ta.bytes);
3344 if (qdf_is_macaddr_zero(&auth_event->ap_bssid) ||
3345 qdf_is_macaddr_broadcast(&auth_event->ap_bssid) ||
3346 qdf_is_macaddr_group(&auth_event->ap_bssid)) {
3347 wmi_debug("Invalid bssid");
3348 return -EINVAL;
3349 }
3350
3351 wmi_debug("Received Roam auth offload event for bss:"
3352 QDF_MAC_ADDR_FMT " ta:" QDF_MAC_ADDR_FMT " vdev_id: %d akm: %d",
3353 QDF_MAC_ADDR_REF(auth_event->ap_bssid.bytes),
3354 QDF_MAC_ADDR_REF(auth_event->ta.bytes),
3355 auth_event->vdev_id, auth_event->akm);
3356
3357 return QDF_STATUS_SUCCESS;
3358 }
3359
3360 /**
3361 * extract_roam_pmkid_request_tlv() - Extract the roam pmkid request event
3362 * @wmi_handle: wmi handle
3363 * @evt_buf: Pointer to the event buffer
3364 * @len: Data length
3365 * @list: Extract the data and fill in list
3366 */
3367 static QDF_STATUS
extract_roam_pmkid_request_tlv(wmi_unified_t wmi_handle,uint8_t * evt_buf,uint32_t len,struct roam_pmkid_req_event ** list)3368 extract_roam_pmkid_request_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf,
3369 uint32_t len,
3370 struct roam_pmkid_req_event **list)
3371 {
3372 WMI_ROAM_PMKID_REQUEST_EVENTID_param_tlvs *param_buf;
3373 wmi_roam_pmkid_request_event_fixed_param *roam_pmkid_req_ev;
3374 wmi_roam_pmkid_request_tlv_param *src_list;
3375 struct qdf_mac_addr *roam_bsslist;
3376 uint32_t num_entries, i;
3377 struct roam_pmkid_req_event *dst_list;
3378
3379 if (!evt_buf || !len) {
3380 wmi_err("received null event from target");
3381 return QDF_STATUS_E_INVAL;
3382 }
3383
3384 param_buf = (WMI_ROAM_PMKID_REQUEST_EVENTID_param_tlvs *)evt_buf;
3385 if (!param_buf) {
3386 wmi_err("received null buf from target");
3387 return QDF_STATUS_E_INVAL;
3388 }
3389
3390 roam_pmkid_req_ev = param_buf->fixed_param;
3391 if (!roam_pmkid_req_ev) {
3392 wmi_err("received null event data from target");
3393 return QDF_STATUS_E_INVAL;
3394 }
3395
3396 if (roam_pmkid_req_ev->vdev_id >= WLAN_MAX_VDEVS) {
3397 wmi_err_rl("Invalid vdev_id %d", roam_pmkid_req_ev->vdev_id);
3398 return QDF_STATUS_E_INVAL;
3399 }
3400
3401 num_entries = param_buf->num_pmkid_request;
3402 if (num_entries > MAX_RSSI_AVOID_BSSID_LIST) {
3403 wmi_err("num bssid entries:%d exceeds maximum value",
3404 num_entries);
3405 return QDF_STATUS_E_INVAL;
3406 }
3407
3408 src_list = param_buf->pmkid_request;
3409 if (len < (sizeof(*roam_pmkid_req_ev) +
3410 (num_entries * sizeof(*src_list)))) {
3411 wmi_err("Invalid length: %d", len);
3412 return QDF_STATUS_E_INVAL;
3413 }
3414
3415 dst_list = qdf_mem_malloc(sizeof(struct roam_pmkid_req_event) +
3416 (sizeof(struct qdf_mac_addr) * num_entries));
3417 if (!dst_list)
3418 return QDF_STATUS_E_NOMEM;
3419
3420 dst_list->vdev_id = roam_pmkid_req_ev->vdev_id;
3421
3422 for (i = 0; i < num_entries; i++) {
3423 roam_bsslist = &dst_list->ap_bssid[i];
3424 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_list->bssid,
3425 roam_bsslist->bytes);
3426 if (qdf_is_macaddr_zero(roam_bsslist) ||
3427 qdf_is_macaddr_broadcast(roam_bsslist) ||
3428 qdf_is_macaddr_group(roam_bsslist)) {
3429 wmi_err("Invalid bssid");
3430 qdf_mem_free(dst_list);
3431 return QDF_STATUS_E_INVAL;
3432 }
3433 wmi_debug("Received pmkid fallback for bssid: " QDF_MAC_ADDR_FMT" vdev_id:%d",
3434 QDF_MAC_ADDR_REF(roam_bsslist->bytes),
3435 roam_pmkid_req_ev->vdev_id);
3436 src_list++;
3437 }
3438 dst_list->num_entries = num_entries;
3439 *list = dst_list;
3440
3441 return QDF_STATUS_SUCCESS;
3442 }
3443
3444 static QDF_STATUS
extract_roam_candidate_frame_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint32_t len,struct roam_scan_candidate_frame * data)3445 extract_roam_candidate_frame_tlv(wmi_unified_t wmi_handle, uint8_t *event,
3446 uint32_t len,
3447 struct roam_scan_candidate_frame *data)
3448 {
3449 WMI_ROAM_FRAME_EVENTID_param_tlvs *param_buf = NULL;
3450 wmi_roam_frame_event_fixed_param *frame_params = NULL;
3451
3452 if (!event || !len) {
3453 wmi_debug("Empty roam candidate frame event");
3454 return QDF_STATUS_E_FAILURE;
3455 }
3456
3457 param_buf = (WMI_ROAM_FRAME_EVENTID_param_tlvs *)event;
3458 if (!param_buf) {
3459 wmi_err("received null buf from target");
3460 return -EINVAL;
3461 }
3462
3463 frame_params =
3464 (wmi_roam_frame_event_fixed_param *)param_buf->fixed_param;
3465
3466 if (frame_params->vdev_id >= WLAN_MAX_VDEVS) {
3467 wmi_debug("Invalid VDEV id %d", frame_params->vdev_id);
3468 return QDF_STATUS_E_FAILURE;
3469 }
3470
3471 if (frame_params->frame_length > param_buf->num_frame) {
3472 wmi_debug("Invalid frame length %d expected : %d",
3473 frame_params->frame_length,
3474 param_buf->num_frame);
3475 return QDF_STATUS_E_FAILURE;
3476 }
3477
3478 if (!param_buf->frame) {
3479 wmi_debug("Frame pointer is Null");
3480 return QDF_STATUS_E_FAILURE;
3481 }
3482
3483 data->vdev_id = frame_params->vdev_id;
3484 data->frame_length = frame_params->frame_length;
3485 data->frame = (uint8_t *)param_buf->frame;
3486 data->roam_offload_candidate_frm = true;
3487 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
3488 data->frame, data->frame_length);
3489
3490 return QDF_STATUS_SUCCESS;
3491 }
3492
3493 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
3494 static QDF_STATUS
extract_peer_oper_mode_event_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint32_t len,struct peer_oper_mode_event * data)3495 extract_peer_oper_mode_event_tlv(wmi_unified_t wmi_handle, uint8_t *event,
3496 uint32_t len,
3497 struct peer_oper_mode_event *data)
3498 {
3499 WMI_PEER_OPER_MODE_CHANGE_EVENTID_param_tlvs *param_buf = NULL;
3500 wmi_peer_oper_mode_change_event_fixed_param *params = NULL;
3501
3502 if (!event || !len) {
3503 wmi_debug("Empty operating mode change event");
3504 return QDF_STATUS_E_FAILURE;
3505 }
3506
3507 param_buf = (WMI_PEER_OPER_MODE_CHANGE_EVENTID_param_tlvs *)event;
3508 if (!param_buf) {
3509 wmi_err("Received null buf from target");
3510 return -EINVAL;
3511 }
3512
3513 params =
3514 (wmi_peer_oper_mode_change_event_fixed_param *)param_buf->fixed_param;
3515
3516 WMI_MAC_ADDR_TO_CHAR_ARRAY(¶ms->peer_mac_address,
3517 data->peer_mac_address.bytes);
3518 data->ind_type = params->ind_type;
3519 data->new_rxnss = params->new_rxnss;
3520 data->new_bw = params->new_bw;
3521 data->new_txnss = params->new_txnss;
3522 data->new_disablemu = params->new_disablemu;
3523
3524 wmi_debug("peer_mac_addr: " QDF_MAC_ADDR_FMT " ind_type: %d new_rxnss: %d new_bw: %d new_txnss: %d new_disablemu: %d",
3525 QDF_MAC_ADDR_REF(data->peer_mac_address.bytes),
3526 data->ind_type,
3527 data->new_rxnss,
3528 data->new_bw,
3529 data->new_txnss,
3530 data->new_disablemu);
3531
3532 return QDF_STATUS_SUCCESS;
3533 }
3534 #endif
3535 #ifdef WLAN_VENDOR_HANDOFF_CONTROL
3536 /**
3537 * convert_roam_vendor_control_param() - Function to convert
3538 * vendor_control_roam_param enum to TLV specific
3539 * WMI_ROAM_GET_VENDOR_CONTROL_PARAM_ID
3540 * @param_id: Roam vendor control param id
3541 *
3542 * Return: wmi roam vendor control param id
3543 */
3544 static WMI_ROAM_GET_VENDOR_CONTROL_PARAM_ID
convert_roam_vendor_control_param(enum vendor_control_roam_param param_id)3545 convert_roam_vendor_control_param(enum vendor_control_roam_param param_id)
3546 {
3547 switch (param_id) {
3548 case VENDOR_CONTROL_PARAM_ROAM_TRIGGER:
3549 return ROAM_VENDOR_CONTROL_PARAM_TRIGGER;
3550 case VENDOR_CONTROL_PARAM_ROAM_DELTA:
3551 return ROAM_VENDOR_CONTROL_PARAM_DELTA;
3552 case VENDOR_CONTROL_PARAM_ROAM_FULL_SCANPERIOD:
3553 return ROAM_VENDOR_CONTROL_PARAM_FULL_SCANPERIOD;
3554 case VENDOR_CONTROL_PARAM_ROAM_PARTIAL_SCANPERIOD:
3555 return ROAM_VENDOR_CONTROL_PARAM_PARTIAL_SCANPERIOD;
3556 case VENDOR_CONTROL_PARAM_ROAM_ACTIVE_CH_DWELLTIME:
3557 return ROAM_VENDOR_CONTROL_PARAM_ACTIVE_CH_DWELLTIME;
3558 case VENDOR_CONTROL_PARAM_ROAM_PASSIVE_CH_DWELLTIME:
3559 return ROAM_VENDOR_CONTROL_PARAM_PASSIVE_CH_DWELLTIME;
3560 case VENDOR_CONTROL_PARAM_ROAM_HOME_CH_TIME:
3561 return ROAM_VENDOR_CONTROL_PARAM_HOME_CH_TIME;
3562 case VENDOR_CONTROL_PARAM_ROAM_AWAY_TIME:
3563 return ROAM_VENDOR_CONTROL_PARAM_AWAY_TIME;
3564 case VENDOR_CONTROL_PARAM_ROAM_ALL:
3565 return ROAM_VENDOR_CONTROL_PARAM_ALL;
3566 default:
3567 wmi_debug("Invalid param id");
3568 return 0;
3569 }
3570 }
3571
3572 /**
3573 * convert_wmi_roam_vendor_control_param() - Function to convert TLV specific
3574 * WMI_ROAM_GET_VENDOR_CONTROL_PARAM_ID to vendor_control_roam_param
3575 * @param_id: wmi vendor control param id
3576 *
3577 * Return: roam vendor control param id
3578 */
convert_wmi_roam_vendor_control_param(WMI_ROAM_GET_VENDOR_CONTROL_PARAM_ID param_id)3579 static enum vendor_control_roam_param convert_wmi_roam_vendor_control_param(
3580 WMI_ROAM_GET_VENDOR_CONTROL_PARAM_ID param_id)
3581 {
3582 switch (param_id) {
3583 case ROAM_VENDOR_CONTROL_PARAM_TRIGGER:
3584 return VENDOR_CONTROL_PARAM_ROAM_TRIGGER;
3585 case ROAM_VENDOR_CONTROL_PARAM_DELTA:
3586 return VENDOR_CONTROL_PARAM_ROAM_DELTA;
3587 case ROAM_VENDOR_CONTROL_PARAM_FULL_SCANPERIOD:
3588 return VENDOR_CONTROL_PARAM_ROAM_FULL_SCANPERIOD;
3589 case ROAM_VENDOR_CONTROL_PARAM_PARTIAL_SCANPERIOD:
3590 return VENDOR_CONTROL_PARAM_ROAM_PARTIAL_SCANPERIOD;
3591 case ROAM_VENDOR_CONTROL_PARAM_ACTIVE_CH_DWELLTIME:
3592 return VENDOR_CONTROL_PARAM_ROAM_ACTIVE_CH_DWELLTIME;
3593 case ROAM_VENDOR_CONTROL_PARAM_PASSIVE_CH_DWELLTIME:
3594 return VENDOR_CONTROL_PARAM_ROAM_PASSIVE_CH_DWELLTIME;
3595 case ROAM_VENDOR_CONTROL_PARAM_HOME_CH_TIME:
3596 return VENDOR_CONTROL_PARAM_ROAM_HOME_CH_TIME;
3597 case ROAM_VENDOR_CONTROL_PARAM_AWAY_TIME:
3598 return VENDOR_CONTROL_PARAM_ROAM_AWAY_TIME;
3599 case ROAM_VENDOR_CONTROL_PARAM_ALL:
3600 return VENDOR_CONTROL_PARAM_ROAM_ALL;
3601 default:
3602 wmi_debug("Invalid param id");
3603 return 0;
3604 }
3605 }
3606
3607 static QDF_STATUS
extract_roam_vendor_control_param_event_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint32_t len,struct roam_vendor_handoff_params ** list)3608 extract_roam_vendor_control_param_event_tlv(wmi_unified_t wmi_handle,
3609 uint8_t *event, uint32_t len,
3610 struct roam_vendor_handoff_params **list)
3611 {
3612 WMI_ROAM_GET_VENDOR_CONTROL_PARAM_EVENTID_param_tlvs *param_buf = NULL;
3613 wmi_roam_get_vendor_control_param_event_fixed_param *fixed_param = NULL;
3614 uint32_t num_entries, i;
3615 wmi_vendor_control_param *src_list;
3616 struct roam_vendor_handoff_params *dst_list;
3617 struct roam_param_info *param_info;
3618
3619 if (!event || !len) {
3620 wmi_debug("Empty roam vendor control param event");
3621 return QDF_STATUS_E_FAILURE;
3622 }
3623
3624 param_buf =
3625 (WMI_ROAM_GET_VENDOR_CONTROL_PARAM_EVENTID_param_tlvs *)event;
3626 if (!param_buf) {
3627 wmi_err("received null buf from target");
3628 return QDF_STATUS_E_INVAL;
3629 }
3630
3631 fixed_param = (wmi_roam_get_vendor_control_param_event_fixed_param *)
3632 param_buf->fixed_param;
3633 if (!fixed_param) {
3634 wmi_err("received null event data from target");
3635 return QDF_STATUS_E_INVAL;
3636 }
3637
3638 if (fixed_param->vdev_id >= WLAN_MAX_VDEVS) {
3639 wmi_debug("Invalid VDEV id %d", fixed_param->vdev_id);
3640 return QDF_STATUS_E_FAILURE;
3641 }
3642
3643 num_entries = param_buf->num_vendor_control_param;
3644 src_list = param_buf->vendor_control_param;
3645
3646 if (len < (sizeof(*fixed_param) + (num_entries * sizeof(*src_list)))) {
3647 wmi_err("Invalid length: %d", len);
3648 return QDF_STATUS_E_FAILURE;
3649 }
3650
3651 dst_list = qdf_mem_malloc(sizeof(struct roam_vendor_handoff_params));
3652 if (!dst_list)
3653 return QDF_STATUS_E_FAILURE;
3654
3655 dst_list->vdev_id = fixed_param->vdev_id;
3656 wmi_debug("vdev_id:%d, num_tlv:%d", dst_list->vdev_id, num_entries);
3657
3658 param_info = &dst_list->param_info[0];
3659 for (i = 0; i < num_entries; i++) {
3660 param_info->param_id =
3661 convert_wmi_roam_vendor_control_param(src_list->param_id);
3662 param_info->param_value = src_list->param_value;
3663 wmi_debug("param_info->param_id:%d, param_info->param_value:%d",
3664 param_info->param_id, param_info->param_value);
3665 param_info++;
3666 src_list++;
3667 }
3668
3669 dst_list->num_entries = num_entries;
3670 *list = dst_list;
3671
3672 return QDF_STATUS_SUCCESS;
3673 }
3674
3675 /**
3676 * send_process_roam_vendor_handoff_req_cmd_tlv() - Send vendor handoff command
3677 * to fw.
3678 * @wmi_handle: wmi handle
3679 * @vdev_id: vdev id
3680 * @param_id: parameter ID to set
3681 *
3682 * Return: QDF STATUS
3683 */
3684 static QDF_STATUS
send_process_roam_vendor_handoff_req_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,uint32_t param_id)3685 send_process_roam_vendor_handoff_req_cmd_tlv(wmi_unified_t wmi_handle,
3686 uint8_t vdev_id,
3687 uint32_t param_id)
3688 {
3689 wmi_roam_get_vendor_control_param_cmd_fixed_param *cmd;
3690 wmi_buf_t wmi_buf;
3691 uint8_t *buf_ptr;
3692 uint16_t len;
3693
3694 len = sizeof(wmi_roam_get_vendor_control_param_cmd_fixed_param);
3695
3696 wmi_buf = wmi_buf_alloc(wmi_handle, len);
3697 if (!wmi_buf)
3698 return QDF_STATUS_E_NOMEM;
3699
3700 cmd = (wmi_roam_get_vendor_control_param_cmd_fixed_param *)wmi_buf_data(
3701 wmi_buf);
3702 buf_ptr = (uint8_t *)cmd;
3703 WMITLV_SET_HDR(&cmd->tlv_header,
3704 WMITLV_TAG_STRUC_wmi_roam_get_vendor_control_param_cmd_fixed_param,
3705 WMITLV_GET_STRUCT_TLVLEN
3706 (wmi_roam_get_vendor_control_param_cmd_fixed_param));
3707 cmd->vdev_id = vdev_id;
3708 cmd->param_id = convert_roam_vendor_control_param(param_id);
3709 wmi_debug("Send GET_VENDOR_CONTROL_PARAM cmd vdev_id:%d, param_id:0x%x",
3710 cmd->vdev_id, cmd->param_id);
3711 wmi_mtrace(WMI_ROAM_GET_VENDOR_CONTROL_PARAM_CMDID, cmd->vdev_id, 0);
3712 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
3713 WMI_ROAM_GET_VENDOR_CONTROL_PARAM_CMDID)) {
3714 wmi_err("Failed to send get vendor control param command");
3715 wmi_buf_free(wmi_buf);
3716 return QDF_STATUS_E_FAILURE;
3717 }
3718
3719 return QDF_STATUS_SUCCESS;
3720 }
3721
3722 /**
3723 * wmi_roam_offload_attach_vendor_handoff_tlv() - register wmi ops for vendor
3724 * handoff related command and event
3725 * @ops: wmi ops
3726 *
3727 * Return: none
3728 */
3729 static inline void
wmi_roam_offload_attach_vendor_handoff_tlv(struct wmi_ops * ops)3730 wmi_roam_offload_attach_vendor_handoff_tlv(struct wmi_ops *ops)
3731 {
3732 ops->extract_roam_vendor_control_param_event =
3733 extract_roam_vendor_control_param_event_tlv;
3734 ops->send_process_roam_vendor_handoff_req_cmd =
3735 send_process_roam_vendor_handoff_req_cmd_tlv;
3736 }
3737 #else
3738 static inline void
wmi_roam_offload_attach_vendor_handoff_tlv(struct wmi_ops * ops)3739 wmi_roam_offload_attach_vendor_handoff_tlv(struct wmi_ops *ops)
3740 {
3741 }
3742 #endif
3743
3744 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(WLAN_FEATURE_11BE_MLO)
3745 static inline
wlan_wmi_cipher_to_crypto(uint8_t cipher)3746 enum wlan_crypto_cipher_type wlan_wmi_cipher_to_crypto(uint8_t cipher)
3747 {
3748 switch (cipher) {
3749 case WMI_CIPHER_NONE:
3750 return WLAN_CRYPTO_CIPHER_NONE;
3751 case WMI_CIPHER_WEP:
3752 return WLAN_CRYPTO_CIPHER_WEP;
3753 case WMI_CIPHER_TKIP:
3754 return WLAN_CRYPTO_CIPHER_TKIP;
3755 case WMI_CIPHER_AES_OCB:
3756 return WLAN_CRYPTO_CIPHER_AES_OCB;
3757 case WMI_CIPHER_AES_CCM:
3758 return WLAN_CRYPTO_CIPHER_AES_CCM;
3759 case WMI_CIPHER_WAPI:
3760 return WLAN_CRYPTO_CIPHER_WAPI_SMS4;
3761 case WMI_CIPHER_CKIP:
3762 return WLAN_CRYPTO_CIPHER_CKIP;
3763 case WMI_CIPHER_AES_CMAC:
3764 return WLAN_CRYPTO_CIPHER_AES_CMAC;
3765 case WMI_CIPHER_AES_GCM:
3766 return WLAN_CRYPTO_CIPHER_AES_GCM;
3767 case WMI_CIPHER_AES_GMAC:
3768 return WLAN_CRYPTO_CIPHER_AES_GMAC;
3769 case WMI_CIPHER_WAPI_GCM_SM4:
3770 return WLAN_CRYPTO_CIPHER_WAPI_GCM4;
3771 case WMI_CIPHER_BIP_CMAC_128:
3772 return WLAN_CRYPTO_CIPHER_AES_CMAC;
3773 case WMI_CIPHER_BIP_CMAC_256:
3774 return WLAN_CRYPTO_CIPHER_AES_CMAC_256;
3775 case WMI_CIPHER_BIP_GMAC_128:
3776 return WLAN_CRYPTO_CIPHER_AES_GMAC;
3777 case WMI_CIPHER_BIP_GMAC_256:
3778 return WLAN_CRYPTO_CIPHER_AES_GMAC_256;
3779
3780 default:
3781 return 0;
3782 }
3783 }
3784 #define MLO_PAIRWISE_LINKID 0xF
3785 /**
3786 * wmi_fill_keys_from_tlv - Fill the destination key buffer from the WMI TLV
3787 * @ml_keys: ML Keys TLV pointer
3788 * @dst_key: Destination keys
3789 * @dst_key_len: Destination keys length
3790 * @count: TLV count
3791 * @max_num_tlv: Total number of TLVs
3792 *
3793 * Return: None
3794 */
3795 static void
wmi_fill_keys_from_tlv(wmi_roam_ml_key_material_param ** ml_keys,uint8_t * dst_key,uint8_t * dst_key_len,uint8_t * count,uint8_t max_num_tlv)3796 wmi_fill_keys_from_tlv(wmi_roam_ml_key_material_param **ml_keys,
3797 uint8_t *dst_key, uint8_t *dst_key_len, uint8_t *count,
3798 uint8_t max_num_tlv)
3799 {
3800 uint8_t rem_key_len, bytes_filled, key_len, total_key_len;
3801 uint8_t max_key_len = WLAN_CRYPTO_KEYBUF_SIZE + WLAN_CRYPTO_MICBUF_SIZE;
3802
3803 *dst_key_len = (*ml_keys)->key_len;
3804 if (*dst_key_len > max_key_len)
3805 *dst_key_len = max_key_len;
3806
3807 total_key_len = *dst_key_len;
3808 rem_key_len = *dst_key_len;
3809
3810 while (rem_key_len) {
3811 if (!(*ml_keys)) {
3812 wmi_err_rl("ml_keys is NULL. rem_key_len:%d",
3813 rem_key_len);
3814 return;
3815 }
3816
3817 if (*count >= max_num_tlv) {
3818 wmi_debug("Read all TLVs count:%d", *count);
3819 return;
3820 }
3821
3822 if (rem_key_len < WMI_MAX_KEY_LEN)
3823 key_len = rem_key_len;
3824 else
3825 key_len = WMI_MAX_KEY_LEN;
3826
3827 bytes_filled = total_key_len - rem_key_len;
3828 qdf_mem_copy(dst_key + bytes_filled, (*ml_keys)->key_buff,
3829 key_len);
3830 (*ml_keys)++;
3831 (*count)++;
3832
3833 rem_key_len -= key_len;
3834 }
3835 }
3836
3837 #define WMI_NUM_KEYS_ALLOCATED (WLAN_MAX_ML_BSS_LINKS * 4)
3838 static QDF_STATUS
extract_roam_synch_key_event_tlv(wmi_unified_t wmi_handle,uint8_t * event,uint32_t data_len,struct wlan_crypto_key_entry ** entries,uint8_t * num_entries,struct qdf_mac_addr * mld_addr)3839 extract_roam_synch_key_event_tlv(wmi_unified_t wmi_handle,
3840 uint8_t *event, uint32_t data_len,
3841 struct wlan_crypto_key_entry **entries,
3842 uint8_t *num_entries,
3843 struct qdf_mac_addr *mld_addr)
3844 {
3845 WMI_ROAM_SYNCH_KEY_EVENTID_param_tlvs *param_buf = NULL;
3846 wmi_roam_ml_key_material_param *ml_keys = NULL;
3847 struct wlan_crypto_key_entry *key_entry;
3848 struct wlan_crypto_keys *all_keys;
3849 struct wlan_crypto_key *dst_key, *pairwise;
3850 struct wlan_crypto_key *key_alloc_buf[WMI_NUM_KEYS_ALLOCATED];
3851 bool flush_keybuf;
3852 uint8_t total_num_tlv, j = 0, k = 0;
3853 uint8_t count = 0, total_links = 0, dst_key_count = 0;
3854 uint8_t igtk_idx = 0, bigtk_idx = 0;
3855 bool slot_found;
3856 QDF_STATUS status = QDF_STATUS_SUCCESS;
3857
3858 param_buf = (WMI_ROAM_SYNCH_KEY_EVENTID_param_tlvs *)event;
3859 if (!param_buf) {
3860 wmi_err_rl("received null buf from target");
3861 return QDF_STATUS_E_INVAL;
3862 }
3863
3864 total_num_tlv = param_buf->num_ml_key_material;
3865 ml_keys = (wmi_roam_ml_key_material_param *)param_buf->ml_key_material;
3866 if (!ml_keys) {
3867 wmi_err_rl("received ml keys param is null");
3868 return QDF_STATUS_E_INVAL;
3869 }
3870
3871 *entries = qdf_mem_malloc(WLAN_MAX_ML_BSS_LINKS * sizeof(*key_entry));
3872 if (!*entries)
3873 return QDF_STATUS_E_NOMEM;
3874
3875 /*
3876 * Allocate memory for each PTK, GTK, IGTK, BIGTK keys.
3877 * So total WLAN_MAX_ML_BSS_LINKS * 4 keys are needed
3878 */
3879 for (k = 0; k < WMI_NUM_KEYS_ALLOCATED; k++) {
3880 key_alloc_buf[k] = qdf_mem_malloc(sizeof(*dst_key));
3881 if (!key_alloc_buf[k]) {
3882 flush_keybuf = true;
3883 status = QDF_STATUS_E_NOMEM;
3884 goto free_entries;
3885 }
3886 }
3887
3888 /*
3889 * key_entry is the master structure that is given directly to the
3890 * crypto module and stored for each link.
3891 * key_entry -> keys ->key filled from dst_key has the PTK & GTK indexed
3892 * with corresponding key index
3893 *
3894 * key_entry -> keys -> iGTK holds the iGTK key
3895 * key_entry -> keys -> BIGTK holds the BIGTK key
3896 */
3897 key_entry = *entries;
3898
3899 /*
3900 * Initialize all the Key Entry structures with invalid Link
3901 * ID to identify empty links allocated and will be freed
3902 * at the end.
3903 */
3904 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++)
3905 key_entry[j].link_id = MLO_INVALID_LINK_IDX;
3906
3907 /*
3908 * TLV Format to parse:
3909 * 1. wmi_roam_ml_key_material_param -> For PTK with Link ID = 0xF
3910 * Copy this PTK to all the key entry of all the links.
3911 *
3912 * 2. wmi_roam_ml_key_material_param -> GTK for a valid Link.
3913 * Get available entry, and fill the GTK to that entry
3914 *
3915 * 3. wmi_roam_ml_key_material_param -> IGTK for a valid link
3916 *
3917 * 4. wmi_roam_ml_key_material_param -> BIGTK for a valid link
3918 *
3919 * 5. wmi_roam_ml_key_material_param -> For LTF Keyseed with Link ID =
3920 * 0xF and flags has LTF_USAGE set.
3921 *
3922 * If any of the key length is > WMI_MAX_KEY_LEN, then multiple
3923 * wmi_roam_ml_key_material_param TLVs follow to get the entire key
3924 */
3925 while (ml_keys && count < total_num_tlv &&
3926 dst_key_count < WMI_NUM_KEYS_ALLOCATED) {
3927 /*
3928 * Track individual keys with key_alloc_buf[dst_key_count] array
3929 * pointer to avoid mem leaks if parsing/validating any of the
3930 * keys fail.
3931 * Freeing the allocated keys it done at the end of this
3932 * function
3933 */
3934 dst_key = key_alloc_buf[dst_key_count];
3935 wmi_debug("link_id:%d key_ix:%d key_cipher:%d key_len:%d key_flags:%d",
3936 ml_keys->link_id, ml_keys->key_ix,
3937 ml_keys->key_cipher,
3938 ml_keys->key_len, ml_keys->key_flags);
3939
3940 if (!is_valid_keyix(ml_keys->key_ix)) {
3941 wmi_err_rl("invalid key index:%d", ml_keys->key_ix);
3942 status = QDF_STATUS_E_INVAL;
3943 flush_keybuf = true;
3944 goto free_entries;
3945 }
3946
3947 /* Copy pairwise keys to all the entries */
3948 if (ml_keys->link_id == MLO_PAIRWISE_LINKID) {
3949 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ml_keys->mac_addr,
3950 mld_addr->bytes);
3951 if (!ml_keys->key_len) {
3952 wmi_err_rl("Received key_len as 0 for tlv:%d",
3953 count);
3954 status = QDF_STATUS_E_INVAL;
3955 flush_keybuf = true;
3956 goto free_entries;
3957 }
3958
3959 if (ml_keys->key_flags & LTF_USAGE) {
3960 struct wlan_crypto_ltf_keyseed_data key_seed;
3961 uint8_t key_seed_len;
3962
3963 if (ml_keys->key_len >
3964 WLAN_MAX_SECURE_LTF_KEYSEED_LEN)
3965 ml_keys->key_len =
3966 WLAN_MAX_SECURE_LTF_KEYSEED_LEN;
3967
3968 /*
3969 * Filling the keys from multiple TLVs is
3970 * handled by below API and ml_keys ptr gets
3971 * incremented accordingly inside
3972 */
3973 wmi_fill_keys_from_tlv(&ml_keys,
3974 key_seed.key_seed,
3975 &key_seed_len, &count,
3976 total_num_tlv);
3977 key_seed.key_seed_len = key_seed_len;
3978 wmi_debug("ML_KEY: Got LTF keyseed key for MLD: "
3979 QDF_MAC_ADDR_FMT " key_seed_len:%d",
3980 QDF_MAC_ADDR_REF(mld_addr->bytes),
3981 key_seed.key_seed_len);
3982
3983 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++)
3984 key_entry[j].keys.ltf_key_seed =
3985 key_seed;
3986
3987 continue;
3988 }
3989
3990 dst_key->valid = true;
3991 dst_key->keylen = ml_keys->key_len;
3992 dst_key->flags = ml_keys->key_flags;
3993 dst_key->keyix = ml_keys->key_ix;
3994 dst_key->key_type =
3995 WLAN_CRYPTO_KEY_TYPE_UNICAST;
3996 dst_key->cipher_type =
3997 wlan_wmi_cipher_to_crypto(ml_keys->key_cipher);
3998 dst_key->keylen = ml_keys->key_len;
3999
4000 wmi_fill_keys_from_tlv(&ml_keys, dst_key->keyval,
4001 &dst_key->keylen, &count,
4002 total_num_tlv);
4003 wmi_err_rl("ML_KEY: Got Pairwise key for MLD: "
4004 QDF_MAC_ADDR_FMT " rem_len:%d",
4005 QDF_MAC_ADDR_REF(mld_addr->bytes),
4006 dst_key->keylen);
4007
4008 pairwise = dst_key;
4009 /*
4010 * Pairwise keys will be sent only once. Copy that for
4011 * all the link entries
4012 */
4013 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++) {
4014 dst_key = key_alloc_buf[dst_key_count];
4015 *dst_key = *pairwise;
4016 key_entry[j].keys.key[dst_key->keyix] = dst_key;
4017 dst_key_count++;
4018 }
4019
4020 continue;
4021 }
4022
4023 slot_found = false;
4024 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++) {
4025 if (ml_keys->link_id == MLO_INVALID_LINK_IDX)
4026 break;
4027
4028 if (key_entry[j].link_id == MLO_INVALID_LINK_IDX ||
4029 key_entry[j].link_id == ml_keys->link_id) {
4030 slot_found = true;
4031 break;
4032 }
4033 }
4034
4035 if (!slot_found) {
4036 wmi_err_rl("Not able to find a entry for link:%d j=%d",
4037 ml_keys->link_id, j);
4038 break;
4039 }
4040
4041 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ml_keys->mac_addr,
4042 dst_key->macaddr);
4043 key_entry[j].link_id = ml_keys->link_id;
4044 qdf_copy_macaddr((struct qdf_mac_addr *)key_entry[j].mac_addr.raw,
4045 (struct qdf_mac_addr *)dst_key->macaddr);
4046 all_keys = &key_entry[j].keys;
4047
4048 dst_key->valid = true;
4049 dst_key->keyix = ml_keys->key_ix;
4050 dst_key->cipher_type =
4051 wlan_wmi_cipher_to_crypto(ml_keys->key_cipher);
4052
4053 qdf_mem_copy(dst_key->keyrsc, ml_keys->pn, WMI_MAX_PN_LEN);
4054
4055 /*
4056 * For LTF keyseed or FILS SHA 384, FILS SHA 512 cases, the key
4057 * size will go beyond WMI_MAX_KEY_LEN(32). So extract first 32
4058 * bytes from 1st TLV and extract the rest of the bytes from
4059 * the following TLVs
4060 */
4061 dst_key->keylen = ml_keys->key_len;
4062 wmi_fill_keys_from_tlv(&ml_keys, dst_key->keyval,
4063 &dst_key->keylen, &count, total_num_tlv);
4064
4065 if (is_igtk(dst_key->keyix)) {
4066 dst_key->key_type = WLAN_CRYPTO_KEY_TYPE_GROUP;
4067
4068 igtk_idx = dst_key->keyix - WLAN_CRYPTO_MAXKEYIDX;
4069 bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX;
4070
4071 wmi_debug("ML_KEY: Slot:%d link_id:%d addr: " QDF_MAC_ADDR_FMT "Key is IGTK key_ix:%d igtk_idx:%d bigtk:%d",
4072 j, key_entry[j].link_id,
4073 QDF_MAC_ADDR_REF(dst_key->macaddr),
4074 dst_key->keyix, igtk_idx, bigtk_idx);
4075 all_keys->igtk_key[igtk_idx] = dst_key;
4076 all_keys->def_igtk_tx_keyid = igtk_idx;
4077
4078 bigtk_idx = 0;
4079 igtk_idx = 0;
4080 } else if (is_bigtk(dst_key->keyix)) {
4081 dst_key->key_type = WLAN_CRYPTO_KEY_TYPE_GROUP;
4082
4083 igtk_idx = dst_key->keyix - WLAN_CRYPTO_MAXKEYIDX;
4084 bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX;
4085
4086 wmi_debug("ML_KEY: Slot:%d link_id:%d addr: " QDF_MAC_ADDR_FMT "Key is BIGTK key_ix:%d igtk_idx:%d bigtk:%d",
4087 j, key_entry[j].link_id,
4088 QDF_MAC_ADDR_REF(dst_key->macaddr),
4089 dst_key->keyix, igtk_idx, bigtk_idx);
4090 all_keys->bigtk_key[bigtk_idx] = dst_key;
4091 all_keys->def_bigtk_tx_keyid = bigtk_idx;
4092
4093 bigtk_idx = 0;
4094 igtk_idx = 0;
4095 } else if (is_gtk(dst_key->keyix)) {
4096 wmi_debug("ML_KEY: Slot:%d link_id:%d addr: " QDF_MAC_ADDR_FMT " Key is GTK key_ix:%d",
4097 j, key_entry[j].link_id,
4098 QDF_MAC_ADDR_REF(dst_key->macaddr),
4099 dst_key->keyix);
4100 dst_key->key_type = WLAN_CRYPTO_KEY_TYPE_GROUP;
4101 all_keys->key[dst_key->keyix] = dst_key;
4102 } else {
4103 wmi_debug("Key is Pairwise. Shouldn't reach here");
4104 /* Pairwise key */
4105 dst_key->key_type = WLAN_CRYPTO_KEY_TYPE_UNICAST;
4106 all_keys->key[dst_key->keyix] = dst_key;
4107 }
4108
4109 dst_key_count++;
4110 }
4111
4112 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++) {
4113 /*
4114 * Pairwise keys maybe copied for all the WLAN_MAX_ML_BSS_LINKS
4115 * but firmware might have roamed to AP with number of links
4116 * less than WLAN_MAX_ML_BSS_LINKS. So free the memory for those
4117 * links
4118 */
4119 if (key_entry[j].link_id != MLO_INVALID_LINK_IDX) {
4120 total_links++;
4121 } else {
4122 wmi_err_rl("Free keys for invalid entry at index:%d",
4123 j);
4124 wlan_crypto_free_key(&key_entry[j].keys);
4125 }
4126 }
4127
4128 *num_entries = total_links;
4129 /* Free the invalid dst_keys allocated */
4130 if (!*num_entries)
4131 goto free_entries;
4132
4133 /*
4134 * This is to free the unfilled key_alloc_buf that
4135 * was allocated initially
4136 */
4137 flush_keybuf = false;
4138
4139 wmi_err_rl("ML_KEYS: total_entries filled:%d total_num_tlv:%d dst_key_count:%d",
4140 *num_entries, total_num_tlv, dst_key_count);
4141 goto free_keys;
4142
4143 free_entries:
4144 qdf_mem_zero(*entries,
4145 WLAN_MAX_ML_BSS_LINKS * sizeof(**entries));
4146 qdf_mem_free(*entries);
4147
4148 free_keys:
4149 for (k = 0; k < WMI_NUM_KEYS_ALLOCATED; k++) {
4150 if (!key_alloc_buf[k])
4151 continue;
4152
4153 wmi_err_rl("flush keybuf :%d, key is valid", flush_keybuf,
4154 key_alloc_buf[k]->valid);
4155 if (!flush_keybuf && key_alloc_buf[k]->valid)
4156 continue;
4157
4158 wmi_err("Free key allocated at idx:%d", k);
4159 qdf_mem_zero(key_alloc_buf[k], sizeof(*key_alloc_buf[k]));
4160 qdf_mem_free(key_alloc_buf[k]);
4161 }
4162
4163 return status;
4164 }
4165
4166 static void
wmi_roam_offload_attach_mlo_tlv(struct wmi_ops * ops)4167 wmi_roam_offload_attach_mlo_tlv(struct wmi_ops *ops)
4168 {
4169 ops->extract_roam_synch_key_event = extract_roam_synch_key_event_tlv;
4170 }
4171 #else
4172 static inline void
wmi_roam_offload_attach_mlo_tlv(struct wmi_ops * ops)4173 wmi_roam_offload_attach_mlo_tlv(struct wmi_ops *ops)
4174 {}
4175 #endif
4176
wmi_roam_offload_attach_tlv(wmi_unified_t wmi_handle)4177 void wmi_roam_offload_attach_tlv(wmi_unified_t wmi_handle)
4178 {
4179 struct wmi_ops *ops = wmi_handle->ops;
4180
4181 ops->extract_roam_btm_response_stats =
4182 extract_roam_btm_response_stats_tlv;
4183 ops->extract_roam_initial_info = extract_roam_initial_info_tlv;
4184 ops->extract_roam_msg_info = extract_roam_msg_info_tlv;
4185 ops->extract_roam_frame_info = extract_roam_frame_info_tlv;
4186 ops->extract_roam_sync_event = extract_roam_sync_event_tlv;
4187 ops->extract_roam_sync_frame_event = extract_roam_sync_frame_event_tlv;
4188 ops->extract_roam_event = extract_roam_event_tlv;
4189 ops->extract_btm_dl_event = extract_btm_denylist_event;
4190 ops->extract_vdev_disconnect_event = extract_vdev_disconnect_event_tlv;
4191 ops->extract_roam_scan_chan_list = extract_roam_scan_chan_list_tlv;
4192 ops->extract_roam_stats_event = extract_roam_stats_event_tlv;
4193 ops->extract_auth_offload_event = extract_auth_offload_event_tlv;
4194 ops->extract_roam_pmkid_request = extract_roam_pmkid_request_tlv;
4195 ops->send_set_ric_req_cmd = send_set_ric_req_cmd_tlv;
4196 ops->send_process_roam_synch_complete_cmd =
4197 send_process_roam_synch_complete_cmd_tlv;
4198 ops->send_roam_invoke_cmd = send_roam_invoke_cmd_tlv;
4199 ops->send_vdev_set_pcl_cmd = send_vdev_set_pcl_cmd_tlv;
4200 ops->send_set_roam_trigger_cmd = send_set_roam_trigger_cmd_tlv;
4201 ops->extract_roam_candidate_frame = extract_roam_candidate_frame_tlv;
4202 ops->extract_peer_oper_mode_event = extract_peer_oper_mode_event_tlv;
4203 wmi_roam_offload_attach_vendor_handoff_tlv(ops);
4204 wmi_roam_offload_attach_mlo_tlv(ops);
4205 }
4206 #else
4207 static inline QDF_STATUS
extract_roam_btm_response_stats_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct roam_btm_response_data * dst,uint8_t idx)4208 extract_roam_btm_response_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf,
4209 struct roam_btm_response_data *dst,
4210 uint8_t idx)
4211 {
4212 return QDF_STATUS_E_NOSUPPORT;
4213 }
4214
4215 static inline QDF_STATUS
extract_roam_initial_info_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct roam_initial_data * dst,uint8_t idx)4216 extract_roam_initial_info_tlv(wmi_unified_t wmi_handle, void *evt_buf,
4217 struct roam_initial_data *dst, uint8_t idx)
4218 {
4219 return QDF_STATUS_E_NOSUPPORT;
4220 }
4221
4222 static inline QDF_STATUS
extract_roam_msg_info_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct roam_msg_info * dst,uint8_t idx)4223 extract_roam_msg_info_tlv(wmi_unified_t wmi_handle, void *evt_buf,
4224 struct roam_msg_info *dst, uint8_t idx)
4225 {
4226 return QDF_STATUS_E_NOSUPPORT;
4227 }
4228
4229 static inline QDF_STATUS
extract_roam_sync_event(wmi_unified_t wmi_handle,void * evt_buf,uint32_t len,struct roam_offload_synch_ind ** roam_sync_ind)4230 extract_roam_sync_event(wmi_unified_t wmi_handle, void *evt_buf,
4231 uint32_t len,
4232 struct roam_offload_synch_ind **roam_sync_ind)
4233 {
4234 return QDF_STATUS_E_NOSUPPORT;
4235 }
4236
4237 static inline QDF_STATUS
extract_roam_sync_frame_event(wmi_unified_t wmi_handle,void * evt_buf,struct roam_msg_info * dst,uint8_t idx)4238 extract_roam_sync_frame_event(wmi_unified_t wmi_handle, void *evt_buf,
4239 struct roam_msg_info *dst, uint8_t idx)
4240 {
4241 return QDF_STATUS_E_NOSUPPORT;
4242 }
4243
4244 static inline QDF_STATUS
extract_roam_event(wmi_unified_t wmi_handle,void * evt_buf,uint32_t len,struct roam_offload_roam_event * roam_event)4245 extract_roam_event(wmi_unified_t wmi_handle, void *evt_buf, uint32_t len,
4246 struct roam_offload_roam_event *roam_event)
4247 {
4248 return QDF_STATUS_E_NOSUPPORT;
4249 }
4250 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
4251
4252 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
4253 /**
4254 * wmi_fill_roam_offload_11r_params() - Fill roam scan params to send it to fw
4255 * @akm: Authentication key management type
4256 * @roam_offload_11r: TLV to be filled with 11r params
4257 * @roam_req: roam request param
4258 */
wmi_fill_roam_offload_11r_params(uint32_t akm,wmi_roam_11r_offload_tlv_param * roam_offload_11r,struct wlan_roam_scan_offload_params * roam_req)4259 static void wmi_fill_roam_offload_11r_params(
4260 uint32_t akm,
4261 wmi_roam_11r_offload_tlv_param *roam_offload_11r,
4262 struct wlan_roam_scan_offload_params *roam_req)
4263 {
4264 struct wlan_rso_11r_params *src_11r_params;
4265 uint8_t *psk_msk, len;
4266
4267 src_11r_params = &roam_req->rso_11r_info;
4268
4269 if ((akm == WMI_AUTH_FT_RSNA_FILS_SHA256 ||
4270 akm == WMI_AUTH_FT_RSNA_FILS_SHA384) &&
4271 roam_req->fils_roam_config.fils_ft_len) {
4272 wmi_debug("Update the FILS FT key to Firmware");
4273 psk_msk = roam_req->fils_roam_config.fils_ft;
4274 len = roam_req->fils_roam_config.fils_ft_len;
4275 } else {
4276 psk_msk = src_11r_params->psk_pmk;
4277 len = src_11r_params->pmk_len;
4278 }
4279
4280 /*
4281 * For SHA384 based akm, the pmk length is 48 bytes. So fill
4282 * first 32 bytes in roam_offload_11r->psk_msk and the remaining
4283 * bytes in roam_offload_11r->psk_msk_ext buffer
4284 */
4285 roam_offload_11r->psk_msk_len = len > ROAM_OFFLOAD_PSK_MSK_BYTES ?
4286 ROAM_OFFLOAD_PSK_MSK_BYTES : len;
4287 qdf_mem_copy(roam_offload_11r->psk_msk, psk_msk,
4288 roam_offload_11r->psk_msk_len);
4289 roam_offload_11r->psk_msk_ext_len = 0;
4290
4291 if (len > ROAM_OFFLOAD_PSK_MSK_BYTES) {
4292 roam_offload_11r->psk_msk_ext_len =
4293 len - roam_offload_11r->psk_msk_len;
4294 qdf_mem_copy(roam_offload_11r->psk_msk_ext,
4295 &psk_msk[roam_offload_11r->psk_msk_len],
4296 roam_offload_11r->psk_msk_ext_len);
4297 }
4298 }
4299
4300 /**
4301 * wmi_is_ft_akm() - Check if the akm is FT akm. Based on the AKM 11r params
4302 * will be sent for lfr-3.0 roaming offload
4303 * @akm: AKM negotiated for the connection
4304 * @roam_req: roam request sent to firmware
4305 *
4306 * Return: true if the akm is 11r based
4307 */
wmi_is_ft_akm(int akm,struct wlan_roam_scan_offload_params * roam_req)4308 static bool wmi_is_ft_akm(int akm,
4309 struct wlan_roam_scan_offload_params *roam_req)
4310 {
4311 switch (akm) {
4312 case WMI_AUTH_FT_RSNA:
4313 case WMI_AUTH_FT_RSNA_PSK:
4314 case WMI_AUTH_FT_RSNA_SAE:
4315 case WMI_AUTH_FT_RSNA_SUITE_B_8021X_SHA384:
4316 case WMI_AUTH_FT_RSNA_FILS_SHA256:
4317 case WMI_AUTH_FT_RSNA_FILS_SHA384:
4318 case WMI_AUTH_FT_RSNA_SAE_SHA384:
4319 return true;
4320 case WMI_AUTH_OPEN:
4321 if (roam_req->rso_11r_info.mdid.mdie_present &&
4322 roam_req->rso_11r_info.is_11r_assoc)
4323 return true;
4324
4325 break;
4326 default:
4327 return false;
4328 }
4329
4330 return false;
4331 }
4332
4333 /**
4334 * wmi_get_rso_buf_len() - calculate the length needed to allocate buffer
4335 * for RSO mode command
4336 * @roam_req: roam request parameters
4337 */
4338 static uint32_t
wmi_get_rso_buf_len(struct wlan_roam_scan_offload_params * roam_req)4339 wmi_get_rso_buf_len(struct wlan_roam_scan_offload_params *roam_req)
4340 {
4341 wmi_tlv_buf_len_param *assoc_ies;
4342 uint32_t buf_len;
4343 uint32_t fils_tlv_len = 0;
4344 int akm = roam_req->akm;
4345
4346 /*
4347 * Allocate room for wmi_roam_offload_tlv_param and
4348 * 11i or 11r or ese roam offload tlv param
4349 * Todo: Test if below headroom of 2 TLV header is needed
4350 */
4351 buf_len = (2 * WMI_TLV_HDR_SIZE);
4352
4353 if (roam_req->is_rso_stop ||
4354 !roam_req->roam_offload_enabled) {
4355 buf_len += (4 * WMI_TLV_HDR_SIZE);
4356
4357 if (!roam_req->is_rso_stop)
4358 wmi_debug("vdev[%d]: %s roam offload: %d",
4359 roam_req->vdev_id,
4360 roam_req->is_rso_stop ? "RSO stop cmd." : "",
4361 roam_req->roam_offload_enabled);
4362
4363 return buf_len;
4364 }
4365
4366 wmi_debug("wmi akm = %d", akm);
4367
4368 buf_len += sizeof(wmi_roam_offload_tlv_param);
4369 buf_len += 2 * WMI_TLV_HDR_SIZE;
4370
4371 if ((akm != WMI_AUTH_OPEN || roam_req->rso_ese_info.is_ese_assoc ||
4372 wmi_is_ft_akm(akm, roam_req)) && akm != WMI_AUTH_NONE) {
4373 if (roam_req->rso_ese_info.is_ese_assoc)
4374 buf_len += sizeof(wmi_roam_ese_offload_tlv_param);
4375 else if (wmi_is_ft_akm(akm, roam_req))
4376 buf_len += sizeof(wmi_roam_11r_offload_tlv_param);
4377 else
4378 buf_len += sizeof(wmi_roam_11i_offload_tlv_param);
4379 }
4380
4381 buf_len += (sizeof(*assoc_ies) + (2 * WMI_TLV_HDR_SIZE) +
4382 roundup(roam_req->assoc_ie_length, sizeof(uint32_t)));
4383
4384 /* Fils TLV */
4385 buf_len += WMI_TLV_HDR_SIZE;
4386 if (roam_req->add_fils_tlv) {
4387 fils_tlv_len = sizeof(wmi_roam_fils_offload_tlv_param);
4388 buf_len += fils_tlv_len;
4389 }
4390
4391 if (roam_req->rso_11i_info.is_sae_same_pmk)
4392 buf_len += WMI_TLV_HDR_SIZE +
4393 sizeof(wmi_roam_sae_offload_tlv_param);
4394
4395 roam_req->rso_mode_info.roam_scan_mode |=
4396 WMI_ROAM_SCAN_MODE_ROAMOFFLOAD;
4397
4398 return buf_len;
4399 }
4400
4401 #if defined(WLAN_FEATURE_FILS_SK)
4402 /**
4403 * wmi_add_fils_tlv() - Add FILS TLV to roam scan offload command
4404 * @wmi_handle: wmi handle
4405 * @roam_req: Roam scan offload params
4406 * @buf_ptr: command buffer to send
4407 * @fils_tlv_len: fils tlv length
4408 *
4409 * Return: Updated buffer pointer
4410 */
wmi_add_fils_tlv(wmi_unified_t wmi_handle,struct wlan_roam_scan_offload_params * roam_req,uint8_t * buf_ptr,uint32_t fils_tlv_len)4411 static uint8_t *wmi_add_fils_tlv(wmi_unified_t wmi_handle,
4412 struct wlan_roam_scan_offload_params *roam_req,
4413 uint8_t *buf_ptr, uint32_t fils_tlv_len)
4414 {
4415 wmi_roam_fils_offload_tlv_param *fils_tlv;
4416 wmi_erp_info *erp_info;
4417 struct wlan_roam_fils_params *roam_fils_params;
4418
4419 if (!roam_req->add_fils_tlv) {
4420 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
4421 buf_ptr += WMI_TLV_HDR_SIZE;
4422 return buf_ptr;
4423 }
4424
4425 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
4426 sizeof(*fils_tlv));
4427 buf_ptr += WMI_TLV_HDR_SIZE;
4428
4429 fils_tlv = (wmi_roam_fils_offload_tlv_param *)buf_ptr;
4430 WMITLV_SET_HDR(&fils_tlv->tlv_header,
4431 WMITLV_TAG_STRUC_wmi_roam_fils_offload_tlv_param,
4432 WMITLV_GET_STRUCT_TLVLEN
4433 (wmi_roam_fils_offload_tlv_param));
4434
4435 roam_fils_params = &roam_req->fils_roam_config;
4436 erp_info = (wmi_erp_info *)(&fils_tlv->vdev_erp_info);
4437
4438 erp_info->username_length = roam_fils_params->username_length;
4439 qdf_mem_copy(erp_info->username, roam_fils_params->username,
4440 erp_info->username_length);
4441
4442 erp_info->next_erp_seq_num = roam_fils_params->next_erp_seq_num;
4443
4444 erp_info->rRk_length = roam_fils_params->rrk_length;
4445 qdf_mem_copy(erp_info->rRk, roam_fils_params->rrk,
4446 erp_info->rRk_length);
4447
4448 erp_info->rIk_length = roam_fils_params->rik_length;
4449 qdf_mem_copy(erp_info->rIk, roam_fils_params->rik,
4450 erp_info->rIk_length);
4451
4452 erp_info->realm_len = roam_fils_params->realm_len;
4453 qdf_mem_copy(erp_info->realm, roam_fils_params->realm,
4454 erp_info->realm_len);
4455
4456 buf_ptr += sizeof(*fils_tlv);
4457 wmi_debug("RSO_CFG: ERP: usrname_len:%d next_erp_seq_num:%d rRk_len:%d rIk_len:%d realm_len:%d",
4458 erp_info->username_length, erp_info->next_erp_seq_num,
4459 erp_info->rRk_length, erp_info->rIk_length,
4460 erp_info->realm_len);
4461 return buf_ptr;
4462 }
4463 #else
4464 static inline
wmi_add_fils_tlv(wmi_unified_t wmi_handle,struct wlan_roam_scan_offload_params * roam_req,uint8_t * buf_ptr,uint32_t fils_tlv_len)4465 uint8_t *wmi_add_fils_tlv(wmi_unified_t wmi_handle,
4466 struct wlan_roam_scan_offload_params *roam_req,
4467 uint8_t *buf_ptr, uint32_t fils_tlv_len)
4468 {
4469 return buf_ptr;
4470 }
4471 #endif
4472
4473 #ifdef WLAN_SAE_SINGLE_PMK
4474 static inline void
wmi_fill_sae_single_pmk_param(struct wlan_rso_11i_params * src_11i,wmi_roam_11i_offload_tlv_param * roam_offload_11i)4475 wmi_fill_sae_single_pmk_param(struct wlan_rso_11i_params *src_11i,
4476 wmi_roam_11i_offload_tlv_param *roam_offload_11i)
4477 {
4478 if (src_11i->is_sae_same_pmk)
4479 roam_offload_11i->flags |=
4480 1 << WMI_ROAM_OFFLOAD_FLAG_SAE_SAME_PMKID;
4481 }
4482
wmi_fill_sae_single_pmk_tlv(struct wlan_roam_scan_offload_params * roam_req,uint8_t * buf_ptr)4483 static uint8_t *wmi_fill_sae_single_pmk_tlv(
4484 struct wlan_roam_scan_offload_params *roam_req, uint8_t *buf_ptr)
4485 {
4486 wmi_roam_sae_offload_tlv_param *sae_offload_param;
4487
4488 if (!roam_req->rso_11i_info.is_sae_same_pmk)
4489 return buf_ptr;
4490
4491 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
4492 sizeof(wmi_roam_sae_offload_tlv_param));
4493 buf_ptr += WMI_TLV_HDR_SIZE;
4494
4495 sae_offload_param = (wmi_roam_sae_offload_tlv_param *)buf_ptr;
4496 WMITLV_SET_HDR(&sae_offload_param->tlv_header,
4497 WMITLV_TAG_STRUC_wmi_roam_sae_offload_tlv_param,
4498 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_sae_offload_tlv_param));
4499
4500 sae_offload_param->spmk_timeout =
4501 roam_req->sae_offload_params.spmk_timeout;
4502 wmi_debug("spmk_timeout:%d seconds", sae_offload_param->spmk_timeout);
4503
4504 buf_ptr += sizeof(*sae_offload_param);
4505
4506 return buf_ptr;
4507 }
4508 #else
4509 static inline void
wmi_fill_sae_single_pmk_param(struct wlan_rso_11i_params * src_11i,wmi_roam_11i_offload_tlv_param * roam_offload_11i)4510 wmi_fill_sae_single_pmk_param(struct wlan_rso_11i_params *src_11i,
4511 wmi_roam_11i_offload_tlv_param *roam_offload_11i)
4512 {}
4513
wmi_fill_sae_single_pmk_tlv(struct wlan_roam_scan_offload_params * roam_req,uint8_t * buf_ptr)4514 static inline uint8_t *wmi_fill_sae_single_pmk_tlv(
4515 struct wlan_roam_scan_offload_params *roam_req,
4516 uint8_t *buf_ptr)
4517 {
4518 return buf_ptr;
4519 }
4520
4521 #endif
4522
4523 static QDF_STATUS
wmi_fill_rso_tlvs(wmi_unified_t wmi_handle,uint8_t * buf,struct wlan_roam_scan_offload_params * roam_req)4524 wmi_fill_rso_tlvs(wmi_unified_t wmi_handle, uint8_t *buf,
4525 struct wlan_roam_scan_offload_params *roam_req)
4526 {
4527 wmi_roam_offload_tlv_param *roam_offload_params;
4528 wmi_roam_11i_offload_tlv_param *roam_offload_11i;
4529 wmi_roam_11r_offload_tlv_param *roam_offload_11r;
4530 wmi_roam_ese_offload_tlv_param *roam_offload_ese;
4531 wmi_tlv_buf_len_param *assoc_ies;
4532 uint32_t fils_tlv_len = 0;
4533 int akm = roam_req->akm;
4534 struct wlan_rso_lfr3_params *src_lfr3_params =
4535 &roam_req->rso_lfr3_params;
4536 struct wlan_rso_lfr3_caps *src_lfr3_caps =
4537 &roam_req->rso_lfr3_caps;
4538 struct wlan_rso_11i_params *src_11i_info =
4539 &roam_req->rso_11i_info;
4540 struct wlan_rso_ese_params *src_ese_info =
4541 &roam_req->rso_ese_info;
4542 struct wlan_rso_11r_params *src_11r_info =
4543 &roam_req->rso_11r_info;
4544
4545 /* For RSO stop command, dont fill 11i, 11r or ese tlv */
4546 if (roam_req->is_rso_stop || !roam_req->roam_offload_enabled) {
4547 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC,
4548 WMITLV_GET_STRUCT_TLVLEN(0));
4549 buf += WMI_TLV_HDR_SIZE;
4550 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC,
4551 WMITLV_GET_STRUCT_TLVLEN(0));
4552 buf += WMI_TLV_HDR_SIZE;
4553 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC,
4554 WMITLV_GET_STRUCT_TLVLEN(0));
4555 buf += WMI_TLV_HDR_SIZE;
4556
4557 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC,
4558 WMITLV_GET_STRUCT_TLVLEN(0));
4559 buf += WMI_TLV_HDR_SIZE;
4560 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC,
4561 WMITLV_GET_STRUCT_TLVLEN(0));
4562 buf += WMI_TLV_HDR_SIZE;
4563 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_BYTE,
4564 WMITLV_GET_STRUCT_TLVLEN(0));
4565
4566 return QDF_STATUS_SUCCESS;
4567 }
4568
4569 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC,
4570 sizeof(wmi_roam_offload_tlv_param));
4571
4572 buf += WMI_TLV_HDR_SIZE;
4573 roam_offload_params = (wmi_roam_offload_tlv_param *)buf;
4574 WMITLV_SET_HDR(buf,
4575 WMITLV_TAG_STRUC_wmi_roam_offload_tlv_param,
4576 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_offload_tlv_param));
4577
4578 roam_offload_params->prefer_5g = src_lfr3_params->prefer_5ghz;
4579 roam_offload_params->rssi_cat_gap = src_lfr3_params->roam_rssi_cat_gap;
4580 roam_offload_params->select_5g_margin =
4581 src_lfr3_params->select_5ghz_margin;
4582 roam_offload_params->handoff_delay_for_rx =
4583 src_lfr3_params->ho_delay_for_rx;
4584 roam_offload_params->max_mlme_sw_retries =
4585 src_lfr3_params->roam_retry_count;
4586 roam_offload_params->no_ack_timeout =
4587 src_lfr3_params->roam_preauth_no_ack_timeout;
4588 roam_offload_params->reassoc_failure_timeout =
4589 src_lfr3_params->reassoc_failure_timeout;
4590 roam_offload_params->roam_candidate_validity_time =
4591 src_lfr3_params->rct_validity_timer;
4592 roam_offload_params->roam_to_current_bss_disable =
4593 src_lfr3_params->disable_self_roam;
4594 wmi_debug("RSO_CFG: prefer_5g:%d rssi_cat_gap:%d select_5g_margin:%d ho_delay:%d max_sw_retry:%d no_ack_timeout:%d",
4595 roam_offload_params->prefer_5g,
4596 roam_offload_params->rssi_cat_gap,
4597 roam_offload_params->select_5g_margin,
4598 roam_offload_params->handoff_delay_for_rx,
4599 roam_offload_params->max_mlme_sw_retries,
4600 roam_offload_params->no_ack_timeout);
4601 wmi_debug("RSO_CFG: reassoc_fail_timeout:%d rct_validity_time:%d disable_self_roam:%d",
4602 roam_offload_params->reassoc_failure_timeout,
4603 roam_offload_params->roam_candidate_validity_time,
4604 roam_offload_params->roam_to_current_bss_disable);
4605
4606 /* Fill the capabilities */
4607 roam_offload_params->capability = src_lfr3_caps->capability;
4608 roam_offload_params->ht_caps_info = src_lfr3_caps->ht_caps_info;
4609 roam_offload_params->ampdu_param = src_lfr3_caps->ampdu_param;
4610 roam_offload_params->ht_ext_cap = src_lfr3_caps->ht_ext_cap;
4611 roam_offload_params->ht_txbf = src_lfr3_caps->ht_txbf;
4612 roam_offload_params->asel_cap = src_lfr3_caps->asel_cap;
4613 roam_offload_params->qos_caps = src_lfr3_caps->qos_caps;
4614 roam_offload_params->qos_enabled = src_lfr3_caps->qos_enabled;
4615 roam_offload_params->wmm_caps = src_lfr3_caps->wmm_caps;
4616 qdf_mem_copy((uint8_t *)roam_offload_params->mcsset,
4617 (uint8_t *)src_lfr3_caps->mcsset,
4618 ROAM_OFFLOAD_NUM_MCS_SET);
4619 wmi_debug("RSO_CFG: capability:0x%x ht_caps:0x%x ampdu_param:0%x ht_ext_cap:0x%x ht_txbf:0x%x asel_cap:0x%x qos_caps:0x%x qos_en:%d wmm_caps:0x%x",
4620 roam_offload_params->capability,
4621 roam_offload_params->ht_caps_info,
4622 roam_offload_params->ampdu_param,
4623 roam_offload_params->ht_ext_cap,
4624 roam_offload_params->ht_txbf, roam_offload_params->asel_cap,
4625 roam_offload_params->qos_caps,
4626 roam_offload_params->qos_enabled,
4627 roam_offload_params->wmm_caps);
4628
4629 buf += sizeof(wmi_roam_offload_tlv_param);
4630 /*
4631 * The TLV's are in the order of 11i, 11R, ESE. Hence,
4632 * they are filled in the same order.Depending on the
4633 * authentication type, the other mode TLV's are nullified
4634 * and only headers are filled.
4635 */
4636 if ((akm != WMI_AUTH_OPEN || roam_req->rso_ese_info.is_ese_assoc ||
4637 wmi_is_ft_akm(akm, roam_req)) && akm != WMI_AUTH_NONE) {
4638 if (roam_req->rso_ese_info.is_ese_assoc) {
4639 /* Fill the length of 11i, 11r TLV as 0 */
4640 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0);
4641 buf += WMI_TLV_HDR_SIZE;
4642
4643 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0);
4644 buf += WMI_TLV_HDR_SIZE;
4645
4646 /* Start filling the ESE TLV */
4647 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC,
4648 sizeof(wmi_roam_ese_offload_tlv_param));
4649 buf += WMI_TLV_HDR_SIZE;
4650 roam_offload_ese =
4651 (wmi_roam_ese_offload_tlv_param *)buf;
4652 qdf_mem_copy(roam_offload_ese->krk, src_ese_info->krk,
4653 sizeof(src_ese_info->krk));
4654 qdf_mem_copy(roam_offload_ese->btk, src_ese_info->btk,
4655 sizeof(src_ese_info->btk));
4656
4657 WMITLV_SET_HDR(&roam_offload_ese->tlv_header,
4658 WMITLV_TAG_STRUC_wmi_roam_ese_offload_tlv_param,
4659 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_ese_offload_tlv_param));
4660
4661 buf += sizeof(wmi_roam_ese_offload_tlv_param);
4662 } else if (wmi_is_ft_akm(akm, roam_req)) {
4663 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0);
4664 buf += WMI_TLV_HDR_SIZE;
4665
4666 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC,
4667 sizeof(wmi_roam_11r_offload_tlv_param));
4668 buf += WMI_TLV_HDR_SIZE;
4669
4670 roam_offload_11r =
4671 (wmi_roam_11r_offload_tlv_param *)buf;
4672
4673 roam_offload_11r->r0kh_id_len =
4674 src_11r_info->r0kh_id_length;
4675 qdf_mem_copy(roam_offload_11r->r0kh_id,
4676 src_11r_info->r0kh_id,
4677 src_11r_info->r0kh_id_length);
4678
4679 wmi_fill_roam_offload_11r_params(akm, roam_offload_11r,
4680 roam_req);
4681
4682 roam_offload_11r->mdie_present =
4683 src_11r_info->mdid.mdie_present;
4684 roam_offload_11r->mdid =
4685 src_11r_info->mdid.mobility_domain;
4686 roam_offload_11r->adaptive_11r =
4687 src_11r_info->is_adaptive_11r;
4688 roam_offload_11r->ft_im_for_deauth =
4689 src_11r_info->enable_ft_im_roaming;
4690 roam_offload_11r->ft_over_ds_enable =
4691 src_11r_info->enable_ft_over_ds;
4692
4693 if (akm == WMI_AUTH_OPEN) {
4694 /*
4695 * If FT-Open ensure pmk length
4696 * and r0khid len are zero
4697 */
4698 roam_offload_11r->r0kh_id_len = 0;
4699 roam_offload_11r->psk_msk_len = 0;
4700 }
4701
4702 WMITLV_SET_HDR(&roam_offload_11r->tlv_header,
4703 WMITLV_TAG_STRUC_wmi_roam_11r_offload_tlv_param,
4704 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_11r_offload_tlv_param));
4705
4706 buf += sizeof(wmi_roam_11r_offload_tlv_param);
4707 /* Set ESE TLV len to 0*/
4708 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0);
4709 buf += WMI_TLV_HDR_SIZE;
4710
4711 wmi_debug("RSO_CFG: vdev[%d] 11r TLV psk_msk_len = %d psk_msk_ext:%d md:0x%x",
4712 roam_req->vdev_id,
4713 roam_offload_11r->psk_msk_len,
4714 roam_offload_11r->psk_msk_ext_len,
4715 roam_offload_11r->mdid);
4716 if (roam_offload_11r->psk_msk_len)
4717 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI,
4718 QDF_TRACE_LEVEL_DEBUG,
4719 roam_offload_11r->psk_msk,
4720 WLAN_MAX_PMK_DUMP_BYTES);
4721 } else {
4722 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC,
4723 sizeof(wmi_roam_11i_offload_tlv_param));
4724 buf += WMI_TLV_HDR_SIZE;
4725
4726 roam_offload_11i =
4727 (wmi_roam_11i_offload_tlv_param *)buf;
4728
4729 if (src_11i_info->roam_key_mgmt_offload_enabled &&
4730 src_11i_info->fw_okc)
4731 WMI_SET_ROAM_OFFLOAD_OKC_ENABLED(
4732 roam_offload_11i->flags);
4733 else
4734 WMI_SET_ROAM_OFFLOAD_OKC_DISABLED(
4735 roam_offload_11i->flags);
4736
4737 if (src_11i_info->roam_key_mgmt_offload_enabled &&
4738 src_11i_info->fw_pmksa_cache)
4739 WMI_SET_ROAM_OFFLOAD_PMK_CACHE_ENABLED(
4740 roam_offload_11i->flags);
4741 else
4742 WMI_SET_ROAM_OFFLOAD_PMK_CACHE_DISABLED(
4743 roam_offload_11i->flags);
4744
4745 wmi_fill_sae_single_pmk_param(src_11i_info,
4746 roam_offload_11i);
4747
4748 roam_offload_11i->pmk_len =
4749 src_11i_info->pmk_len > ROAM_OFFLOAD_PMK_BYTES ?
4750 ROAM_OFFLOAD_PMK_BYTES : src_11i_info->pmk_len;
4751 qdf_mem_copy(roam_offload_11i->pmk,
4752 src_11i_info->psk_pmk,
4753 roam_offload_11i->pmk_len);
4754
4755 roam_offload_11i->pmk_ext_len = 0;
4756 if (src_11i_info->pmk_len > ROAM_OFFLOAD_PMK_BYTES) {
4757 roam_offload_11i->pmk_ext_len =
4758 QDF_MIN(src_11i_info->pmk_len -
4759 ROAM_OFFLOAD_PMK_BYTES,
4760 ROAM_OFFLOAD_PMK_BYTES);
4761 }
4762 qdf_mem_copy(
4763 roam_offload_11i->pmk_ext,
4764 &src_11i_info->psk_pmk[ROAM_OFFLOAD_PMK_BYTES],
4765 roam_offload_11i->pmk_ext_len);
4766
4767 WMITLV_SET_HDR(&roam_offload_11i->tlv_header,
4768 WMITLV_TAG_STRUC_wmi_roam_11i_offload_tlv_param,
4769 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_11i_offload_tlv_param));
4770
4771 buf += sizeof(wmi_roam_11i_offload_tlv_param);
4772
4773 /*
4774 * Set 11r TLV len to 0, since security profile is not
4775 * FT
4776 */
4777 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0);
4778 buf += WMI_TLV_HDR_SIZE;
4779
4780 /*
4781 * Set ESE TLV len to 0 since security profile is not
4782 * ESE
4783 */
4784 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0);
4785 buf += WMI_TLV_HDR_SIZE;
4786
4787 wmi_info("RSO_CFG: vdev:%d pmk_len = %d pmksa caching:%d OKC:%d sae_same_pmk:%d key_mgmt_offload:%d",
4788 roam_req->vdev_id, roam_offload_11i->pmk_len,
4789 src_11i_info->fw_pmksa_cache,
4790 src_11i_info->fw_okc,
4791 src_11i_info->is_sae_same_pmk,
4792 src_11i_info->roam_key_mgmt_offload_enabled);
4793 if (roam_offload_11i->pmk_len)
4794 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI,
4795 QDF_TRACE_LEVEL_DEBUG,
4796 roam_offload_11i->pmk,
4797 WLAN_MAX_PMK_DUMP_BYTES);
4798 if (roam_offload_11i->pmk_ext_len)
4799 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI,
4800 QDF_TRACE_LEVEL_DEBUG,
4801 roam_offload_11i->pmk_ext,
4802 WLAN_MAX_PMK_DUMP_BYTES);
4803 }
4804 } else {
4805 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0);
4806 buf += WMI_TLV_HDR_SIZE;
4807
4808 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0);
4809 buf += WMI_TLV_HDR_SIZE;
4810
4811 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0);
4812 buf += WMI_TLV_HDR_SIZE;
4813 }
4814
4815 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, sizeof(*assoc_ies));
4816 buf += WMI_TLV_HDR_SIZE;
4817
4818 assoc_ies = (wmi_tlv_buf_len_param *)buf;
4819 WMITLV_SET_HDR(&assoc_ies->tlv_header,
4820 WMITLV_TAG_STRUC_wmi_tlv_buf_len_param,
4821 WMITLV_GET_STRUCT_TLVLEN(wmi_tlv_buf_len_param));
4822 assoc_ies->buf_len = roam_req->assoc_ie_length;
4823
4824 buf += sizeof(*assoc_ies);
4825
4826 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_BYTE,
4827 roundup(assoc_ies->buf_len, sizeof(uint32_t)));
4828 buf += WMI_TLV_HDR_SIZE;
4829
4830 wmi_debug("RSO_CFG: akm:%d assoc_ies len:%d", akm, assoc_ies->buf_len);
4831 if (assoc_ies->buf_len)
4832 qdf_mem_copy(buf, roam_req->assoc_ie, assoc_ies->buf_len);
4833
4834 buf += qdf_roundup(assoc_ies->buf_len, sizeof(uint32_t));
4835 buf = wmi_add_fils_tlv(wmi_handle, roam_req, buf, fils_tlv_len);
4836
4837 buf = wmi_fill_sae_single_pmk_tlv(roam_req, buf);
4838
4839 return QDF_STATUS_SUCCESS;
4840 }
4841 #else
4842 static inline
wmi_get_rso_buf_len(struct wlan_roam_scan_offload_params * roam_req)4843 uint32_t wmi_get_rso_buf_len(struct wlan_roam_scan_offload_params *roam_req)
4844 {
4845 return 0;
4846 }
4847
4848 static inline QDF_STATUS
wmi_fill_rso_tlvs(wmi_unified_t wmi_handle,uint8_t * buf_ptr,struct wlan_roam_scan_offload_params * roam_req)4849 wmi_fill_rso_tlvs(wmi_unified_t wmi_handle, uint8_t *buf_ptr,
4850 struct wlan_roam_scan_offload_params *roam_req)
4851 {
4852 return QDF_STATUS_SUCCESS;
4853 }
4854 #endif
4855
4856 static QDF_STATUS
wmi_fill_rso_start_scan_tlv(struct wlan_roam_scan_offload_params * rso_req,wmi_start_scan_cmd_fixed_param * scan_tlv)4857 wmi_fill_rso_start_scan_tlv(struct wlan_roam_scan_offload_params *rso_req,
4858 wmi_start_scan_cmd_fixed_param *scan_tlv)
4859 {
4860 struct wlan_roam_scan_params *src_scan_params;
4861
4862 src_scan_params = &rso_req->rso_scan_params;
4863 scan_tlv->scan_ctrl_flags = WMI_SCAN_ADD_CCK_RATES |
4864 WMI_SCAN_ADD_OFDM_RATES |
4865 WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ |
4866 WMI_SCAN_FILTER_PROBE_REQ;
4867 if (rso_req->is_rso_stop) {
4868 scan_tlv->dwell_time_active =
4869 ROAM_SCAN_DWELL_TIME_ACTIVE_DEFAULT;
4870 scan_tlv->dwell_time_passive =
4871 ROAM_SCAN_DWELL_TIME_PASSIVE_DEFAULT;
4872 scan_tlv->min_rest_time = ROAM_SCAN_MIN_REST_TIME_DEFAULT;
4873 scan_tlv->max_rest_time = ROAM_SCAN_MAX_REST_TIME_DEFAULT;
4874 scan_tlv->repeat_probe_time = 0;
4875 scan_tlv->probe_spacing_time = 0;
4876 scan_tlv->probe_delay = 0;
4877 scan_tlv->max_scan_time = ROAM_SCAN_HW_DEF_SCAN_MAX_DURATION;
4878 scan_tlv->idle_time = src_scan_params->min_rest_time;
4879 scan_tlv->burst_duration = 0;
4880
4881 return QDF_STATUS_SUCCESS;
4882 }
4883
4884 scan_tlv->dwell_time_active = src_scan_params->dwell_time_active;
4885 scan_tlv->dwell_time_passive = src_scan_params->dwell_time_passive;
4886 scan_tlv->min_dwell_time_6ghz = src_scan_params->min_dwell_time_6ghz;
4887 scan_tlv->burst_duration = src_scan_params->burst_duration;
4888 scan_tlv->min_rest_time = src_scan_params->min_rest_time;
4889 scan_tlv->max_rest_time = src_scan_params->max_rest_time;
4890 scan_tlv->repeat_probe_time = src_scan_params->repeat_probe_time;
4891 scan_tlv->probe_spacing_time = src_scan_params->probe_spacing_time;
4892 scan_tlv->probe_delay = src_scan_params->probe_delay;
4893 scan_tlv->max_scan_time = ROAM_SCAN_HW_DEF_SCAN_MAX_DURATION;
4894 scan_tlv->idle_time = src_scan_params->idle_time;
4895 scan_tlv->n_probes = src_scan_params->n_probes;
4896 scan_tlv->scan_ctrl_flags |= src_scan_params->scan_ctrl_flags;
4897 scan_tlv->dwell_time_active_6ghz =
4898 src_scan_params->dwell_time_active_6ghz;
4899 scan_tlv->dwell_time_passive_6ghz =
4900 src_scan_params->dwell_time_passive_6ghz;
4901
4902 WMI_SCAN_SET_DWELL_MODE(scan_tlv->scan_ctrl_flags,
4903 src_scan_params->rso_adaptive_dwell_mode);
4904
4905 /* Configure roaming scan behavior (DBS/Non-DBS scan) */
4906 if (rso_req->roaming_scan_policy)
4907 scan_tlv->scan_ctrl_flags_ext |=
4908 WMI_SCAN_DBS_POLICY_FORCE_NONDBS;
4909 else
4910 scan_tlv->scan_ctrl_flags_ext |=
4911 WMI_SCAN_DBS_POLICY_DEFAULT;
4912
4913 wmi_debug("RSO_CFG: dwell time: active %d passive %d, burst_duration:%d, active 6g %d passive 6g %d, min_rest_time %d max rest %d repeat probe time %d probe_spacing:%d",
4914 scan_tlv->dwell_time_active, scan_tlv->dwell_time_passive,
4915 scan_tlv->burst_duration,
4916 scan_tlv->dwell_time_active_6ghz,
4917 scan_tlv->dwell_time_passive_6ghz,
4918 scan_tlv->min_rest_time, scan_tlv->max_rest_time,
4919 scan_tlv->repeat_probe_time, scan_tlv->probe_spacing_time);
4920 wmi_debug("RSO_CFG: ctrl_flags:0x%x probe_delay:%d max_scan_time:%d idle_time:%d n_probes:%d",
4921 scan_tlv->scan_ctrl_flags_ext, scan_tlv->probe_delay,
4922 scan_tlv->max_scan_time, scan_tlv->idle_time,
4923 scan_tlv->n_probes);
4924
4925 return QDF_STATUS_SUCCESS;
4926 }
4927
4928 #ifdef WLAN_FEATURE_11BE_MLO
4929 static void
wmi_set_rso_stop_report_status(wmi_roam_scan_mode_fixed_param * rso_fp)4930 wmi_set_rso_stop_report_status(wmi_roam_scan_mode_fixed_param *rso_fp)
4931 {
4932 /**
4933 * Set the REPORT status flag always, so that firmware sends RSO stop
4934 * status always
4935 */
4936 rso_fp->flags |= WMI_ROAM_SCAN_MODE_FLAG_REPORT_STATUS;
4937 }
4938 #else
4939 static void
wmi_set_rso_stop_report_status(wmi_roam_scan_mode_fixed_param * rso_fp)4940 wmi_set_rso_stop_report_status(wmi_roam_scan_mode_fixed_param *rso_fp)
4941 {
4942 }
4943 #endif
4944
4945 /**
4946 * send_roam_scan_offload_mode_cmd_tlv() - send roam scan mode request to fw
4947 * @wmi_handle: wmi handle
4948 * @rso_req: roam request param
4949 *
4950 * send WMI_ROAM_SCAN_MODE TLV to firmware. It has a piggyback
4951 * of WMI_ROAM_SCAN_MODE.
4952 *
4953 * Return: QDF status
4954 */
4955 static QDF_STATUS
send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_roam_scan_offload_params * rso_req)4956 send_roam_scan_offload_mode_cmd_tlv(
4957 wmi_unified_t wmi_handle,
4958 struct wlan_roam_scan_offload_params *rso_req)
4959 {
4960 wmi_buf_t buf = NULL;
4961 QDF_STATUS status;
4962 size_t len;
4963 uint8_t *buf_ptr;
4964 wmi_roam_scan_mode_fixed_param *roam_scan_mode_fp;
4965 wmi_start_scan_cmd_fixed_param *scan_cmd_fp;
4966 struct wlan_roam_scan_mode_params *src_rso_mode_info = NULL;
4967
4968 /*
4969 * Need to create a buf with roam_scan command at
4970 * front and piggyback with scan command
4971 */
4972 len = sizeof(wmi_roam_scan_mode_fixed_param) +
4973 sizeof(wmi_start_scan_cmd_fixed_param);
4974 len += wmi_get_rso_buf_len(rso_req);
4975
4976 if (rso_req->rso_mode_info.roam_scan_mode ==
4977 (WMI_ROAM_SCAN_MODE_NONE | WMI_ROAM_SCAN_MODE_ROAMOFFLOAD))
4978 len = sizeof(wmi_roam_scan_mode_fixed_param);
4979
4980 buf = wmi_buf_alloc(wmi_handle, len);
4981 if (!buf)
4982 return QDF_STATUS_E_NOMEM;
4983
4984 buf_ptr = (uint8_t *)wmi_buf_data(buf);
4985
4986 src_rso_mode_info = &rso_req->rso_mode_info;
4987 roam_scan_mode_fp = (wmi_roam_scan_mode_fixed_param *)buf_ptr;
4988 WMITLV_SET_HDR(
4989 &roam_scan_mode_fp->tlv_header,
4990 WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param,
4991 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_scan_mode_fixed_param));
4992
4993 roam_scan_mode_fp->min_delay_roam_trigger_reason_bitmask =
4994 src_rso_mode_info->min_delay_roam_trigger_bitmask;
4995 roam_scan_mode_fp->min_delay_btw_scans =
4996 WMI_SEC_TO_MSEC(src_rso_mode_info->min_delay_btw_scans);
4997 roam_scan_mode_fp->roam_scan_mode = src_rso_mode_info->roam_scan_mode;
4998 roam_scan_mode_fp->vdev_id = rso_req->vdev_id;
4999 wmi_debug("RSO_CFG: vdev_id:%d roam scan mode:0x%x min_delay_bitmap:0x%x min_delay_btw_scans:%d",
5000 rso_req->vdev_id,
5001 roam_scan_mode_fp->roam_scan_mode,
5002 roam_scan_mode_fp->min_delay_roam_trigger_reason_bitmask,
5003 roam_scan_mode_fp->min_delay_btw_scans);
5004 /*
5005 * For supplicant disabled roaming, all other roam triggers are disabled
5006 * so send only roam scan mode Fixed param in the command
5007 */
5008 if (src_rso_mode_info->roam_scan_mode ==
5009 (WMI_ROAM_SCAN_MODE_NONE | WMI_ROAM_SCAN_MODE_ROAMOFFLOAD)) {
5010 roam_scan_mode_fp->flags |=
5011 WMI_ROAM_SCAN_MODE_FLAG_REPORT_STATUS;
5012 goto send_roam_scan_mode_cmd;
5013 } else {
5014 wmi_set_rso_stop_report_status(roam_scan_mode_fp);
5015 }
5016
5017 /* Fill in scan parameters suitable for roaming scan */
5018 buf_ptr += sizeof(wmi_roam_scan_mode_fixed_param);
5019 WMITLV_SET_HDR(
5020 buf_ptr,
5021 WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param,
5022 WMITLV_GET_STRUCT_TLVLEN(wmi_start_scan_cmd_fixed_param));
5023 scan_cmd_fp = (wmi_start_scan_cmd_fixed_param *)buf_ptr;
5024 wmi_fill_rso_start_scan_tlv(rso_req, scan_cmd_fp);
5025
5026 /* Ensure there is no additional IEs */
5027 scan_cmd_fp->ie_len = 0;
5028 buf_ptr += sizeof(wmi_start_scan_cmd_fixed_param);
5029
5030 status = wmi_fill_rso_tlvs(wmi_handle, buf_ptr, rso_req);
5031 if (QDF_IS_STATUS_ERROR(status)) {
5032 wmi_buf_free(buf);
5033 return status;
5034 }
5035
5036 send_roam_scan_mode_cmd:
5037 wmi_mtrace(WMI_ROAM_SCAN_MODE, rso_req->vdev_id, 0);
5038 status = wmi_unified_cmd_send(wmi_handle, buf,
5039 len, WMI_ROAM_SCAN_MODE);
5040 if (QDF_IS_STATUS_ERROR(status))
5041 wmi_buf_free(buf);
5042
5043 return status;
5044 }
5045
5046 #ifdef WLAN_FEATURE_11BE_MLO
5047 static void
send_update_mlo_roam_params(wmi_roam_cnd_scoring_param * score_param,struct ap_profile_params * ap_profile)5048 send_update_mlo_roam_params(wmi_roam_cnd_scoring_param *score_param,
5049 struct ap_profile_params *ap_profile)
5050 {
5051 score_param->eht_weightage_pcnt =
5052 ap_profile->param.eht_caps_weightage;
5053 score_param->mlo_weightage_pcnt =
5054 ap_profile->param.mlo_weightage;
5055 wmi_debug("11be score params weightage: EHT %d MLO %d",
5056 score_param->eht_weightage_pcnt,
5057 score_param->mlo_weightage_pcnt);
5058 }
5059
convert_support_link_band_to_wmi(uint32_t bands)5060 static uint32_t convert_support_link_band_to_wmi(uint32_t bands)
5061 {
5062 uint32_t target_bands = 0;
5063
5064 if (bands & BIT(REG_BAND_2G))
5065 target_bands |= BIT(0);
5066 if (bands & BIT(REG_BAND_5G))
5067 target_bands |= BIT(1);
5068 if (bands & BIT(REG_BAND_6G))
5069 target_bands |= BIT(2);
5070
5071 return target_bands;
5072 }
5073
5074 /**
5075 * send_roam_mlo_config_tlv() - send roam mlo config parameters
5076 * @wmi_handle: wmi handle
5077 * @req: pointer to wlan roam mlo config parameters
5078 *
5079 * This function sends the roam mlo config parameters to fw.
5080 *
5081 * Return: QDF status
5082 */
5083 static QDF_STATUS
send_roam_mlo_config_tlv(wmi_unified_t wmi_handle,struct wlan_roam_mlo_config * req)5084 send_roam_mlo_config_tlv(wmi_unified_t wmi_handle,
5085 struct wlan_roam_mlo_config *req)
5086 {
5087 wmi_roam_mlo_config_cmd_fixed_param *cmd;
5088 wmi_buf_t buf;
5089 uint32_t len;
5090
5091 len = sizeof(*cmd);
5092 buf = wmi_buf_alloc(wmi_handle, len);
5093 if (!buf)
5094 return QDF_STATUS_E_NOMEM;
5095
5096 cmd = (wmi_roam_mlo_config_cmd_fixed_param *)wmi_buf_data(buf);
5097 WMITLV_SET_HDR(
5098 &cmd->tlv_header,
5099 WMITLV_TAG_STRUC_wmi_roam_mlo_config_cmd_fixed_param,
5100 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_mlo_config_cmd_fixed_param));
5101
5102 cmd->vdev_id = req->vdev_id;
5103 cmd->support_link_num = req->support_link_num;
5104 cmd->support_link_band = convert_support_link_band_to_wmi(
5105 req->support_link_band);
5106 if (!req->mlo_5gl_5gh_mlsr)
5107 cmd->disallow_connect_modes |= WMI_ROAM_MLO_CONNECTION_MODE_5GL_5GH_MLSR;
5108
5109 WMI_CHAR_ARRAY_TO_MAC_ADDR(req->partner_link_addr.bytes,
5110 &cmd->partner_link_addr);
5111
5112 wmi_debug("RSO_CFG MLO: vdev_id:%d support_link_num:%d support_link_band:0x%0x disallow_connect_mode %d link addr:"QDF_MAC_ADDR_FMT,
5113 cmd->vdev_id, cmd->support_link_num,
5114 cmd->support_link_band,
5115 cmd->disallow_connect_modes,
5116 QDF_MAC_ADDR_REF(req->partner_link_addr.bytes));
5117
5118 wmi_mtrace(WMI_ROAM_MLO_CONFIG_CMDID, cmd->vdev_id, 0);
5119 if (wmi_unified_cmd_send(wmi_handle, buf, len,
5120 WMI_ROAM_MLO_CONFIG_CMDID)) {
5121 wmi_err("Failed to send WMI_ROAM_MLO_CONFIG_CMDID");
5122 wmi_buf_free(buf);
5123 return QDF_STATUS_E_FAILURE;
5124 }
5125
5126 return QDF_STATUS_SUCCESS;
5127 }
5128
wmi_roam_mlo_attach_tlv(struct wmi_unified * wmi_handle)5129 static void wmi_roam_mlo_attach_tlv(struct wmi_unified *wmi_handle)
5130 {
5131 struct wmi_ops *ops = wmi_handle->ops;
5132
5133 ops->send_roam_mlo_config = send_roam_mlo_config_tlv;
5134 }
5135
5136 #else
5137 static void
send_update_mlo_roam_params(wmi_roam_cnd_scoring_param * score_param,struct ap_profile_params * ap_profile)5138 send_update_mlo_roam_params(wmi_roam_cnd_scoring_param *score_param,
5139 struct ap_profile_params *ap_profile)
5140 {
5141 }
5142
wmi_roam_mlo_attach_tlv(struct wmi_unified * wmi_handle)5143 static void wmi_roam_mlo_attach_tlv(struct wmi_unified *wmi_handle)
5144 {
5145 }
5146 #endif
5147
5148 #ifdef WLAN_FEATURE_11BE_MLO
5149 /**
5150 * update_mlo_prefer_percentage() - Update mlo preference with configured value
5151 * @psoc: psoc object
5152 * @mlo_prefer_percentage: pointer to hold mlo preference percentage
5153 *
5154 * Return: None
5155 */
update_mlo_prefer_percentage(struct wlan_objmgr_psoc * psoc,int8_t * mlo_prefer_percentage)5156 static void update_mlo_prefer_percentage(struct wlan_objmgr_psoc *psoc,
5157 int8_t *mlo_prefer_percentage)
5158 {
5159 wlan_mlme_get_mlo_prefer_percentage(psoc, mlo_prefer_percentage);
5160 /* host will deliver actual weighted number based on 100.
5161 * For example:
5162 * If percentage value in INI is 20, then host will give 120 (100 + 20)
5163 * i.e (100 * 1.2) as mlo_etp_weightage_pcnt.
5164 * If percentage value in INI is -20, then host will give 80 (100 - 20)
5165 * i.e (100 * 0.8) as mlo_etp_weightage_pcnt.
5166 */
5167 *mlo_prefer_percentage += 100;
5168 }
5169 #else
5170 static inline
update_mlo_prefer_percentage(struct wlan_objmgr_psoc * psoc,int8_t * mlo_preference_pctn)5171 void update_mlo_prefer_percentage(struct wlan_objmgr_psoc *psoc,
5172 int8_t *mlo_preference_pctn)
5173 {}
5174 #endif
5175
5176 /**
5177 * send_roam_scan_offload_ap_profile_cmd_tlv() - set roam ap profile in fw
5178 * @wmi_handle: wmi handle
5179 * @ap_profile: ap profile
5180 *
5181 * Send WMI_ROAM_AP_PROFILE to firmware
5182 *
5183 * Return: CDF status
5184 */
5185 static QDF_STATUS
send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle,struct ap_profile_params * ap_profile)5186 send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle,
5187 struct ap_profile_params *ap_profile)
5188 {
5189 wmi_buf_t buf = NULL;
5190 QDF_STATUS status;
5191 size_t len;
5192 uint8_t *buf_ptr;
5193 wmi_roam_ap_profile_fixed_param *roam_ap_profile_fp;
5194 wmi_roam_cnd_scoring_param *score_param;
5195 wmi_ap_profile *profile;
5196 wmi_roam_score_delta_param *score_delta_param;
5197 wmi_roam_cnd_min_rssi_param *min_rssi_param;
5198 wmi_owe_ap_profile *owe_ap_profile;
5199 enum roam_trigger_reason trig_reason;
5200 uint32_t *authmode_list;
5201 int8_t mlo_prefer_percentage = 0;
5202 wmi_ssid *ssid;
5203 int i;
5204
5205 len = sizeof(wmi_roam_ap_profile_fixed_param) + sizeof(wmi_ap_profile);
5206 len += sizeof(*score_param) + WMI_TLV_HDR_SIZE;
5207
5208 if (!wmi_service_enabled(wmi_handle,
5209 wmi_service_configure_roam_trigger_param_support)) {
5210 len += WMI_TLV_HDR_SIZE;
5211 len += NUM_OF_ROAM_TRIGGERS * sizeof(*score_delta_param);
5212 len += WMI_TLV_HDR_SIZE;
5213 len += NUM_OF_ROAM_MIN_RSSI * sizeof(*min_rssi_param);
5214 } else {
5215 len += 2 * WMI_TLV_HDR_SIZE;
5216 }
5217
5218 if (ap_profile->owe_ap_profile.is_owe_transition_conn) {
5219 len += WMI_TLV_HDR_SIZE;
5220 len += sizeof(*owe_ap_profile);
5221 } else {
5222 len += WMI_TLV_HDR_SIZE;
5223 }
5224
5225 if (ap_profile->profile.num_allowed_authmode) {
5226 len += WMI_TLV_HDR_SIZE;
5227 len += ap_profile->profile.num_allowed_authmode *
5228 sizeof(uint32_t);
5229 } else {
5230 len += WMI_TLV_HDR_SIZE;
5231 }
5232
5233 buf = wmi_buf_alloc(wmi_handle, len);
5234 if (!buf)
5235 return QDF_STATUS_E_NOMEM;
5236
5237 buf_ptr = (uint8_t *)wmi_buf_data(buf);
5238 roam_ap_profile_fp = (wmi_roam_ap_profile_fixed_param *)buf_ptr;
5239 WMITLV_SET_HDR(&roam_ap_profile_fp->tlv_header,
5240 WMITLV_TAG_STRUC_wmi_roam_ap_profile_fixed_param,
5241 WMITLV_GET_STRUCT_TLVLEN
5242 (wmi_roam_ap_profile_fixed_param));
5243 /* fill in threshold values */
5244 roam_ap_profile_fp->vdev_id = ap_profile->vdev_id;
5245 roam_ap_profile_fp->id = 0;
5246 buf_ptr += sizeof(wmi_roam_ap_profile_fixed_param);
5247
5248 profile = (wmi_ap_profile *)buf_ptr;
5249 WMITLV_SET_HDR(&profile->tlv_header,
5250 WMITLV_TAG_STRUC_wmi_ap_profile,
5251 WMITLV_GET_STRUCT_TLVLEN(wmi_ap_profile));
5252 profile->flags = ap_profile->profile.flags;
5253 profile->rssi_threshold = ap_profile->profile.rssi_threshold;
5254 profile->bg_rssi_threshold = ap_profile->profile.bg_rssi_threshold;
5255 profile->ssid.ssid_len = ap_profile->profile.ssid.length;
5256 qdf_mem_copy(profile->ssid.ssid, ap_profile->profile.ssid.ssid,
5257 profile->ssid.ssid_len);
5258 profile->rsn_authmode = ap_profile->profile.rsn_authmode;
5259 profile->rsn_ucastcipherset = ap_profile->profile.rsn_ucastcipherset;
5260 profile->rsn_mcastcipherset = ap_profile->profile.rsn_mcastcipherset;
5261 profile->rsn_mcastmgmtcipherset =
5262 ap_profile->profile.rsn_mcastmgmtcipherset;
5263 profile->rssi_abs_thresh = ap_profile->profile.rssi_abs_thresh;
5264
5265 wmi_debug("vdev %d AP PROFILE: flags:%x rssi_thres:%d bg_rssi_thres:%d ssid:" QDF_SSID_FMT " authmode:%d uc cipher:%d mc cipher:%d mc mgmt cipher:%d rssi abs thresh:%d",
5266 roam_ap_profile_fp->vdev_id,
5267 profile->flags, profile->rssi_threshold,
5268 profile->bg_rssi_threshold,
5269 QDF_SSID_REF(profile->ssid.ssid_len,
5270 ap_profile->profile.ssid.ssid),
5271 profile->rsn_authmode, profile->rsn_ucastcipherset,
5272 profile->rsn_mcastcipherset, profile->rsn_mcastmgmtcipherset,
5273 profile->rssi_abs_thresh);
5274
5275 buf_ptr += sizeof(wmi_ap_profile);
5276
5277 score_param = (wmi_roam_cnd_scoring_param *)buf_ptr;
5278 WMITLV_SET_HDR(&score_param->tlv_header,
5279 WMITLV_TAG_STRUC_wmi_roam_cnd_scoring_param,
5280 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_cnd_scoring_param));
5281 score_param->disable_bitmap = ap_profile->param.disable_bitmap;
5282 score_param->rssi_weightage_pcnt =
5283 ap_profile->param.rssi_weightage;
5284 score_param->ht_weightage_pcnt = ap_profile->param.ht_weightage;
5285 score_param->vht_weightage_pcnt = ap_profile->param.vht_weightage;
5286 score_param->he_weightage_pcnt = ap_profile->param.he_weightage;
5287 score_param->bw_weightage_pcnt = ap_profile->param.bw_weightage;
5288 score_param->band_weightage_pcnt = ap_profile->param.band_weightage;
5289 score_param->nss_weightage_pcnt = ap_profile->param.nss_weightage;
5290 score_param->security_weightage_pcnt =
5291 ap_profile->param.security_weightage;
5292 score_param->esp_qbss_weightage_pcnt =
5293 ap_profile->param.esp_qbss_weightage;
5294 score_param->beamforming_weightage_pcnt =
5295 ap_profile->param.beamforming_weightage;
5296 score_param->pcl_weightage_pcnt = ap_profile->param.pcl_weightage;
5297 score_param->oce_wan_weightage_pcnt =
5298 ap_profile->param.oce_wan_weightage;
5299 score_param->oce_ap_tx_pwr_weightage_pcnt =
5300 ap_profile->param.oce_ap_tx_pwr_weightage;
5301 score_param->oce_ap_subnet_id_weightage_pcnt =
5302 ap_profile->param.oce_subnet_id_weightage;
5303 score_param->vendor_roam_score_algorithm_id =
5304 ap_profile->param.vendor_roam_score_algorithm;
5305 score_param->sae_pk_ap_weightage_pcnt =
5306 ap_profile->param.sae_pk_ap_weightage;
5307 update_mlo_prefer_percentage(wmi_handle->soc->wmi_psoc,
5308 &mlo_prefer_percentage);
5309 score_param->mlo_etp_weightage_pcnt = mlo_prefer_percentage;
5310 send_update_mlo_roam_params(score_param, ap_profile);
5311 wmi_debug("Score params weightage: disable_bitmap %x rssi %d ht %d vht %d he %d BW %d band %d NSS %d ESP %d BF %d PCL %d OCE WAN %d APTX %d roam score algo %d subnet id %d sae-pk %d security %d mlo_etp_weight_pct %d",
5312 score_param->disable_bitmap, score_param->rssi_weightage_pcnt,
5313 score_param->ht_weightage_pcnt,
5314 score_param->vht_weightage_pcnt,
5315 score_param->he_weightage_pcnt,
5316 score_param->bw_weightage_pcnt,
5317 score_param->band_weightage_pcnt,
5318 score_param->nss_weightage_pcnt,
5319 score_param->esp_qbss_weightage_pcnt,
5320 score_param->beamforming_weightage_pcnt,
5321 score_param->pcl_weightage_pcnt,
5322 score_param->oce_wan_weightage_pcnt,
5323 score_param->oce_ap_tx_pwr_weightage_pcnt,
5324 score_param->vendor_roam_score_algorithm_id,
5325 score_param->oce_ap_subnet_id_weightage_pcnt,
5326 score_param->sae_pk_ap_weightage_pcnt,
5327 score_param->security_weightage_pcnt,
5328 score_param->mlo_etp_weightage_pcnt);
5329
5330 score_param->bw_scoring.score_pcnt = ap_profile->param.bw_index_score;
5331 score_param->band_scoring.score_pcnt =
5332 ap_profile->param.band_index_score;
5333 score_param->nss_scoring.score_pcnt =
5334 ap_profile->param.nss_index_score;
5335 score_param->security_scoring.score_pcnt =
5336 ap_profile->param.security_index_score;
5337
5338 wmi_debug("bw_index_score %x band_index_score %x nss_index_score %x security_index_score %x",
5339 score_param->bw_scoring.score_pcnt,
5340 score_param->band_scoring.score_pcnt,
5341 score_param->nss_scoring.score_pcnt,
5342 score_param->security_scoring.score_pcnt);
5343
5344 score_param->rssi_scoring.best_rssi_threshold =
5345 (-1) * ap_profile->param.rssi_scoring.best_rssi_threshold;
5346 score_param->rssi_scoring.good_rssi_threshold =
5347 (-1) * ap_profile->param.rssi_scoring.good_rssi_threshold;
5348 score_param->rssi_scoring.bad_rssi_threshold =
5349 (-1) * ap_profile->param.rssi_scoring.bad_rssi_threshold;
5350 score_param->rssi_scoring.good_rssi_pcnt =
5351 ap_profile->param.rssi_scoring.good_rssi_pcnt;
5352 score_param->rssi_scoring.bad_rssi_pcnt =
5353 ap_profile->param.rssi_scoring.bad_rssi_pcnt;
5354 score_param->rssi_scoring.good_bucket_size =
5355 ap_profile->param.rssi_scoring.good_rssi_bucket_size;
5356 score_param->rssi_scoring.bad_bucket_size =
5357 ap_profile->param.rssi_scoring.bad_rssi_bucket_size;
5358 score_param->rssi_scoring.rssi_pref_5g_rssi_thresh =
5359 (-1) * ap_profile->param.rssi_scoring.rssi_pref_5g_rssi_thresh;
5360
5361 wmi_debug("Rssi scoring threshold: best RSSI %d good RSSI %d bad RSSI %d prefer 5g threshold %d",
5362 score_param->rssi_scoring.best_rssi_threshold,
5363 score_param->rssi_scoring.good_rssi_threshold,
5364 score_param->rssi_scoring.bad_rssi_threshold,
5365 score_param->rssi_scoring.rssi_pref_5g_rssi_thresh);
5366 wmi_debug("Good RSSI score for each slot %d bad RSSI score for each slot %d good bucket %d bad bucket %d",
5367 score_param->rssi_scoring.good_rssi_pcnt,
5368 score_param->rssi_scoring.bad_rssi_pcnt,
5369 score_param->rssi_scoring.good_bucket_size,
5370 score_param->rssi_scoring.bad_bucket_size);
5371
5372 score_param->esp_qbss_scoring.num_slot =
5373 ap_profile->param.esp_qbss_scoring.num_slot;
5374 score_param->esp_qbss_scoring.score_pcnt3_to_0 =
5375 ap_profile->param.esp_qbss_scoring.score_pcnt3_to_0;
5376 score_param->esp_qbss_scoring.score_pcnt7_to_4 =
5377 ap_profile->param.esp_qbss_scoring.score_pcnt7_to_4;
5378 score_param->esp_qbss_scoring.score_pcnt11_to_8 =
5379 ap_profile->param.esp_qbss_scoring.score_pcnt11_to_8;
5380 score_param->esp_qbss_scoring.score_pcnt15_to_12 =
5381 ap_profile->param.esp_qbss_scoring.score_pcnt15_to_12;
5382
5383 wmi_debug("ESP QBSS index weight: slots %d weight 0to3 %x weight 4to7 %x weight 8to11 %x weight 12to15 %x",
5384 score_param->esp_qbss_scoring.num_slot,
5385 score_param->esp_qbss_scoring.score_pcnt3_to_0,
5386 score_param->esp_qbss_scoring.score_pcnt7_to_4,
5387 score_param->esp_qbss_scoring.score_pcnt11_to_8,
5388 score_param->esp_qbss_scoring.score_pcnt15_to_12);
5389
5390 score_param->oce_wan_scoring.num_slot =
5391 ap_profile->param.oce_wan_scoring.num_slot;
5392 score_param->oce_wan_scoring.score_pcnt3_to_0 =
5393 ap_profile->param.oce_wan_scoring.score_pcnt3_to_0;
5394 score_param->oce_wan_scoring.score_pcnt7_to_4 =
5395 ap_profile->param.oce_wan_scoring.score_pcnt7_to_4;
5396 score_param->oce_wan_scoring.score_pcnt11_to_8 =
5397 ap_profile->param.oce_wan_scoring.score_pcnt11_to_8;
5398 score_param->oce_wan_scoring.score_pcnt15_to_12 =
5399 ap_profile->param.oce_wan_scoring.score_pcnt15_to_12;
5400
5401 wmi_debug("OCE WAN index weight: slots %d weight 0to3 %x weight 4to7 %x weight 8to11 %x weight 12to15 %x",
5402 score_param->oce_wan_scoring.num_slot,
5403 score_param->oce_wan_scoring.score_pcnt3_to_0,
5404 score_param->oce_wan_scoring.score_pcnt7_to_4,
5405 score_param->oce_wan_scoring.score_pcnt11_to_8,
5406 score_param->oce_wan_scoring.score_pcnt15_to_12);
5407
5408 score_param->roam_score_delta_pcnt = ap_profile->param.roam_score_delta;
5409 score_param->roam_score_delta_mask =
5410 ap_profile->param.roam_trigger_bitmap;
5411 score_param->candidate_min_roam_score_delta =
5412 ap_profile->param.cand_min_roam_score_delta;
5413 wmi_debug("Roam score delta:%d Roam_trigger_bitmap:%x cand min score delta = %d",
5414 score_param->roam_score_delta_pcnt,
5415 score_param->roam_score_delta_mask,
5416 score_param->candidate_min_roam_score_delta);
5417
5418 buf_ptr += sizeof(*score_param);
5419
5420 if (!wmi_service_enabled(wmi_handle,
5421 wmi_service_configure_roam_trigger_param_support)) {
5422 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5423 (NUM_OF_ROAM_TRIGGERS * sizeof(*score_delta_param)));
5424 buf_ptr += WMI_TLV_HDR_SIZE;
5425
5426 score_delta_param = (wmi_roam_score_delta_param *)buf_ptr;
5427 WMITLV_SET_HDR(&score_delta_param->tlv_header,
5428 WMITLV_TAG_STRUC_wmi_roam_score_delta_param,
5429 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_score_delta_param));
5430 trig_reason =
5431 ap_profile->score_delta_param[IDLE_ROAM_TRIGGER].trigger_reason;
5432 score_delta_param->roam_trigger_reason =
5433 convert_roam_trigger_reason(trig_reason);
5434 score_delta_param->roam_score_delta =
5435 ap_profile->score_delta_param[IDLE_ROAM_TRIGGER].roam_score_delta;
5436
5437 buf_ptr += sizeof(*score_delta_param);
5438 score_delta_param = (wmi_roam_score_delta_param *)buf_ptr;
5439 WMITLV_SET_HDR(&score_delta_param->tlv_header,
5440 WMITLV_TAG_STRUC_wmi_roam_score_delta_param,
5441 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_score_delta_param));
5442 trig_reason =
5443 ap_profile->score_delta_param[BTM_ROAM_TRIGGER].trigger_reason;
5444 score_delta_param->roam_trigger_reason =
5445 convert_roam_trigger_reason(trig_reason);
5446 score_delta_param->roam_score_delta =
5447 ap_profile->score_delta_param[BTM_ROAM_TRIGGER].roam_score_delta;
5448
5449 buf_ptr += sizeof(*score_delta_param);
5450 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5451 (NUM_OF_ROAM_MIN_RSSI * sizeof(*min_rssi_param)));
5452 buf_ptr += WMI_TLV_HDR_SIZE;
5453
5454 min_rssi_param = (wmi_roam_cnd_min_rssi_param *)buf_ptr;
5455 WMITLV_SET_HDR(&min_rssi_param->tlv_header,
5456 WMITLV_TAG_STRUC_wmi_roam_cnd_min_rssi_param,
5457 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_cnd_min_rssi_param));
5458 trig_reason =
5459 ap_profile->min_rssi_params[DEAUTH_MIN_RSSI].trigger_reason;
5460 min_rssi_param->roam_trigger_reason =
5461 convert_roam_trigger_reason(trig_reason);
5462 min_rssi_param->candidate_min_rssi =
5463 ap_profile->min_rssi_params[DEAUTH_MIN_RSSI].min_rssi;
5464
5465 buf_ptr += sizeof(*min_rssi_param);
5466 min_rssi_param = (wmi_roam_cnd_min_rssi_param *)buf_ptr;
5467 WMITLV_SET_HDR(&min_rssi_param->tlv_header,
5468 WMITLV_TAG_STRUC_wmi_roam_cnd_min_rssi_param,
5469 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_cnd_min_rssi_param));
5470 trig_reason =
5471 ap_profile->min_rssi_params[BMISS_MIN_RSSI].trigger_reason;
5472 min_rssi_param->roam_trigger_reason =
5473 convert_roam_trigger_reason(trig_reason);
5474 min_rssi_param->candidate_min_rssi =
5475 ap_profile->min_rssi_params[BMISS_MIN_RSSI].min_rssi;
5476
5477 buf_ptr += sizeof(*min_rssi_param);
5478 min_rssi_param = (wmi_roam_cnd_min_rssi_param *)buf_ptr;
5479 WMITLV_SET_HDR(&min_rssi_param->tlv_header,
5480 WMITLV_TAG_STRUC_wmi_roam_cnd_min_rssi_param,
5481 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_cnd_min_rssi_param));
5482 trig_reason =
5483 ap_profile->min_rssi_params[MIN_RSSI_2G_TO_5G_ROAM].trigger_reason;
5484 min_rssi_param->roam_trigger_reason =
5485 convert_roam_trigger_reason(trig_reason);
5486 min_rssi_param->candidate_min_rssi =
5487 ap_profile->min_rssi_params[MIN_RSSI_2G_TO_5G_ROAM].min_rssi;
5488
5489 buf_ptr += sizeof(*min_rssi_param);
5490 } else {
5491 /* set zero TLV's for roam_score_delta_param_list */
5492 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5493 WMITLV_GET_STRUCT_TLVLEN(0));
5494 buf_ptr += WMI_TLV_HDR_SIZE;
5495
5496 /* set zero TLV's for roam_cnd_min_rssi_param_list */
5497 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5498 WMITLV_GET_STRUCT_TLVLEN(0));
5499 buf_ptr += WMI_TLV_HDR_SIZE;
5500 }
5501
5502 /* set zero TLV's for roam_cnd_vendor_scoring_param */
5503 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5504 WMITLV_GET_STRUCT_TLVLEN(0));
5505 buf_ptr += WMI_TLV_HDR_SIZE;
5506
5507 if (ap_profile->owe_ap_profile.is_owe_transition_conn) {
5508 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5509 sizeof(*owe_ap_profile));
5510 buf_ptr += WMI_TLV_HDR_SIZE;
5511
5512 owe_ap_profile = (wmi_owe_ap_profile *)buf_ptr;
5513 ssid = &owe_ap_profile->open_ssid_for_owe_transition;
5514 WMITLV_SET_HDR(&owe_ap_profile->tlv_header,
5515 WMITLV_TAG_STRUC_wmi_owe_ap_profile,
5516 WMITLV_GET_STRUCT_TLVLEN(wmi_owe_ap_profile));
5517
5518 ssid->ssid_len = ap_profile->owe_ap_profile.ssid.length;
5519 qdf_mem_copy(ssid->ssid,
5520 ap_profile->owe_ap_profile.ssid.ssid,
5521 ap_profile->owe_ap_profile.ssid.length);
5522 wmi_debug("[OWE_TRANSITION]: open ssid:" QDF_SSID_FMT,
5523 QDF_SSID_REF(ssid->ssid_len, (char *)ssid->ssid));
5524
5525 buf_ptr += sizeof(*owe_ap_profile);
5526 } else {
5527 /* set zero TLV's for owe_ap_profile */
5528 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5529 WMITLV_GET_STRUCT_TLVLEN(0));
5530 buf_ptr += WMI_TLV_HDR_SIZE;
5531 }
5532
5533 /* List of Allowed authmode other than the connected akm */
5534 if (ap_profile->profile.num_allowed_authmode) {
5535 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
5536 (ap_profile->profile.num_allowed_authmode *
5537 sizeof(uint32_t)));
5538
5539 buf_ptr += WMI_TLV_HDR_SIZE;
5540
5541 authmode_list = (uint32_t *)buf_ptr;
5542 for (i = 0; i < ap_profile->profile.num_allowed_authmode; i++)
5543 authmode_list[i] =
5544 ap_profile->profile.allowed_authmode[i];
5545
5546 wmi_debug("[Allowed Authmode]: num_allowed_authmode: %d",
5547 ap_profile->profile.num_allowed_authmode);
5548 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
5549 authmode_list,
5550 ap_profile->profile.num_allowed_authmode *
5551 sizeof(uint32_t));
5552 } else {
5553 /* set zero TLV's for allowed_authmode */
5554 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
5555 WMITLV_GET_STRUCT_TLVLEN(0));
5556 buf_ptr += WMI_TLV_HDR_SIZE;
5557 }
5558
5559 wmi_mtrace(WMI_ROAM_AP_PROFILE, NO_SESSION, 0);
5560 status = wmi_unified_cmd_send(wmi_handle, buf,
5561 len, WMI_ROAM_AP_PROFILE);
5562 if (QDF_IS_STATUS_ERROR(status))
5563 wmi_buf_free(buf);
5564
5565 return status;
5566 }
5567
5568 /**
5569 * send_roam_scan_offload_cmd_tlv() - set roam offload command
5570 * @wmi_handle: wmi handle
5571 * @command: command
5572 * @vdev_id: vdev id
5573 *
5574 * This function set roam offload command to fw.
5575 *
5576 * Return: QDF status
5577 */
5578 static QDF_STATUS
send_roam_scan_offload_cmd_tlv(wmi_unified_t wmi_handle,uint32_t command,uint32_t vdev_id)5579 send_roam_scan_offload_cmd_tlv(wmi_unified_t wmi_handle,
5580 uint32_t command, uint32_t vdev_id)
5581 {
5582 QDF_STATUS status;
5583 wmi_roam_scan_cmd_fixed_param *cmd_fp;
5584 wmi_buf_t buf = NULL;
5585 int len;
5586 uint8_t *buf_ptr;
5587
5588 len = sizeof(wmi_roam_scan_cmd_fixed_param);
5589 buf = wmi_buf_alloc(wmi_handle, len);
5590 if (!buf)
5591 return QDF_STATUS_E_NOMEM;
5592
5593 buf_ptr = (uint8_t *)wmi_buf_data(buf);
5594
5595 cmd_fp = (wmi_roam_scan_cmd_fixed_param *)buf_ptr;
5596 WMITLV_SET_HDR(&cmd_fp->tlv_header,
5597 WMITLV_TAG_STRUC_wmi_roam_scan_cmd_fixed_param,
5598 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_scan_cmd_fixed_param));
5599 cmd_fp->vdev_id = vdev_id;
5600 cmd_fp->command_arg = command;
5601
5602 wmi_mtrace(WMI_ROAM_SCAN_CMD, NO_SESSION, 0);
5603 status = wmi_unified_cmd_send(wmi_handle, buf,
5604 len, WMI_ROAM_SCAN_CMD);
5605 if (QDF_IS_STATUS_ERROR(status))
5606 goto error;
5607
5608 wmi_info("WMI --> WMI_ROAM_SCAN_CMD");
5609 return QDF_STATUS_SUCCESS;
5610
5611 error:
5612 wmi_buf_free(buf);
5613
5614 return status;
5615 }
5616
5617 /**
5618 * send_roam_scan_offload_chan_list_cmd_tlv() - set roam offload channel list
5619 * @wmi_handle: wmi handle
5620 * @rso_ch_info: Roam offload channel information
5621 *
5622 * Set roam offload channel list.
5623 *
5624 * Return: QDF status
5625 */
send_roam_scan_offload_chan_list_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_roam_scan_channel_list * rso_ch_info)5626 static QDF_STATUS send_roam_scan_offload_chan_list_cmd_tlv(
5627 wmi_unified_t wmi_handle,
5628 struct wlan_roam_scan_channel_list *rso_ch_info)
5629 {
5630 wmi_buf_t buf = NULL;
5631 QDF_STATUS status;
5632 int len, list_tlv_len;
5633 int i;
5634 uint8_t *buf_ptr;
5635 wmi_roam_chan_list_fixed_param *chan_list_fp;
5636 uint32_t *roam_chan_list_array;
5637 uint8_t chan_count = rso_ch_info->chan_count;
5638 uint32_t *chan_list = rso_ch_info->chan_freq_list;
5639
5640 /* Channel list is a table of 2 TLV's */
5641 list_tlv_len = WMI_TLV_HDR_SIZE + chan_count * sizeof(uint32_t);
5642 len = sizeof(wmi_roam_chan_list_fixed_param) + list_tlv_len;
5643 buf = wmi_buf_alloc(wmi_handle, len);
5644 if (!buf)
5645 return QDF_STATUS_E_NOMEM;
5646
5647 buf_ptr = (uint8_t *)wmi_buf_data(buf);
5648 chan_list_fp = (wmi_roam_chan_list_fixed_param *)buf_ptr;
5649 WMITLV_SET_HDR(&chan_list_fp->tlv_header,
5650 WMITLV_TAG_STRUC_wmi_roam_chan_list_fixed_param,
5651 WMITLV_GET_STRUCT_TLVLEN
5652 (wmi_roam_chan_list_fixed_param));
5653 chan_list_fp->vdev_id = rso_ch_info->vdev_id;
5654 chan_list_fp->num_chan = chan_count;
5655 if (rso_ch_info->chan_cache_type == WMI_CHANNEL_LIST_STATIC)
5656 /* external app is controlling channel list */
5657 chan_list_fp->chan_list_type =
5658 WMI_ROAM_SCAN_CHAN_LIST_TYPE_STATIC;
5659 else
5660 /* umac supplied occupied channel list in LFR */
5661 chan_list_fp->chan_list_type =
5662 WMI_ROAM_SCAN_CHAN_LIST_TYPE_DYNAMIC;
5663
5664 buf_ptr += sizeof(wmi_roam_chan_list_fixed_param);
5665 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
5666 (chan_list_fp->num_chan * sizeof(uint32_t)));
5667 roam_chan_list_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
5668 for (i = 0; ((i < chan_list_fp->num_chan) &&
5669 (i < WMI_ROAM_MAX_CHANNELS)); i++)
5670 roam_chan_list_array[i] = chan_list[i];
5671
5672 wmi_debug("RSO_CFG: vdev:%d num_chan:%d cache_type:%d",
5673 chan_list_fp->vdev_id, chan_list_fp->num_chan,
5674 rso_ch_info->chan_cache_type);
5675 wmi_mtrace(WMI_ROAM_CHAN_LIST, NO_SESSION, 0);
5676 status = wmi_unified_cmd_send(wmi_handle, buf,
5677 len, WMI_ROAM_CHAN_LIST);
5678 if (QDF_IS_STATUS_ERROR(status))
5679 goto error;
5680
5681 return QDF_STATUS_SUCCESS;
5682 error:
5683 wmi_buf_free(buf);
5684
5685 return status;
5686 }
5687
5688 /**
5689 * send_roam_scan_offload_rssi_change_cmd_tlv() - set roam offload RSSI th
5690 * @wmi_handle: wmi handle
5691 * @params: RSSI change parameters
5692 *
5693 * Send WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD parameters to fw.
5694 *
5695 * Return: CDF status
5696 */
send_roam_scan_offload_rssi_change_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_roam_rssi_change_params * params)5697 static QDF_STATUS send_roam_scan_offload_rssi_change_cmd_tlv(
5698 wmi_unified_t wmi_handle,
5699 struct wlan_roam_rssi_change_params *params)
5700 {
5701 wmi_buf_t buf = NULL;
5702 QDF_STATUS status;
5703 int len;
5704 uint8_t *buf_ptr;
5705 wmi_roam_scan_rssi_change_threshold_fixed_param *rssi_change_fp;
5706
5707 /* Send rssi change parameters */
5708 len = sizeof(wmi_roam_scan_rssi_change_threshold_fixed_param);
5709 buf = wmi_buf_alloc(wmi_handle, len);
5710 if (!buf)
5711 return QDF_STATUS_E_NOMEM;
5712
5713 buf_ptr = (uint8_t *)wmi_buf_data(buf);
5714 rssi_change_fp =
5715 (wmi_roam_scan_rssi_change_threshold_fixed_param *)buf_ptr;
5716 WMITLV_SET_HDR(&rssi_change_fp->tlv_header,
5717 WMITLV_TAG_STRUC_wmi_roam_scan_rssi_change_threshold_fixed_param,
5718 WMITLV_GET_STRUCT_TLVLEN
5719 (wmi_roam_scan_rssi_change_threshold_fixed_param));
5720 /* fill in rssi change threshold (hysteresis) values */
5721 rssi_change_fp->vdev_id = params->vdev_id;
5722 rssi_change_fp->roam_scan_rssi_change_thresh =
5723 params->rssi_change_thresh;
5724 rssi_change_fp->bcn_rssi_weight = params->bcn_rssi_weight;
5725 rssi_change_fp->hirssi_delay_btw_scans = params->hirssi_delay_btw_scans;
5726
5727 wmi_nofl_debug("RSO_CFG: vdev %d rssi_change_thresh:%d bcn_rssi_weight:%d hirssi_delay_btw_scans:%d",
5728 rssi_change_fp->vdev_id,
5729 rssi_change_fp->roam_scan_rssi_change_thresh,
5730 rssi_change_fp->bcn_rssi_weight,
5731 rssi_change_fp->hirssi_delay_btw_scans);
5732
5733 wmi_mtrace(WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
5734 rssi_change_fp->vdev_id, 0);
5735 status = wmi_unified_cmd_send(wmi_handle, buf, len,
5736 WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD);
5737 if (QDF_IS_STATUS_ERROR(status))
5738 goto error;
5739
5740 return QDF_STATUS_SUCCESS;
5741 error:
5742 wmi_buf_free(buf);
5743
5744 return status;
5745 }
5746
5747 /**
5748 * send_per_roam_config_cmd_tlv() - set per roaming config to FW
5749 * @wmi_handle: wmi handle
5750 * @req_buf: per roam config buffer
5751 *
5752 * Return: QDF status
5753 */
5754 static QDF_STATUS
send_per_roam_config_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_per_roam_config_req * req_buf)5755 send_per_roam_config_cmd_tlv(wmi_unified_t wmi_handle,
5756 struct wlan_per_roam_config_req *req_buf)
5757 {
5758 wmi_buf_t buf = NULL;
5759 QDF_STATUS status;
5760 int len;
5761 uint8_t *buf_ptr;
5762 wmi_roam_per_config_fixed_param *wmi_per_config;
5763
5764 len = sizeof(wmi_roam_per_config_fixed_param);
5765 buf = wmi_buf_alloc(wmi_handle, len);
5766 if (!buf)
5767 return QDF_STATUS_E_NOMEM;
5768
5769 buf_ptr = (uint8_t *)wmi_buf_data(buf);
5770 wmi_per_config =
5771 (wmi_roam_per_config_fixed_param *)buf_ptr;
5772 WMITLV_SET_HDR(&wmi_per_config->tlv_header,
5773 WMITLV_TAG_STRUC_wmi_roam_per_config_fixed_param,
5774 WMITLV_GET_STRUCT_TLVLEN
5775 (wmi_roam_per_config_fixed_param));
5776
5777 /* fill in per roam config values */
5778 wmi_per_config->vdev_id = req_buf->vdev_id;
5779
5780 wmi_per_config->enable = req_buf->per_config.enable;
5781 wmi_per_config->high_rate_thresh =
5782 (req_buf->per_config.tx_high_rate_thresh << 16) |
5783 (req_buf->per_config.rx_high_rate_thresh & 0x0000ffff);
5784 wmi_per_config->low_rate_thresh =
5785 (req_buf->per_config.tx_low_rate_thresh << 16) |
5786 (req_buf->per_config.rx_low_rate_thresh & 0x0000ffff);
5787 wmi_per_config->pkt_err_rate_thresh_pct =
5788 (req_buf->per_config.tx_rate_thresh_percnt << 16) |
5789 (req_buf->per_config.rx_rate_thresh_percnt & 0x0000ffff);
5790 wmi_per_config->per_rest_time = req_buf->per_config.per_rest_time;
5791 wmi_per_config->pkt_err_rate_mon_time =
5792 (req_buf->per_config.tx_per_mon_time << 16) |
5793 (req_buf->per_config.rx_per_mon_time & 0x0000ffff);
5794 wmi_per_config->min_candidate_rssi =
5795 req_buf->per_config.min_candidate_rssi;
5796
5797 /* Send per roam config parameters */
5798 wmi_mtrace(WMI_ROAM_PER_CONFIG_CMDID, NO_SESSION, 0);
5799 status = wmi_unified_cmd_send(wmi_handle, buf,
5800 len, WMI_ROAM_PER_CONFIG_CMDID);
5801 if (QDF_IS_STATUS_ERROR(status)) {
5802 wmi_err("WMI_ROAM_PER_CONFIG_CMDID failed, Error %d", status);
5803 wmi_buf_free(buf);
5804 return status;
5805 }
5806 wmi_debug("per roam enable=%d, vdev=%d",
5807 req_buf->per_config.enable, req_buf->vdev_id);
5808
5809 return QDF_STATUS_SUCCESS;
5810 }
5811
5812 /**
5813 * send_limit_off_chan_cmd_tlv() - send wmi cmd of limit off chan
5814 * configuration params
5815 * @wmi_handle: wmi handler
5816 * @limit_off_chan_param: pointer to wmi_off_chan_param
5817 *
5818 * Return: 0 for success and non zero for failure
5819 */
send_limit_off_chan_cmd_tlv(wmi_unified_t wmi_handle,struct wmi_limit_off_chan_param * limit_off_chan_param)5820 static QDF_STATUS send_limit_off_chan_cmd_tlv(
5821 wmi_unified_t wmi_handle,
5822 struct wmi_limit_off_chan_param *limit_off_chan_param)
5823 {
5824 wmi_vdev_limit_offchan_cmd_fixed_param *cmd;
5825 wmi_buf_t buf;
5826 uint32_t len = sizeof(*cmd);
5827 int err;
5828
5829 buf = wmi_buf_alloc(wmi_handle, len);
5830 if (!buf)
5831 return QDF_STATUS_E_NOMEM;
5832
5833 cmd = (wmi_vdev_limit_offchan_cmd_fixed_param *)wmi_buf_data(buf);
5834
5835 WMITLV_SET_HDR(&cmd->tlv_header,
5836 WMITLV_TAG_STRUC_wmi_vdev_limit_offchan_cmd_fixed_param,
5837 WMITLV_GET_STRUCT_TLVLEN(
5838 wmi_vdev_limit_offchan_cmd_fixed_param));
5839
5840 cmd->vdev_id = limit_off_chan_param->vdev_id;
5841
5842 cmd->flags &= 0;
5843 if (limit_off_chan_param->status)
5844 cmd->flags |= WMI_VDEV_LIMIT_OFFCHAN_ENABLE;
5845 if (limit_off_chan_param->skip_dfs_chans)
5846 cmd->flags |= WMI_VDEV_LIMIT_OFFCHAN_SKIP_DFS;
5847
5848 cmd->max_offchan_time = limit_off_chan_param->max_offchan_time;
5849 cmd->rest_time = limit_off_chan_param->rest_time;
5850
5851 wmi_debug("vdev_id=%d, flags =%x, max_offchan_time=%d, rest_time=%d",
5852 cmd->vdev_id, cmd->flags, cmd->max_offchan_time,
5853 cmd->rest_time);
5854
5855 wmi_mtrace(WMI_VDEV_LIMIT_OFFCHAN_CMDID, cmd->vdev_id, 0);
5856 err = wmi_unified_cmd_send(wmi_handle, buf,
5857 len, WMI_VDEV_LIMIT_OFFCHAN_CMDID);
5858 if (QDF_IS_STATUS_ERROR(err)) {
5859 wmi_err("Failed to send limit off chan cmd err=%d", err);
5860 wmi_buf_free(buf);
5861 return QDF_STATUS_E_FAILURE;
5862 }
5863
5864 return QDF_STATUS_SUCCESS;
5865 }
5866
5867 #ifdef WLAN_FEATURE_FILS_SK
send_roam_scan_send_hlp_cmd_tlv(wmi_unified_t wmi_handle,struct hlp_params * params)5868 static QDF_STATUS send_roam_scan_send_hlp_cmd_tlv(wmi_unified_t wmi_handle,
5869 struct hlp_params *params)
5870 {
5871 uint32_t len;
5872 uint8_t *buf_ptr;
5873 wmi_buf_t buf = NULL;
5874 wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param *hlp_params;
5875
5876 len = sizeof(wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param);
5877 len += WMI_TLV_HDR_SIZE;
5878 len += qdf_roundup(params->hlp_ie_len, sizeof(uint32_t));
5879
5880 buf = wmi_buf_alloc(wmi_handle, len);
5881 if (!buf)
5882 return QDF_STATUS_E_NOMEM;
5883
5884 buf_ptr = (uint8_t *)wmi_buf_data(buf);
5885 hlp_params = (wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param *)buf_ptr;
5886 WMITLV_SET_HDR(&hlp_params->tlv_header,
5887 WMITLV_TAG_STRUC_wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param,
5888 WMITLV_GET_STRUCT_TLVLEN(
5889 wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param));
5890
5891 hlp_params->vdev_id = params->vdev_id;
5892 hlp_params->size = params->hlp_ie_len;
5893 hlp_params->pkt_type = WMI_FILS_HLP_PKT_TYPE_DHCP_DISCOVER;
5894
5895 buf_ptr += sizeof(*hlp_params);
5896
5897 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
5898 round_up(params->hlp_ie_len, sizeof(uint32_t)));
5899
5900 buf_ptr += WMI_TLV_HDR_SIZE;
5901 qdf_mem_copy(buf_ptr, params->hlp_ie, params->hlp_ie_len);
5902
5903 wmi_debug("send FILS HLP pkt vdev %d len %d",
5904 hlp_params->vdev_id, hlp_params->size);
5905 wmi_mtrace(WMI_PDEV_UPDATE_FILS_HLP_PKT_CMDID, NO_SESSION, 0);
5906 if (wmi_unified_cmd_send(wmi_handle, buf, len,
5907 WMI_PDEV_UPDATE_FILS_HLP_PKT_CMDID)) {
5908 wmi_err("Failed to send FILS HLP pkt cmd");
5909 wmi_buf_free(buf);
5910 return QDF_STATUS_E_FAILURE;
5911 }
5912
5913 return QDF_STATUS_SUCCESS;
5914 }
5915
wmi_fils_sk_attach_tlv(wmi_unified_t wmi_handle)5916 void wmi_fils_sk_attach_tlv(wmi_unified_t wmi_handle)
5917 {
5918 struct wmi_ops *ops = wmi_handle->ops;
5919
5920 ops->send_roam_scan_hlp_cmd = send_roam_scan_send_hlp_cmd_tlv;
5921 }
5922 #endif /* WLAN_FEATURE_FILS_SK */
5923
5924 /*
5925 * send_btm_config_cmd_tlv() - Send wmi cmd for BTM config
5926 * @wmi_handle: wmi handle
5927 * @params: pointer to wlan_roam_btm_config
5928 *
5929 * Return: QDF_STATUS
5930 */
send_btm_config_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_roam_btm_config * params)5931 static QDF_STATUS send_btm_config_cmd_tlv(wmi_unified_t wmi_handle,
5932 struct wlan_roam_btm_config *params)
5933 {
5934 wmi_btm_config_fixed_param *cmd;
5935 wmi_buf_t buf;
5936 uint32_t len;
5937
5938 len = sizeof(*cmd);
5939 buf = wmi_buf_alloc(wmi_handle, len);
5940 if (!buf)
5941 return QDF_STATUS_E_NOMEM;
5942
5943 cmd = (wmi_btm_config_fixed_param *)wmi_buf_data(buf);
5944 WMITLV_SET_HDR(&cmd->tlv_header,
5945 WMITLV_TAG_STRUC_wmi_btm_config_fixed_param,
5946 WMITLV_GET_STRUCT_TLVLEN(wmi_btm_config_fixed_param));
5947 cmd->vdev_id = params->vdev_id;
5948 cmd->flags = params->btm_offload_config;
5949 cmd->max_attempt_cnt = params->btm_max_attempt_cnt;
5950 cmd->solicited_timeout_ms = params->btm_solicited_timeout;
5951 cmd->stick_time_seconds = params->btm_sticky_time;
5952 cmd->disassoc_timer_threshold = params->disassoc_timer_threshold;
5953 cmd->btm_bitmap = params->btm_query_bitmask;
5954 cmd->btm_candidate_min_score = params->btm_candidate_min_score;
5955
5956 wmi_debug("RSO_CFG: vdev_id:%u btm_offload:%u btm_query_bitmask:%u btm_candidate_min_score:%u",
5957 cmd->vdev_id, cmd->flags, cmd->btm_bitmap,
5958 cmd->btm_candidate_min_score);
5959 wmi_debug("RSO_CFG: btm_solicited_timeout:%u btm_max_attempt_cnt:%u btm_sticky_time:%u disassoc_timer_threshold:%u",
5960 cmd->solicited_timeout_ms, cmd->max_attempt_cnt,
5961 cmd->stick_time_seconds, cmd->disassoc_timer_threshold);
5962
5963 wmi_mtrace(WMI_ROAM_BTM_CONFIG_CMDID, cmd->vdev_id, 0);
5964 if (wmi_unified_cmd_send(wmi_handle, buf, len,
5965 WMI_ROAM_BTM_CONFIG_CMDID)) {
5966 wmi_err("Failed to send WMI_ROAM_BTM_CONFIG_CMDID");
5967 wmi_buf_free(buf);
5968 return QDF_STATUS_E_FAILURE;
5969 }
5970
5971 return QDF_STATUS_SUCCESS;
5972 }
5973
5974 /**
5975 * send_roam_bss_load_config_tlv() - send roam load bss trigger configuration
5976 * @wmi_handle: wmi handle
5977 * @params: pointer to wlan_roam_bss_load_config
5978 *
5979 * This function sends the roam load bss trigger configuration to fw.
5980 * the bss_load_threshold parameter is used to configure the maximum
5981 * bss load percentage, above which the firmware should trigger roaming
5982 *
5983 * Return: QDF status
5984 */
5985 static QDF_STATUS
send_roam_bss_load_config_tlv(wmi_unified_t wmi_handle,struct wlan_roam_bss_load_config * params)5986 send_roam_bss_load_config_tlv(wmi_unified_t wmi_handle,
5987 struct wlan_roam_bss_load_config *params)
5988 {
5989 wmi_roam_bss_load_config_cmd_fixed_param *cmd;
5990 wmi_buf_t buf;
5991 uint32_t len;
5992
5993 len = sizeof(*cmd);
5994 buf = wmi_buf_alloc(wmi_handle, len);
5995 if (!buf)
5996 return QDF_STATUS_E_NOMEM;
5997
5998 cmd = (wmi_roam_bss_load_config_cmd_fixed_param *)wmi_buf_data(buf);
5999 WMITLV_SET_HDR(
6000 &cmd->tlv_header,
6001 WMITLV_TAG_STRUC_wmi_roam_bss_load_config_cmd_fixed_param,
6002 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_bss_load_config_cmd_fixed_param));
6003
6004 cmd->vdev_id = params->vdev_id;
6005 cmd->bss_load_threshold = params->bss_load_threshold;
6006 cmd->monitor_time_window = params->bss_load_sample_time;
6007 cmd->rssi_2g_threshold = params->rssi_threshold_24ghz;
6008 cmd->rssi_5g_threshold = params->rssi_threshold_5ghz;
6009 cmd->rssi_6g_threshold = params->rssi_threshold_6ghz;
6010
6011 wmi_debug("RSO_CFG: vdev:%d bss_load_thres:%d monitor_time:%d rssi_2g:%d rssi_5g:%d, rssi_6g:%d",
6012 cmd->vdev_id, cmd->bss_load_threshold,
6013 cmd->monitor_time_window, cmd->rssi_2g_threshold,
6014 cmd->rssi_5g_threshold, cmd->rssi_6g_threshold);
6015
6016 wmi_mtrace(WMI_ROAM_BSS_LOAD_CONFIG_CMDID, cmd->vdev_id, 0);
6017 if (wmi_unified_cmd_send(wmi_handle, buf, len,
6018 WMI_ROAM_BSS_LOAD_CONFIG_CMDID)) {
6019 wmi_err("Failed to send WMI_ROAM_BSS_LOAD_CONFIG_CMDID");
6020 wmi_buf_free(buf);
6021 return QDF_STATUS_E_FAILURE;
6022 }
6023
6024 return QDF_STATUS_SUCCESS;
6025 }
6026
6027 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
6028 /**
6029 * send_disconnect_roam_params_tlv() - send disconnect roam trigger parameters
6030 * @wmi_handle: wmi handle
6031 * @req: pointer to wlan_roam_disconnect_params which carries the
6032 * disconnect_roam_trigger parameters
6033 *
6034 * This function sends the disconnect roam trigger parameters to fw.
6035 *
6036 * Return: QDF status
6037 */
6038 static QDF_STATUS
send_disconnect_roam_params_tlv(wmi_unified_t wmi_handle,struct wlan_roam_disconnect_params * req)6039 send_disconnect_roam_params_tlv(wmi_unified_t wmi_handle,
6040 struct wlan_roam_disconnect_params *req)
6041 {
6042 wmi_roam_deauth_config_cmd_fixed_param *cmd;
6043 wmi_buf_t buf;
6044 uint32_t len;
6045
6046 len = sizeof(*cmd);
6047 buf = wmi_buf_alloc(wmi_handle, len);
6048 if (!buf)
6049 return QDF_STATUS_E_NOMEM;
6050
6051 cmd = (wmi_roam_deauth_config_cmd_fixed_param *)wmi_buf_data(buf);
6052 WMITLV_SET_HDR(
6053 &cmd->tlv_header,
6054 WMITLV_TAG_STRUC_wmi_roam_deauth_config_cmd_fixed_param,
6055 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_deauth_config_cmd_fixed_param));
6056
6057 cmd->vdev_id = req->vdev_id;
6058 cmd->enable = req->enable;
6059 wmi_debug("RSO_CFG: vdev_id:%d enable:%d", cmd->vdev_id, cmd->enable);
6060
6061 wmi_mtrace(WMI_ROAM_DEAUTH_CONFIG_CMDID, cmd->vdev_id, 0);
6062 if (wmi_unified_cmd_send(wmi_handle, buf, len,
6063 WMI_ROAM_DEAUTH_CONFIG_CMDID)) {
6064 wmi_err("Failed to send WMI_ROAM_DEAUTH_CONFIG_CMDID");
6065 wmi_buf_free(buf);
6066 return QDF_STATUS_E_FAILURE;
6067 }
6068
6069 return QDF_STATUS_SUCCESS;
6070 }
6071
6072 #define WLAN_TIME_IN_MS 1000
6073 /**
6074 * send_idle_roam_params_tlv() - send idle roam trigger parameters
6075 * @wmi_handle: wmi handle
6076 * @idle_roam_params: pointer to wlan_roam_idle_params which carries the
6077 * idle roam parameters from CSR
6078 *
6079 * This function sends the idle roam trigger parameters to fw.
6080 *
6081 * Return: QDF status
6082 */
6083 static QDF_STATUS
send_idle_roam_params_tlv(wmi_unified_t wmi_handle,struct wlan_roam_idle_params * idle_roam_params)6084 send_idle_roam_params_tlv(wmi_unified_t wmi_handle,
6085 struct wlan_roam_idle_params *idle_roam_params)
6086 {
6087 wmi_roam_idle_config_cmd_fixed_param *cmd;
6088 wmi_buf_t buf;
6089 uint32_t len;
6090
6091 len = sizeof(*cmd);
6092 buf = wmi_buf_alloc(wmi_handle, len);
6093 if (!buf)
6094 return QDF_STATUS_E_NOMEM;
6095
6096 cmd = (wmi_roam_idle_config_cmd_fixed_param *)wmi_buf_data(buf);
6097 WMITLV_SET_HDR(
6098 &cmd->tlv_header,
6099 WMITLV_TAG_STRUC_wmi_roam_idle_config_cmd_fixed_param,
6100 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_idle_config_cmd_fixed_param));
6101
6102 cmd->vdev_id = idle_roam_params->vdev_id;
6103 cmd->enable = idle_roam_params->enable;
6104 cmd->band = idle_roam_params->band;
6105 cmd->rssi_delta = idle_roam_params->conn_ap_rssi_delta;
6106 cmd->min_rssi = idle_roam_params->conn_ap_min_rssi;
6107 cmd->idle_time = idle_roam_params->inactive_time / WLAN_TIME_IN_MS;
6108 cmd->data_packet_count = idle_roam_params->data_pkt_count;
6109 wmi_debug("RSO_CFG: vdev_id:%d enable:%d band:%d rssi_delta:%d min_rssi:%d idle_time:%d data_pkt:%d",
6110 cmd->vdev_id, cmd->enable,
6111 cmd->band, cmd->rssi_delta, cmd->min_rssi,
6112 cmd->idle_time, cmd->data_packet_count);
6113
6114 wmi_mtrace(WMI_ROAM_IDLE_CONFIG_CMDID, cmd->vdev_id, 0);
6115 if (wmi_unified_cmd_send(wmi_handle, buf, len,
6116 WMI_ROAM_IDLE_CONFIG_CMDID)) {
6117 wmi_err("Failed to send WMI_ROAM_IDLE_CONFIG_CMDID");
6118 wmi_buf_free(buf);
6119 return QDF_STATUS_E_FAILURE;
6120 }
6121
6122 return QDF_STATUS_SUCCESS;
6123 }
6124
6125 /**
6126 * send_roam_preauth_status_tlv() - send roam pre-authentication status
6127 * @wmi_handle: wmi handle
6128 * @params: pre-auth status params
6129 *
6130 * This function sends the roam pre-authentication status for WPA3 SAE
6131 * pre-auth to target.
6132 *
6133 * Return: QDF status
6134 */
6135 static QDF_STATUS
send_roam_preauth_status_tlv(wmi_unified_t wmi_handle,struct wmi_roam_auth_status_params * params)6136 send_roam_preauth_status_tlv(wmi_unified_t wmi_handle,
6137 struct wmi_roam_auth_status_params *params)
6138 {
6139 wmi_roam_preauth_status_cmd_fixed_param *cmd;
6140 wmi_buf_t buf;
6141 uint32_t len;
6142 uint8_t *buf_ptr;
6143
6144 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + PMKID_LEN;
6145 buf = wmi_buf_alloc(wmi_handle, len);
6146 if (!buf)
6147 return QDF_STATUS_E_NOMEM;
6148
6149 buf_ptr = (uint8_t *)wmi_buf_data(buf);
6150 cmd = (wmi_roam_preauth_status_cmd_fixed_param *)buf_ptr;
6151 WMITLV_SET_HDR(
6152 &cmd->tlv_header,
6153 WMITLV_TAG_STRUC_wmi_roam_preauth_status_cmd_fixed_param,
6154 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_preauth_status_cmd_fixed_param));
6155
6156 cmd->vdev_id = params->vdev_id;
6157 cmd->preauth_status = params->preauth_status;
6158 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssid.bytes,
6159 &cmd->candidate_ap_bssid);
6160
6161 buf_ptr += sizeof(wmi_roam_preauth_status_cmd_fixed_param);
6162 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, PMKID_LEN);
6163 buf_ptr += WMI_TLV_HDR_SIZE;
6164
6165 qdf_mem_copy(buf_ptr, params->pmkid, PMKID_LEN);
6166 wmi_debug("vdev_id:%d status:%d bssid:"QDF_MAC_ADDR_FMT,
6167 cmd->vdev_id, cmd->preauth_status,
6168 QDF_MAC_ADDR_REF(params->bssid.bytes));
6169
6170 wmi_mtrace(WMI_ROAM_PREAUTH_STATUS_CMDID, cmd->vdev_id, 0);
6171 if (wmi_unified_cmd_send(wmi_handle, buf, len,
6172 WMI_ROAM_PREAUTH_STATUS_CMDID)) {
6173 wmi_buf_free(buf);
6174 return QDF_STATUS_E_FAILURE;
6175 }
6176
6177 return QDF_STATUS_SUCCESS;
6178 }
6179 #else
6180 static inline QDF_STATUS
send_disconnect_roam_params_tlv(wmi_unified_t wmi_handle,struct wlan_roam_disconnect_params * req)6181 send_disconnect_roam_params_tlv(wmi_unified_t wmi_handle,
6182 struct wlan_roam_disconnect_params *req)
6183 {
6184 return QDF_STATUS_E_FAILURE;
6185 }
6186
6187 static inline QDF_STATUS
send_idle_roam_params_tlv(wmi_unified_t wmi_handle,struct wlan_roam_idle_params * idle_roam_params)6188 send_idle_roam_params_tlv(wmi_unified_t wmi_handle,
6189 struct wlan_roam_idle_params *idle_roam_params)
6190 {
6191 return QDF_STATUS_E_FAILURE;
6192 }
6193
6194 static inline QDF_STATUS
send_roam_preauth_status_tlv(wmi_unified_t wmi_handle,struct wmi_roam_auth_status_params * params)6195 send_roam_preauth_status_tlv(wmi_unified_t wmi_handle,
6196 struct wmi_roam_auth_status_params *params)
6197 {
6198 return QDF_STATUS_E_FAILURE;
6199 }
6200 #endif
6201
6202 /**
6203 * send_offload_11k_cmd_tlv() - send wmi cmd with 11k offload params
6204 * @wmi_handle: wmi handler
6205 * @params: pointer to 11k offload params
6206 *
6207 * Return: 0 for success and non zero for failure
6208 */
6209 static QDF_STATUS
send_offload_11k_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_roam_11k_offload_params * params)6210 send_offload_11k_cmd_tlv(wmi_unified_t wmi_handle,
6211 struct wlan_roam_11k_offload_params *params)
6212 {
6213 wmi_11k_offload_report_fixed_param *cmd;
6214 wmi_buf_t buf;
6215 QDF_STATUS status;
6216 uint8_t *buf_ptr;
6217 wmi_neighbor_report_11k_offload_tlv_param
6218 *neighbor_report_offload_params;
6219 wmi_neighbor_report_offload *neighbor_report_offload;
6220 uint32_t len = sizeof(*cmd);
6221
6222 if (params->offload_11k_bitmask &
6223 WMI_11K_OFFLOAD_BITMAP_NEIGHBOR_REPORT_REQ)
6224 len += WMI_TLV_HDR_SIZE +
6225 sizeof(wmi_neighbor_report_11k_offload_tlv_param);
6226
6227 buf = wmi_buf_alloc(wmi_handle, len);
6228 if (!buf)
6229 return QDF_STATUS_E_NOMEM;
6230
6231 buf_ptr = (uint8_t *)wmi_buf_data(buf);
6232 cmd = (wmi_11k_offload_report_fixed_param *)buf_ptr;
6233
6234 WMITLV_SET_HDR(&cmd->tlv_header,
6235 WMITLV_TAG_STRUC_wmi_offload_11k_report_fixed_param,
6236 WMITLV_GET_STRUCT_TLVLEN(
6237 wmi_11k_offload_report_fixed_param));
6238
6239 cmd->vdev_id = params->vdev_id;
6240 cmd->offload_11k = params->offload_11k_bitmask;
6241
6242 if (params->offload_11k_bitmask &
6243 WMI_11K_OFFLOAD_BITMAP_NEIGHBOR_REPORT_REQ) {
6244 buf_ptr += sizeof(wmi_11k_offload_report_fixed_param);
6245
6246 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
6247 sizeof(wmi_neighbor_report_11k_offload_tlv_param));
6248 buf_ptr += WMI_TLV_HDR_SIZE;
6249
6250 neighbor_report_offload_params =
6251 (wmi_neighbor_report_11k_offload_tlv_param *)buf_ptr;
6252 WMITLV_SET_HDR(&neighbor_report_offload_params->tlv_header,
6253 WMITLV_TAG_STRUC_wmi_neighbor_report_offload_tlv_param,
6254 WMITLV_GET_STRUCT_TLVLEN(
6255 wmi_neighbor_report_11k_offload_tlv_param));
6256
6257 neighbor_report_offload = &neighbor_report_offload_params->
6258 neighbor_rep_ofld_params;
6259
6260 neighbor_report_offload->time_offset =
6261 params->neighbor_report_params.time_offset;
6262 neighbor_report_offload->low_rssi_offset =
6263 params->neighbor_report_params.low_rssi_offset;
6264 neighbor_report_offload->bmiss_count_trigger =
6265 params->neighbor_report_params.bmiss_count_trigger;
6266 neighbor_report_offload->per_threshold_offset =
6267 params->neighbor_report_params.per_threshold_offset;
6268 neighbor_report_offload->neighbor_report_cache_timeout =
6269 params->neighbor_report_params.
6270 neighbor_report_cache_timeout;
6271 neighbor_report_offload->max_neighbor_report_req_cap =
6272 params->neighbor_report_params.
6273 max_neighbor_report_req_cap;
6274 neighbor_report_offload->ssid.ssid_len =
6275 params->neighbor_report_params.ssid.length;
6276 qdf_mem_copy(neighbor_report_offload->ssid.ssid,
6277 ¶ms->neighbor_report_params.ssid.ssid,
6278 neighbor_report_offload->ssid.ssid_len);
6279 }
6280
6281 wmi_debug("RSO_CFG: vdev %d 11k_bitmask:%u time_offset:%u low_rssi_offset:%u bmiss_count_trigger:%u per_threshold_offset%u",
6282 cmd->vdev_id, params->offload_11k_bitmask,
6283 params->neighbor_report_params.time_offset,
6284 params->neighbor_report_params.low_rssi_offset,
6285 params->neighbor_report_params.bmiss_count_trigger,
6286 params->neighbor_report_params.per_threshold_offset);
6287 wmi_debug("RSO_CFG: neighbor_report_cache_timeout:%u max_neighbor_report_req_cap:%u SSID:" QDF_SSID_FMT,
6288 params->neighbor_report_params.neighbor_report_cache_timeout,
6289 params->neighbor_report_params.max_neighbor_report_req_cap,
6290 QDF_SSID_REF(params->neighbor_report_params.ssid.length,
6291 params->neighbor_report_params.ssid.ssid));
6292
6293 wmi_mtrace(WMI_11K_OFFLOAD_REPORT_CMDID, cmd->vdev_id, 0);
6294 status = wmi_unified_cmd_send(wmi_handle, buf, len,
6295 WMI_11K_OFFLOAD_REPORT_CMDID);
6296 if (status != QDF_STATUS_SUCCESS) {
6297 wmi_err("Failed to send 11k offload command %d", status);
6298 wmi_buf_free(buf);
6299 }
6300
6301 return status;
6302 }
6303
6304 /**
6305 * send_invoke_neighbor_report_cmd_tlv() - send invoke 11k neighbor report
6306 * command
6307 * @wmi_handle: wmi handler
6308 * @params: pointer to neighbor report invoke params
6309 *
6310 * Return: 0 for success and non zero for failure
6311 */
send_invoke_neighbor_report_cmd_tlv(wmi_unified_t wmi_handle,struct wmi_invoke_neighbor_report_params * params)6312 static QDF_STATUS send_invoke_neighbor_report_cmd_tlv(
6313 wmi_unified_t wmi_handle,
6314 struct wmi_invoke_neighbor_report_params *params)
6315 {
6316 wmi_11k_offload_invoke_neighbor_report_fixed_param *cmd;
6317 wmi_buf_t buf;
6318 QDF_STATUS status;
6319 uint8_t *buf_ptr;
6320 uint32_t len = sizeof(*cmd);
6321
6322 buf = wmi_buf_alloc(wmi_handle, len);
6323 if (!buf)
6324 return QDF_STATUS_E_NOMEM;
6325
6326 buf_ptr = (uint8_t *)wmi_buf_data(buf);
6327 cmd = (wmi_11k_offload_invoke_neighbor_report_fixed_param *)buf_ptr;
6328
6329 WMITLV_SET_HDR(&cmd->tlv_header,
6330 WMITLV_TAG_STRUC_wmi_invoke_neighbor_report_fixed_param,
6331 WMITLV_GET_STRUCT_TLVLEN(
6332 wmi_11k_offload_invoke_neighbor_report_fixed_param));
6333
6334 cmd->vdev_id = params->vdev_id;
6335 cmd->flags = params->send_resp_to_host;
6336
6337 cmd->ssid.ssid_len = params->ssid.length;
6338 qdf_mem_copy(cmd->ssid.ssid, ¶ms->ssid.ssid, cmd->ssid.ssid_len);
6339
6340 wmi_mtrace(WMI_11K_INVOKE_NEIGHBOR_REPORT_CMDID, cmd->vdev_id, 0);
6341 status = wmi_unified_cmd_send(wmi_handle, buf, len,
6342 WMI_11K_INVOKE_NEIGHBOR_REPORT_CMDID);
6343 if (status != QDF_STATUS_SUCCESS) {
6344 wmi_err("Failed to send invoke neighbor report command %d",
6345 status);
6346 wmi_buf_free(buf);
6347 }
6348
6349 return status;
6350 }
6351
wmi_roam_attach_tlv(wmi_unified_t wmi_handle)6352 void wmi_roam_attach_tlv(wmi_unified_t wmi_handle)
6353 {
6354 struct wmi_ops *ops = wmi_handle->ops;
6355
6356 ops->send_roam_scan_offload_rssi_thresh_cmd =
6357 send_roam_scan_offload_rssi_thresh_cmd_tlv;
6358 ops->send_roam_mawc_params_cmd = send_roam_mawc_params_cmd_tlv;
6359 ops->send_roam_scan_filter_cmd =
6360 send_roam_scan_filter_cmd_tlv;
6361 ops->send_roam_scan_offload_mode_cmd =
6362 send_roam_scan_offload_mode_cmd_tlv;
6363 ops->send_roam_scan_offload_ap_profile_cmd =
6364 send_roam_scan_offload_ap_profile_cmd_tlv;
6365 ops->send_roam_scan_offload_cmd = send_roam_scan_offload_cmd_tlv;
6366 ops->send_roam_scan_offload_scan_period_cmd =
6367 send_roam_scan_offload_scan_period_cmd_tlv;
6368 ops->send_roam_scan_offload_chan_list_cmd =
6369 send_roam_scan_offload_chan_list_cmd_tlv;
6370 ops->send_roam_scan_offload_rssi_change_cmd =
6371 send_roam_scan_offload_rssi_change_cmd_tlv;
6372 ops->send_per_roam_config_cmd = send_per_roam_config_cmd_tlv;
6373 ops->send_limit_off_chan_cmd = send_limit_off_chan_cmd_tlv;
6374 ops->send_btm_config = send_btm_config_cmd_tlv;
6375 ops->send_offload_11k_cmd = send_offload_11k_cmd_tlv;
6376 ops->send_invoke_neighbor_report_cmd =
6377 send_invoke_neighbor_report_cmd_tlv;
6378 ops->send_roam_bss_load_config = send_roam_bss_load_config_tlv;
6379 ops->send_idle_roam_params = send_idle_roam_params_tlv;
6380 ops->send_disconnect_roam_params = send_disconnect_roam_params_tlv;
6381 ops->send_roam_preauth_status = send_roam_preauth_status_tlv;
6382 ops->extract_roam_event = extract_roam_event_tlv;
6383
6384 wmi_roam_mlo_attach_tlv(wmi_handle);
6385 wmi_lfr_subnet_detection_attach_tlv(wmi_handle);
6386 wmi_rssi_monitor_attach_tlv(wmi_handle);
6387 wmi_ese_attach_tlv(wmi_handle);
6388 wmi_roam_offload_attach_tlv(wmi_handle);
6389 wmi_fils_sk_attach_tlv(wmi_handle);
6390 }
6391