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 = &param_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 = &param_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 = &param_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 = &param_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(&params->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 			     &params->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, &params->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