xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_extscan_tlv.c (revision 77a23e8f71c7ca7f65185b02d0511610d22e9d61)
1 /*
2  * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <osdep.h>
20 #include "wmi.h"
21 #include "wmi_unified_priv.h"
22 
23 /**
24  * send_reset_passpoint_network_list_cmd_tlv() - reset passpoint network list
25  * @wmi_handle: wmi handle
26  * @req: passpoint network request structure
27  *
28  * This function sends down WMI command with network id set to wildcard id.
29  * firmware shall clear all the config entries
30  *
31  * Return: QDF_STATUS enumeration
32  */
33 static QDF_STATUS send_reset_passpoint_network_list_cmd_tlv
34 					(wmi_unified_t wmi_handle,
35 					struct wifi_passpoint_req_param *req)
36 {
37 	wmi_passpoint_config_cmd_fixed_param *cmd;
38 	wmi_buf_t buf;
39 	uint32_t len;
40 	int ret;
41 
42 	len = sizeof(*cmd);
43 	buf = wmi_buf_alloc(wmi_handle, len);
44 	if (!buf) {
45 		wmi_err("Failed allocate wmi buffer");
46 		return QDF_STATUS_E_NOMEM;
47 	}
48 
49 	cmd = (wmi_passpoint_config_cmd_fixed_param *) wmi_buf_data(buf);
50 
51 	WMITLV_SET_HDR(&cmd->tlv_header,
52 			WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param,
53 			WMITLV_GET_STRUCT_TLVLEN(
54 			wmi_passpoint_config_cmd_fixed_param));
55 	cmd->id = WMI_PASSPOINT_NETWORK_ID_WILDCARD;
56 
57 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
58 				   WMI_PASSPOINT_LIST_CONFIG_CMDID);
59 	if (ret) {
60 		wmi_err("Failed to send reset passpoint network list wmi cmd");
61 		wmi_buf_free(buf);
62 		return QDF_STATUS_E_FAILURE;
63 	}
64 
65 	return QDF_STATUS_SUCCESS;
66 }
67 
68 /**
69  * send_set_passpoint_network_list_cmd_tlv() - set passpoint network list
70  * @wmi_handle: wmi handle
71  * @req: passpoint network request structure
72  *
73  * This function reads the incoming @req and fill in the destination
74  * WMI structure and send down the passpoint configs down to the firmware
75  *
76  * Return: QDF_STATUS enumeration
77  */
78 static QDF_STATUS send_set_passpoint_network_list_cmd_tlv
79 					(wmi_unified_t wmi_handle,
80 					struct wifi_passpoint_req_param *req)
81 {
82 	wmi_passpoint_config_cmd_fixed_param *cmd;
83 	u_int8_t i, j, *bytes;
84 	wmi_buf_t buf;
85 	uint32_t len;
86 	int ret;
87 
88 	len = sizeof(*cmd);
89 	for (i = 0; i < req->num_networks; i++) {
90 		buf = wmi_buf_alloc(wmi_handle, len);
91 		if (!buf) {
92 			wmi_err("Failed allocate wmi buffer");
93 			return QDF_STATUS_E_NOMEM;
94 		}
95 
96 		cmd = (wmi_passpoint_config_cmd_fixed_param *)
97 				wmi_buf_data(buf);
98 
99 		WMITLV_SET_HDR(&cmd->tlv_header,
100 			WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param,
101 			WMITLV_GET_STRUCT_TLVLEN(
102 			wmi_passpoint_config_cmd_fixed_param));
103 		cmd->id = req->networks[i].id;
104 		wmi_debug("network id: %u", cmd->id);
105 		qdf_mem_copy(cmd->realm, req->networks[i].realm,
106 			strlen(req->networks[i].realm) + 1);
107 		wmi_debug("realm: %s", cmd->realm);
108 		for (j = 0; j < PASSPOINT_ROAMING_CONSORTIUM_ID_NUM; j++) {
109 			bytes = (uint8_t *) &req->networks[i].roaming_consortium_ids[j];
110 			wmi_debug("index: %d rcids: %02x %02x %02x %02x %02x %02x %02x %02x",
111 				j, bytes[0], bytes[1], bytes[2], bytes[3],
112 				bytes[4], bytes[5], bytes[6], bytes[7]);
113 
114 			qdf_mem_copy(&cmd->roaming_consortium_ids[j],
115 				&req->networks[i].roaming_consortium_ids[j],
116 				PASSPOINT_ROAMING_CONSORTIUM_ID_LEN);
117 		}
118 		qdf_mem_copy(cmd->plmn, req->networks[i].plmn,
119 				PASSPOINT_PLMN_ID_LEN);
120 		wmi_debug("plmn: %02x:%02x:%02x",
121 			 cmd->plmn[0], cmd->plmn[1], cmd->plmn[2]);
122 
123 		ret = wmi_unified_cmd_send(wmi_handle, buf, len,
124 					   WMI_PASSPOINT_LIST_CONFIG_CMDID);
125 		if (ret) {
126 			wmi_err("Failed to send set passpoint network list wmi cmd");
127 			wmi_buf_free(buf);
128 			return QDF_STATUS_E_FAILURE;
129 		}
130 	}
131 
132 	return QDF_STATUS_SUCCESS;
133 }
134 
135 /** send_set_epno_network_list_cmd_tlv() - set epno network list
136  * @wmi_handle: wmi handle
137  * @req: epno config params request structure
138  *
139  * This function reads the incoming epno config request structure
140  * and constructs the WMI message to the firmware.
141  *
142  * Returns: 0 on success, error number otherwise
143  */
144 static QDF_STATUS send_set_epno_network_list_cmd_tlv(wmi_unified_t wmi_handle,
145 		struct wifi_enhanced_pno_params *req)
146 {
147 	wmi_nlo_config_cmd_fixed_param *cmd;
148 	nlo_configured_parameters *nlo_list;
149 	enlo_candidate_score_params *cand_score_params;
150 	u_int8_t i, *buf_ptr;
151 	wmi_buf_t buf;
152 	uint32_t len;
153 	QDF_STATUS ret;
154 
155 	/* Fixed Params */
156 	len = sizeof(*cmd);
157 	if (req->num_networks) {
158 		/* TLV place holder for array of structures
159 		 * then each nlo_configured_parameters(nlo_list) TLV.
160 		 */
161 		len += WMI_TLV_HDR_SIZE;
162 		len += (sizeof(nlo_configured_parameters)
163 			    * QDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS));
164 		/* TLV for array of uint32 channel_list */
165 		len += WMI_TLV_HDR_SIZE;
166 		/* TLV for nlo_channel_prediction_cfg */
167 		len += WMI_TLV_HDR_SIZE;
168 		/* TLV for candidate score params */
169 		len += sizeof(enlo_candidate_score_params);
170 	}
171 
172 	buf = wmi_buf_alloc(wmi_handle, len);
173 	if (!buf) {
174 		wmi_err("Failed allocate wmi buffer");
175 		return QDF_STATUS_E_NOMEM;
176 	}
177 
178 	cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf);
179 
180 	buf_ptr = (u_int8_t *) cmd;
181 	WMITLV_SET_HDR(&cmd->tlv_header,
182 		       WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param,
183 		       WMITLV_GET_STRUCT_TLVLEN(
184 			       wmi_nlo_config_cmd_fixed_param));
185 	cmd->vdev_id = req->vdev_id;
186 
187 	/* set flag to reset if num of networks are 0 */
188 	cmd->flags = (req->num_networks == 0 ?
189 		WMI_NLO_CONFIG_ENLO_RESET : WMI_NLO_CONFIG_ENLO);
190 
191 	buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param);
192 
193 	cmd->no_of_ssids = QDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS);
194 	wmi_debug("SSID count: %d flags: %d",
195 		 cmd->no_of_ssids, cmd->flags);
196 
197 	/* Fill nlo_config only when num_networks are non zero */
198 	if (cmd->no_of_ssids) {
199 		/* Fill networks */
200 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
201 			cmd->no_of_ssids * sizeof(nlo_configured_parameters));
202 		buf_ptr += WMI_TLV_HDR_SIZE;
203 
204 		nlo_list = (nlo_configured_parameters *) buf_ptr;
205 		for (i = 0; i < cmd->no_of_ssids; i++) {
206 			WMITLV_SET_HDR(&nlo_list[i].tlv_header,
207 				WMITLV_TAG_ARRAY_BYTE,
208 				WMITLV_GET_STRUCT_TLVLEN(
209 				nlo_configured_parameters));
210 			/* Copy ssid and it's length */
211 			nlo_list[i].ssid.valid = true;
212 			nlo_list[i].ssid.ssid.ssid_len =
213 				req->networks[i].ssid.length;
214 			qdf_mem_copy(nlo_list[i].ssid.ssid.ssid,
215 				     req->networks[i].ssid.ssid,
216 				     nlo_list[i].ssid.ssid.ssid_len);
217 			wmi_debug("index: %d ssid: %.*s len: %d", i,
218 				 nlo_list[i].ssid.ssid.ssid_len,
219 				 (char *) nlo_list[i].ssid.ssid.ssid,
220 				 nlo_list[i].ssid.ssid.ssid_len);
221 
222 			/* Copy pno flags */
223 			nlo_list[i].bcast_nw_type.valid = true;
224 			nlo_list[i].bcast_nw_type.bcast_nw_type =
225 					req->networks[i].flags;
226 			wmi_debug("PNO flags: %u",
227 				 nlo_list[i].bcast_nw_type.bcast_nw_type);
228 
229 			/* Copy auth bit field */
230 			nlo_list[i].auth_type.valid = true;
231 			nlo_list[i].auth_type.auth_type =
232 					req->networks[i].auth_bit_field;
233 			wmi_debug("Auth bit field: %u",
234 				 nlo_list[i].auth_type.auth_type);
235 		}
236 
237 		buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters);
238 		/* Fill the channel list */
239 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
240 		buf_ptr += WMI_TLV_HDR_SIZE;
241 
242 		/* Fill prediction_param */
243 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
244 		buf_ptr += WMI_TLV_HDR_SIZE;
245 
246 		/* Fill epno candidate score params */
247 		cand_score_params = (enlo_candidate_score_params *) buf_ptr;
248 		WMITLV_SET_HDR(buf_ptr,
249 			WMITLV_TAG_STRUC_enlo_candidate_score_param,
250 			WMITLV_GET_STRUCT_TLVLEN(enlo_candidate_score_params));
251 		cand_score_params->min5GHz_rssi =
252 			req->min_5ghz_rssi;
253 		cand_score_params->min24GHz_rssi =
254 			req->min_24ghz_rssi;
255 		cand_score_params->initial_score_max =
256 			req->initial_score_max;
257 		cand_score_params->current_connection_bonus =
258 			req->current_connection_bonus;
259 		cand_score_params->same_network_bonus =
260 			req->same_network_bonus;
261 		cand_score_params->secure_bonus =
262 			req->secure_bonus;
263 		cand_score_params->band5GHz_bonus =
264 			req->band_5ghz_bonus;
265 		buf_ptr += sizeof(enlo_candidate_score_params);
266 	}
267 
268 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
269 			WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
270 	if (QDF_IS_STATUS_ERROR(ret)) {
271 		wmi_err("Failed to send nlo wmi cmd");
272 		wmi_buf_free(buf);
273 		return QDF_STATUS_E_INVAL;
274 	}
275 
276 	wmi_debug("set ePNO list request sent successfully for vdev %d",
277 		 req->vdev_id);
278 
279 	return ret;
280 }
281 
282 /**
283  * send_extscan_get_capabilities_cmd_tlv() - extscan get capabilities
284  * @wmi_handle: wmi handle
285  * @pgetcapab: get capabilities params
286  *
287  * This function send request to fw to get extscan capabilities.
288  *
289  * Return: CDF status
290  */
291 static QDF_STATUS send_extscan_get_capabilities_cmd_tlv(wmi_unified_t wmi_handle,
292 		    struct extscan_capabilities_params *pgetcapab)
293 {
294 	wmi_extscan_get_capabilities_cmd_fixed_param *cmd;
295 	wmi_buf_t wmi_buf;
296 	uint32_t len;
297 	uint8_t *buf_ptr;
298 
299 	len = sizeof(*cmd);
300 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
301 	if (!wmi_buf) {
302 		wmi_err("wmi_buf_alloc failed");
303 		return QDF_STATUS_E_NOMEM;
304 	}
305 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
306 
307 	cmd = (wmi_extscan_get_capabilities_cmd_fixed_param *) buf_ptr;
308 	WMITLV_SET_HDR(&cmd->tlv_header,
309 	       WMITLV_TAG_STRUC_wmi_extscan_get_capabilities_cmd_fixed_param,
310 	       WMITLV_GET_STRUCT_TLVLEN
311 	       (wmi_extscan_get_capabilities_cmd_fixed_param));
312 
313 	cmd->request_id = pgetcapab->request_id;
314 
315 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
316 				 WMI_EXTSCAN_GET_CAPABILITIES_CMDID)) {
317 		wmi_err("Failed to send extscan get capabilities cmd");
318 		wmi_buf_free(wmi_buf);
319 		return QDF_STATUS_E_FAILURE;
320 	}
321 	return QDF_STATUS_SUCCESS;
322 }
323 
324 /**
325  * send_extscan_get_cached_results_cmd_tlv() - extscan get cached results
326  * @wmi_handle: wmi handle
327  * @pcached_results: cached results parameters
328  *
329  * This function send request to fw to get cached results.
330  *
331  * Return: CDF status
332  */
333 static QDF_STATUS send_extscan_get_cached_results_cmd_tlv(wmi_unified_t wmi_handle,
334 		  struct extscan_cached_result_params *pcached_results)
335 {
336 	wmi_extscan_get_cached_results_cmd_fixed_param *cmd;
337 	wmi_buf_t wmi_buf;
338 	uint32_t len;
339 	uint8_t *buf_ptr;
340 
341 	len = sizeof(*cmd);
342 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
343 	if (!wmi_buf) {
344 		wmi_err("wmi_buf_alloc failed");
345 		return QDF_STATUS_E_NOMEM;
346 	}
347 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
348 
349 	cmd = (wmi_extscan_get_cached_results_cmd_fixed_param *) buf_ptr;
350 	WMITLV_SET_HDR(&cmd->tlv_header,
351 		WMITLV_TAG_STRUC_wmi_extscan_get_cached_results_cmd_fixed_param,
352 		WMITLV_GET_STRUCT_TLVLEN
353 		(wmi_extscan_get_cached_results_cmd_fixed_param));
354 
355 	cmd->request_id = pcached_results->request_id;
356 	cmd->vdev_id = pcached_results->vdev_id;
357 	cmd->control_flags = pcached_results->flush;
358 
359 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
360 				 WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID)) {
361 		wmi_err("failed to  command", __func__);
362 		wmi_buf_free(wmi_buf);
363 		return QDF_STATUS_E_FAILURE;
364 	}
365 	return QDF_STATUS_SUCCESS;
366 }
367 
368 /**
369  * send_extscan_stop_change_monitor_cmd_tlv() - send stop change monitor cmd
370  * @wmi_handle: wmi handle
371  * @reset_req: Reset change request params
372  *
373  * This function sends stop change monitor request to fw.
374  *
375  * Return: CDF status
376  */
377 static QDF_STATUS send_extscan_stop_change_monitor_cmd_tlv
378 			(wmi_unified_t wmi_handle,
379 			struct extscan_capabilities_reset_params *reset_req)
380 {
381 	wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd;
382 	wmi_buf_t wmi_buf;
383 	uint32_t len;
384 	uint8_t *buf_ptr;
385 	int change_list = 0;
386 
387 	len = sizeof(*cmd);
388 
389 	/* reset significant change tlv is set to 0 */
390 	len += WMI_TLV_HDR_SIZE;
391 	len += change_list * sizeof(wmi_extscan_wlan_change_bssid_param);
392 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
393 	if (!wmi_buf) {
394 		wmi_err("wmi_buf_alloc failed");
395 		return QDF_STATUS_E_NOMEM;
396 	}
397 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
398 
399 	cmd = (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)
400 		buf_ptr;
401 	WMITLV_SET_HDR(&cmd->tlv_header,
402 	WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param,
403 		WMITLV_GET_STRUCT_TLVLEN
404 		(wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param));
405 
406 	cmd->request_id = reset_req->request_id;
407 	cmd->vdev_id = reset_req->vdev_id;
408 	cmd->mode = 0;
409 
410 	buf_ptr += sizeof(*cmd);
411 	WMITLV_SET_HDR(buf_ptr,
412 		       WMITLV_TAG_ARRAY_STRUC,
413 		       change_list *
414 		       sizeof(wmi_extscan_wlan_change_bssid_param));
415 	buf_ptr += WMI_TLV_HDR_SIZE + (change_list *
416 				       sizeof
417 				       (wmi_extscan_wlan_change_bssid_param));
418 
419 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
420 			 WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) {
421 		wmi_err("Failed to send extscan change monitor cmd");
422 		wmi_buf_free(wmi_buf);
423 		return QDF_STATUS_E_FAILURE;
424 	}
425 	return QDF_STATUS_SUCCESS;
426 }
427 
428 /**
429  * wmi_get_buf_extscan_change_monitor_cmd() - fill change monitor request
430  * @wmi_handle: wmi handle
431  * @psigchange: change monitor request params
432  * @buf: wmi buffer
433  * @buf_len: buffer length
434  *
435  * This function fills elements of change monitor request buffer.
436  *
437  * Return: QDF status
438  */
439 static QDF_STATUS wmi_get_buf_extscan_change_monitor_cmd
440 			(wmi_unified_t wmi_handle,
441 			struct extscan_set_sig_changereq_params
442 			*psigchange, wmi_buf_t *buf, int *buf_len)
443 {
444 	wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd;
445 	wmi_extscan_wlan_change_bssid_param *dest_chglist;
446 	uint8_t *buf_ptr;
447 	int j;
448 	int len = sizeof(*cmd);
449 	uint32_t numap = psigchange->num_ap;
450 	struct ap_threshold_params *src_ap = psigchange->ap;
451 
452 	if (!numap || (numap > WMI_WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS)) {
453 		wmi_err("Invalid number of bssid's");
454 		return QDF_STATUS_E_INVAL;
455 	}
456 	len += WMI_TLV_HDR_SIZE;
457 	len += numap * sizeof(wmi_extscan_wlan_change_bssid_param);
458 
459 	*buf = wmi_buf_alloc(wmi_handle, len);
460 	if (!*buf) {
461 		wmi_err("Failed to allocate memory for change monitor cmd");
462 		return QDF_STATUS_E_FAILURE;
463 	}
464 	buf_ptr = (uint8_t *) wmi_buf_data(*buf);
465 	cmd =
466 		(wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)
467 		buf_ptr;
468 	WMITLV_SET_HDR(&cmd->tlv_header,
469 	WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param,
470 	       WMITLV_GET_STRUCT_TLVLEN
471 	       (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param));
472 
473 	cmd->request_id = psigchange->request_id;
474 	cmd->vdev_id = psigchange->vdev_id;
475 	cmd->total_entries = numap;
476 	cmd->mode = 1;
477 	cmd->num_entries_in_page = numap;
478 	cmd->lost_ap_scan_count = psigchange->lostap_sample_size;
479 	cmd->max_rssi_samples = psigchange->rssi_sample_size;
480 	cmd->rssi_averaging_samples = psigchange->rssi_sample_size;
481 	cmd->max_out_of_range_count = psigchange->min_breaching;
482 
483 	buf_ptr += sizeof(*cmd);
484 	WMITLV_SET_HDR(buf_ptr,
485 		       WMITLV_TAG_ARRAY_STRUC,
486 		       numap * sizeof(wmi_extscan_wlan_change_bssid_param));
487 	dest_chglist = (wmi_extscan_wlan_change_bssid_param *)
488 		       (buf_ptr + WMI_TLV_HDR_SIZE);
489 
490 	for (j = 0; j < numap; j++) {
491 		WMITLV_SET_HDR(dest_chglist,
492 		       WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
493 		       WMITLV_GET_STRUCT_TLVLEN
494 		       (wmi_extscan_wlan_change_bssid_param));
495 
496 		dest_chglist->lower_rssi_limit = src_ap->low;
497 		dest_chglist->upper_rssi_limit = src_ap->high;
498 		WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid.bytes,
499 					   &dest_chglist->bssid);
500 
501 		wmi_debug("min_rssi: %d", dest_chglist->lower_rssi_limit);
502 		dest_chglist++;
503 		src_ap++;
504 	}
505 	buf_ptr += WMI_TLV_HDR_SIZE +
506 		   (numap * sizeof(wmi_extscan_wlan_change_bssid_param));
507 	*buf_len = len;
508 	return QDF_STATUS_SUCCESS;
509 }
510 
511 /**
512  * send_extscan_start_change_monitor_cmd_tlv() - send start change monitor cmd
513  * @wmi_handle: wmi handle
514  * @psigchange: change monitor request params
515  *
516  * This function sends start change monitor request to fw.
517  *
518  * Return: CDF status
519  */
520 static QDF_STATUS send_extscan_start_change_monitor_cmd_tlv
521 			(wmi_unified_t wmi_handle,
522 			struct extscan_set_sig_changereq_params *
523 			psigchange)
524 {
525 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
526 	wmi_buf_t buf;
527 	int len;
528 
529 
530 	qdf_status = wmi_get_buf_extscan_change_monitor_cmd(wmi_handle,
531 			     psigchange, &buf,
532 			     &len);
533 	if (qdf_status != QDF_STATUS_SUCCESS) {
534 		wmi_err("Failed to get buffer for change monitor cmd");
535 		return QDF_STATUS_E_FAILURE;
536 	}
537 	if (!buf) {
538 		wmi_err("Failed to get buffer");
539 		return QDF_STATUS_E_FAILURE;
540 	}
541 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
542 		 WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) {
543 		wmi_err("Failed to send command");
544 		wmi_buf_free(buf);
545 		return QDF_STATUS_E_FAILURE;
546 	}
547 	return QDF_STATUS_SUCCESS;
548 }
549 
550 /**
551  * send_extscan_stop_hotlist_monitor_cmd_tlv() - stop hotlist monitor
552  * @wmi_handle: wmi handle
553  * @photlist_reset: hotlist reset params
554  *
555  * This function configures hotlist monitor to stop in fw.
556  *
557  * Return: CDF status
558  */
559 static QDF_STATUS send_extscan_stop_hotlist_monitor_cmd_tlv
560 		(wmi_unified_t wmi_handle,
561 		struct extscan_bssid_hotlist_reset_params *photlist_reset)
562 {
563 	wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd;
564 	wmi_buf_t wmi_buf;
565 	uint32_t len;
566 	uint8_t *buf_ptr;
567 	int hotlist_entries = 0;
568 
569 	len = sizeof(*cmd);
570 
571 	/* reset bssid hotlist with tlv set to 0 */
572 	len += WMI_TLV_HDR_SIZE;
573 	len += hotlist_entries * sizeof(wmi_extscan_hotlist_entry);
574 
575 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
576 	if (!wmi_buf) {
577 		wmi_err("wmi_buf_alloc failed");
578 		return QDF_STATUS_E_NOMEM;
579 	}
580 
581 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
582 	cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *)
583 	      buf_ptr;
584 	WMITLV_SET_HDR(&cmd->tlv_header,
585 	WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param,
586 	WMITLV_GET_STRUCT_TLVLEN
587 	(wmi_extscan_configure_hotlist_monitor_cmd_fixed_param));
588 
589 	cmd->request_id = photlist_reset->request_id;
590 	cmd->vdev_id = photlist_reset->vdev_id;
591 	cmd->mode = 0;
592 
593 	buf_ptr += sizeof(*cmd);
594 	WMITLV_SET_HDR(buf_ptr,
595 		       WMITLV_TAG_ARRAY_STRUC,
596 		       hotlist_entries * sizeof(wmi_extscan_hotlist_entry));
597 	buf_ptr += WMI_TLV_HDR_SIZE +
598 		   (hotlist_entries * sizeof(wmi_extscan_hotlist_entry));
599 
600 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
601 				WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) {
602 		wmi_err("Failed to send extscan cfg hotlist cmd");
603 		wmi_buf_free(wmi_buf);
604 		return QDF_STATUS_E_FAILURE;
605 	}
606 	return QDF_STATUS_SUCCESS;
607 }
608 
609 /**
610  * send_stop_extscan_cmd_tlv() - stop extscan command to fw.
611  * @wmi_handle: wmi handle
612  * @pstopcmd: stop scan command request params
613  *
614  * This function sends stop extscan request to fw.
615  *
616  * Return: CDF Status.
617  */
618 static QDF_STATUS send_stop_extscan_cmd_tlv(wmi_unified_t wmi_handle,
619 			  struct extscan_stop_req_params *pstopcmd)
620 {
621 	wmi_extscan_stop_cmd_fixed_param *cmd;
622 	wmi_buf_t wmi_buf;
623 	uint32_t len;
624 	uint8_t *buf_ptr;
625 
626 	len = sizeof(*cmd);
627 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
628 	if (!wmi_buf) {
629 		wmi_err("wmi_buf_alloc failed");
630 		return QDF_STATUS_E_NOMEM;
631 	}
632 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
633 	cmd = (wmi_extscan_stop_cmd_fixed_param *) buf_ptr;
634 	WMITLV_SET_HDR(&cmd->tlv_header,
635 		       WMITLV_TAG_STRUC_wmi_extscan_stop_cmd_fixed_param,
636 		       WMITLV_GET_STRUCT_TLVLEN
637 			       (wmi_extscan_stop_cmd_fixed_param));
638 
639 	cmd->request_id = pstopcmd->request_id;
640 	cmd->vdev_id = pstopcmd->vdev_id;
641 
642 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
643 				 WMI_EXTSCAN_STOP_CMDID)) {
644 		wmi_err("Failed to send extscan stop cmd");
645 		wmi_buf_free(wmi_buf);
646 		return QDF_STATUS_E_FAILURE;
647 	}
648 
649 	return QDF_STATUS_SUCCESS;
650 }
651 
652 /**
653  * wmi_get_buf_extscan_start_cmd() - Fill extscan start request
654  * @wmi_handle: wmi handle
655  * @pstart: scan command request params
656  * @buf: event buffer
657  * @buf_len: length of buffer
658  *
659  * This function fills individual elements of extscan request and
660  * TLV for buckets, channel list.
661  *
662  * Return: CDF Status.
663  */
664 static
665 QDF_STATUS wmi_get_buf_extscan_start_cmd(wmi_unified_t wmi_handle,
666 			 struct wifi_scan_cmd_req_params *pstart,
667 			 wmi_buf_t *buf, int *buf_len)
668 {
669 	wmi_extscan_start_cmd_fixed_param *cmd;
670 	wmi_extscan_bucket *dest_blist;
671 	wmi_extscan_bucket_channel *dest_clist;
672 	struct wifi_scan_bucket_params *src_bucket = pstart->buckets;
673 	struct wifi_scan_channelspec_params *src_channel = src_bucket->channels;
674 	struct wifi_scan_channelspec_params save_channel[WMI_WLAN_EXTSCAN_MAX_CHANNELS];
675 
676 	uint8_t *buf_ptr;
677 	int i, k, count = 0;
678 	int len = sizeof(*cmd);
679 	int nbuckets = pstart->num_buckets;
680 	int nchannels = 0;
681 
682 	/* These TLV's are are NULL by default */
683 	uint32_t ie_len_with_pad = 0;
684 	int num_ssid = 0;
685 	int num_bssid = 0;
686 	int ie_len = 0;
687 
688 	uint32_t base_period = pstart->base_period;
689 
690 	/* TLV placeholder for ssid_list (NULL) */
691 	len += WMI_TLV_HDR_SIZE;
692 	len += num_ssid * sizeof(wmi_ssid);
693 
694 	/* TLV placeholder for bssid_list (NULL) */
695 	len += WMI_TLV_HDR_SIZE;
696 	len += num_bssid * sizeof(wmi_mac_addr);
697 
698 	/* TLV placeholder for ie_data (NULL) */
699 	len += WMI_TLV_HDR_SIZE;
700 	len += ie_len * sizeof(uint32_t);
701 
702 	/* TLV placeholder for bucket */
703 	len += WMI_TLV_HDR_SIZE;
704 	len += nbuckets * sizeof(wmi_extscan_bucket);
705 
706 	/* TLV channel placeholder */
707 	len += WMI_TLV_HDR_SIZE;
708 	for (i = 0; i < nbuckets; i++) {
709 		nchannels += src_bucket->num_channels;
710 		src_bucket++;
711 	}
712 
713 	wmi_debug("Total buckets: %d total #of channels is %d",
714 		 nbuckets, nchannels);
715 	len += nchannels * sizeof(wmi_extscan_bucket_channel);
716 	/* Allocate the memory */
717 	*buf = wmi_buf_alloc(wmi_handle, len);
718 	if (!*buf) {
719 		wmi_err("Failed to allocate memory for start extscan cmd");
720 		return QDF_STATUS_E_NOMEM;
721 	}
722 	buf_ptr = (uint8_t *) wmi_buf_data(*buf);
723 	cmd = (wmi_extscan_start_cmd_fixed_param *) buf_ptr;
724 	WMITLV_SET_HDR(&cmd->tlv_header,
725 		       WMITLV_TAG_STRUC_wmi_extscan_start_cmd_fixed_param,
726 		       WMITLV_GET_STRUCT_TLVLEN
727 			       (wmi_extscan_start_cmd_fixed_param));
728 
729 	cmd->request_id = pstart->request_id;
730 	cmd->vdev_id = pstart->vdev_id;
731 	cmd->base_period = pstart->base_period;
732 	cmd->num_buckets = nbuckets;
733 	cmd->configuration_flags = 0;
734 	if (pstart->configuration_flags & WMI_EXTSCAN_LP_EXTENDED_BATCHING)
735 		cmd->configuration_flags |= WMI_EXTSCAN_EXTENDED_BATCHING_EN;
736 	wmi_debug("configuration_flags: 0x%x", cmd->configuration_flags);
737 #ifdef FEATURE_WLAN_EXTSCAN
738 	cmd->min_rest_time = WMI_EXTSCAN_REST_TIME;
739 	cmd->max_rest_time = WMI_EXTSCAN_REST_TIME;
740 	cmd->max_scan_time = WMI_EXTSCAN_MAX_SCAN_TIME;
741 	cmd->burst_duration = WMI_EXTSCAN_BURST_DURATION;
742 #endif
743 
744 	/* The max dwell time is retrieved from the first channel
745 	 * of the first bucket and kept common for all channels.
746 	 */
747 	cmd->min_dwell_time_active = pstart->min_dwell_time_active;
748 	cmd->max_dwell_time_active = pstart->max_dwell_time_active;
749 	cmd->min_dwell_time_passive = pstart->min_dwell_time_passive;
750 	cmd->max_dwell_time_passive = pstart->max_dwell_time_passive;
751 	cmd->max_bssids_per_scan_cycle = pstart->max_ap_per_scan;
752 	cmd->max_table_usage = pstart->report_threshold_percent;
753 	cmd->report_threshold_num_scans = pstart->report_threshold_num_scans;
754 
755 	cmd->repeat_probe_time = cmd->max_dwell_time_active /
756 					WMI_SCAN_NPROBES_DEFAULT;
757 	cmd->probe_delay = 0;
758 	cmd->probe_spacing_time = 0;
759 	cmd->idle_time = 0;
760 	cmd->scan_ctrl_flags = WMI_SCAN_ADD_BCAST_PROBE_REQ |
761 			       WMI_SCAN_ADD_CCK_RATES |
762 			       WMI_SCAN_ADD_OFDM_RATES |
763 			       WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ |
764 			       WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ;
765 	WMI_SCAN_SET_DWELL_MODE(cmd->scan_ctrl_flags,
766 			pstart->extscan_adaptive_dwell_mode);
767 	cmd->scan_priority = WMI_SCAN_PRIORITY_VERY_LOW;
768 	cmd->num_ssids = 0;
769 	cmd->num_bssid = 0;
770 	cmd->ie_len = 0;
771 	cmd->n_probes = (cmd->repeat_probe_time > 0) ?
772 			cmd->max_dwell_time_active / cmd->repeat_probe_time : 0;
773 
774 	buf_ptr += sizeof(*cmd);
775 	WMITLV_SET_HDR(buf_ptr,
776 		       WMITLV_TAG_ARRAY_FIXED_STRUC,
777 		       num_ssid * sizeof(wmi_ssid));
778 	buf_ptr += WMI_TLV_HDR_SIZE + (num_ssid * sizeof(wmi_ssid));
779 
780 	WMITLV_SET_HDR(buf_ptr,
781 		       WMITLV_TAG_ARRAY_FIXED_STRUC,
782 		       num_bssid * sizeof(wmi_mac_addr));
783 	buf_ptr += WMI_TLV_HDR_SIZE + (num_bssid * sizeof(wmi_mac_addr));
784 
785 	ie_len_with_pad = 0;
786 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
787 			  ie_len_with_pad);
788 	buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad;
789 
790 	WMITLV_SET_HDR(buf_ptr,
791 		       WMITLV_TAG_ARRAY_STRUC,
792 		       nbuckets * sizeof(wmi_extscan_bucket));
793 	dest_blist = (wmi_extscan_bucket *)
794 		     (buf_ptr + WMI_TLV_HDR_SIZE);
795 	src_bucket = pstart->buckets;
796 
797 	/* Retrieve scanning information from each bucket and
798 	 * channels and send it to the target
799 	 */
800 	for (i = 0; i < nbuckets; i++) {
801 		WMITLV_SET_HDR(dest_blist,
802 		      WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
803 		      WMITLV_GET_STRUCT_TLVLEN(wmi_extscan_bucket));
804 
805 		dest_blist->bucket_id = src_bucket->bucket;
806 		dest_blist->base_period_multiplier =
807 			src_bucket->period / base_period;
808 		dest_blist->min_period = src_bucket->period;
809 		dest_blist->max_period = src_bucket->max_period;
810 		dest_blist->exp_backoff = src_bucket->exponent;
811 		dest_blist->exp_max_step_count = src_bucket->step_count;
812 		dest_blist->channel_band = src_bucket->band;
813 		dest_blist->num_channels = src_bucket->num_channels;
814 		dest_blist->notify_extscan_events = 0;
815 
816 		if (src_bucket->report_events &
817 					WMI_EXTSCAN_REPORT_EVENTS_EACH_SCAN)
818 			dest_blist->notify_extscan_events =
819 					WMI_EXTSCAN_CYCLE_COMPLETED_EVENT |
820 					WMI_EXTSCAN_CYCLE_STARTED_EVENT;
821 
822 		if (src_bucket->report_events &
823 				WMI_EXTSCAN_REPORT_EVENTS_FULL_RESULTS) {
824 			dest_blist->forwarding_flags =
825 				WMI_EXTSCAN_FORWARD_FRAME_TO_HOST;
826 			dest_blist->notify_extscan_events |=
827 				WMI_EXTSCAN_BUCKET_COMPLETED_EVENT |
828 				WMI_EXTSCAN_CYCLE_STARTED_EVENT |
829 				WMI_EXTSCAN_CYCLE_COMPLETED_EVENT;
830 		} else {
831 			dest_blist->forwarding_flags =
832 				WMI_EXTSCAN_NO_FORWARDING;
833 		}
834 
835 		if (src_bucket->report_events &
836 					WMI_EXTSCAN_REPORT_EVENTS_NO_BATCH)
837 			dest_blist->configuration_flags = 0;
838 		else
839 			dest_blist->configuration_flags =
840 				WMI_EXTSCAN_BUCKET_CACHE_RESULTS;
841 
842 		wmi_debug("ntfy_extscan_events:%u cfg_flags:%u fwd_flags:%u",
843 			  dest_blist->notify_extscan_events,
844 			  dest_blist->configuration_flags,
845 			  dest_blist->forwarding_flags);
846 
847 		dest_blist->min_dwell_time_active =
848 				   src_bucket->min_dwell_time_active;
849 		dest_blist->max_dwell_time_active =
850 				   src_bucket->max_dwell_time_active;
851 		dest_blist->min_dwell_time_passive =
852 				   src_bucket->min_dwell_time_passive;
853 		dest_blist->max_dwell_time_passive =
854 				   src_bucket->max_dwell_time_passive;
855 		src_channel = src_bucket->channels;
856 
857 		/* save the channel info to later populate
858 		 * the  channel TLV
859 		 */
860 		for (k = 0; k < src_bucket->num_channels; k++) {
861 			save_channel[count++].channel = src_channel->channel;
862 			src_channel++;
863 		}
864 		dest_blist++;
865 		src_bucket++;
866 	}
867 	buf_ptr += WMI_TLV_HDR_SIZE + (nbuckets * sizeof(wmi_extscan_bucket));
868 	WMITLV_SET_HDR(buf_ptr,
869 		       WMITLV_TAG_ARRAY_STRUC,
870 		       nchannels * sizeof(wmi_extscan_bucket_channel));
871 	dest_clist = (wmi_extscan_bucket_channel *)
872 		     (buf_ptr + WMI_TLV_HDR_SIZE);
873 
874 	/* Active or passive scan is based on the bucket dwell time
875 	 * and channel specific active,passive scans are not
876 	 * supported yet
877 	 */
878 	for (i = 0; i < nchannels; i++) {
879 		WMITLV_SET_HDR(dest_clist,
880 		WMITLV_TAG_STRUC_wmi_extscan_bucket_channel_event_fixed_param,
881 			   WMITLV_GET_STRUCT_TLVLEN
882 			   (wmi_extscan_bucket_channel));
883 		dest_clist->channel = save_channel[i].channel;
884 		dest_clist++;
885 	}
886 	buf_ptr += WMI_TLV_HDR_SIZE +
887 		   (nchannels * sizeof(wmi_extscan_bucket_channel));
888 	*buf_len = len;
889 	return QDF_STATUS_SUCCESS;
890 }
891 
892 /**
893  * send_start_extscan_cmd_tlv() - start extscan command to fw.
894  * @wmi_handle: wmi handle
895  * @pstart: scan command request params
896  *
897  * This function sends start extscan request to fw.
898  *
899  * Return: CDF Status.
900  */
901 static QDF_STATUS send_start_extscan_cmd_tlv(wmi_unified_t wmi_handle,
902 			  struct wifi_scan_cmd_req_params *pstart)
903 {
904 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
905 	wmi_buf_t buf;
906 	int len;
907 
908 	/* Fill individual elements of extscan request and
909 	 * TLV for buckets, channel list.
910 	 */
911 	qdf_status = wmi_get_buf_extscan_start_cmd(wmi_handle,
912 			     pstart, &buf, &len);
913 	if (qdf_status != QDF_STATUS_SUCCESS) {
914 		wmi_err("Failed to get buffer for ext scan cmd");
915 		return QDF_STATUS_E_FAILURE;
916 	}
917 	if (!buf) {
918 		wmi_err("Failed to get buffer for current extscan info");
919 		return QDF_STATUS_E_FAILURE;
920 	}
921 	if (wmi_unified_cmd_send(wmi_handle, buf,
922 				 len, WMI_EXTSCAN_START_CMDID)) {
923 		wmi_err("Failed to send extscan start cmd");
924 		wmi_buf_free(buf);
925 		return QDF_STATUS_E_FAILURE;
926 	}
927 
928 	return QDF_STATUS_SUCCESS;
929 }
930 
931 /** wmi_get_hotlist_entries_per_page() - hotlist entries per page
932  * @wmi_handle: wmi handle.
933  * @cmd: size of command structure.
934  * @per_entry_size: per entry size.
935  *
936  * This utility function calculates how many hotlist entries can
937  * fit in one page.
938  *
939  * Return: number of entries
940  */
941 static inline int wmi_get_hotlist_entries_per_page
942 				(wmi_unified_t wmi_handle,
943 				size_t cmd_size,
944 				size_t per_entry_size)
945 {
946 	uint32_t avail_space = 0;
947 	int num_entries = 0;
948 	uint16_t max_msg_len = wmi_get_max_msg_len(wmi_handle);
949 
950 	/* Calculate number of hotlist entries that can
951 	 * be passed in wma message request.
952 	 */
953 	avail_space = max_msg_len - cmd_size;
954 	num_entries = avail_space / per_entry_size;
955 	return num_entries;
956 }
957 
958 /**
959  * send_extscan_start_hotlist_monitor_cmd_tlv() - start hotlist monitor
960  * @wmi_handle: wmi handle
961  * @params: hotlist params
962  *
963  * This function configures hotlist monitor to start in fw.
964  *
965  * Return: QDF status
966  */
967 static QDF_STATUS send_extscan_start_hotlist_monitor_cmd_tlv
968 			(wmi_unified_t wmi_handle,
969 			struct extscan_bssid_hotlist_set_params *params)
970 {
971 	wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd = NULL;
972 	wmi_extscan_hotlist_entry *dest_hotlist;
973 	struct ap_threshold_params *src_ap = params->ap;
974 	wmi_buf_t buf;
975 	uint8_t *buf_ptr;
976 
977 	int j, index = 0;
978 	int cmd_len = 0;
979 	int num_entries;
980 	int min_entries = 0;
981 	uint32_t numap = params->num_ap;
982 	int len = sizeof(*cmd);
983 
984 	len += WMI_TLV_HDR_SIZE;
985 	cmd_len = len;
986 
987 	num_entries = wmi_get_hotlist_entries_per_page(wmi_handle,
988 							cmd_len,
989 							sizeof(*dest_hotlist));
990 	/* setbssid hotlist expects the bssid list
991 	 * to be non zero value
992 	 */
993 	if (!numap || (numap > WMI_WLAN_EXTSCAN_MAX_HOTLIST_APS)) {
994 		wmi_err("Invalid number of APs: %d", numap);
995 		return QDF_STATUS_E_INVAL;
996 	}
997 
998 	/* Split the hot list entry pages and send multiple command
999 	 * requests if the buffer reaches the maximum request size
1000 	 */
1001 	while (index < numap) {
1002 		min_entries = QDF_MIN(num_entries, numap);
1003 		len += min_entries * sizeof(wmi_extscan_hotlist_entry);
1004 		buf = wmi_buf_alloc(wmi_handle, len);
1005 		if (!buf) {
1006 			wmi_err("wmi_buf_alloc failed");
1007 			return QDF_STATUS_E_FAILURE;
1008 		}
1009 		buf_ptr = (uint8_t *) wmi_buf_data(buf);
1010 		cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *)
1011 		      buf_ptr;
1012 		WMITLV_SET_HDR(&cmd->tlv_header,
1013 			       WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param,
1014 			       WMITLV_GET_STRUCT_TLVLEN
1015 				       (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param));
1016 
1017 		/* Multiple requests are sent until the num_entries_in_page
1018 		 * matches the total_entries
1019 		 */
1020 		cmd->request_id = params->request_id;
1021 		cmd->vdev_id = params->vdev_id;
1022 		cmd->total_entries = numap;
1023 		cmd->mode = 1;
1024 		cmd->num_entries_in_page = min_entries;
1025 		cmd->lost_ap_scan_count = params->lost_ap_sample_size;
1026 		cmd->first_entry_index = index;
1027 
1028 		wmi_debug("vdev id:%d total_entries: %d num_entries: %d lost_ap_sample_size: %d",
1029 			 cmd->vdev_id, cmd->total_entries,
1030 			 cmd->num_entries_in_page,
1031 			 cmd->lost_ap_scan_count);
1032 
1033 		buf_ptr += sizeof(*cmd);
1034 		WMITLV_SET_HDR(buf_ptr,
1035 			       WMITLV_TAG_ARRAY_STRUC,
1036 			       min_entries * sizeof(wmi_extscan_hotlist_entry));
1037 		dest_hotlist = (wmi_extscan_hotlist_entry *)
1038 			       (buf_ptr + WMI_TLV_HDR_SIZE);
1039 
1040 		/* Populate bssid, channel info and rssi
1041 		 * for the bssid's that are sent as hotlists.
1042 		 */
1043 		for (j = 0; j < min_entries; j++) {
1044 			WMITLV_SET_HDR(dest_hotlist,
1045 				       WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
1046 				       WMITLV_GET_STRUCT_TLVLEN
1047 					       (wmi_extscan_hotlist_entry));
1048 
1049 			dest_hotlist->min_rssi = src_ap->low;
1050 			WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid.bytes,
1051 						   &dest_hotlist->bssid);
1052 
1053 			wmi_debug("channel:%d min_rssi %d",
1054 				 dest_hotlist->channel,
1055 				 dest_hotlist->min_rssi);
1056 			wmi_debug("bssid mac_addr31to0: 0x%x, mac_addr47to32: 0x%x",
1057 				dest_hotlist->bssid.mac_addr31to0,
1058 				dest_hotlist->bssid.mac_addr47to32);
1059 			dest_hotlist++;
1060 			src_ap++;
1061 		}
1062 		buf_ptr += WMI_TLV_HDR_SIZE +
1063 			   (min_entries * sizeof(wmi_extscan_hotlist_entry));
1064 
1065 		if (wmi_unified_cmd_send(wmi_handle, buf, len,
1066 				WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) {
1067 			wmi_err("Failed to send extscan cfg hotlist monitor cmd");
1068 			wmi_buf_free(buf);
1069 			return QDF_STATUS_E_FAILURE;
1070 		}
1071 		index = index + min_entries;
1072 		num_entries = numap - min_entries;
1073 		len = cmd_len;
1074 	}
1075 	return QDF_STATUS_SUCCESS;
1076 }
1077 
1078 void wmi_extscan_attach_tlv(wmi_unified_t wmi_handle)
1079 {
1080 	struct wmi_ops *ops = wmi_handle->ops;
1081 	ops->send_reset_passpoint_network_list_cmd =
1082 				send_reset_passpoint_network_list_cmd_tlv;
1083 	ops->send_set_passpoint_network_list_cmd =
1084 				send_set_passpoint_network_list_cmd_tlv;
1085 	ops->send_set_epno_network_list_cmd =
1086 				send_set_epno_network_list_cmd_tlv;
1087 	ops->send_extscan_get_capabilities_cmd =
1088 				 send_extscan_get_capabilities_cmd_tlv;
1089 	ops->send_extscan_get_cached_results_cmd =
1090 				send_extscan_get_cached_results_cmd_tlv;
1091 	ops->send_extscan_stop_change_monitor_cmd =
1092 				send_extscan_stop_change_monitor_cmd_tlv;
1093 	ops->send_extscan_start_change_monitor_cmd =
1094 				send_extscan_start_change_monitor_cmd_tlv;
1095 	ops->send_extscan_stop_hotlist_monitor_cmd =
1096 				send_extscan_stop_hotlist_monitor_cmd_tlv;
1097 	ops->send_extscan_start_hotlist_monitor_cmd =
1098 				send_extscan_start_hotlist_monitor_cmd_tlv;
1099 	ops->send_stop_extscan_cmd = send_stop_extscan_cmd_tlv;
1100 	ops->send_start_extscan_cmd = send_start_extscan_cmd_tlv;
1101 }
1102