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