xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_sta_tlv.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2013-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_version.h"
22 #include "wmi_unified_priv.h"
23 #include "wmi_unified_sta_param.h"
24 #include "wmi_unified_sta_api.h"
25 #ifdef FEATURE_WLAN_TDLS
26 #include <wlan_tdls_public_structs.h>
27 #endif
28 
29 /**
30  * send_set_sta_sa_query_param_cmd_tlv() - set sta sa query parameters
31  * @wmi_handle: wmi handle
32  * @vdev_id: vdev id
33  * @max_retries: max retries
34  * @retry_interval: retry interval
35  * This function sets sta query related parameters in fw.
36  *
37  * Return: QDF_STATUS_SUCCESS for success otherwise failure
38  */
39 static QDF_STATUS send_set_sta_sa_query_param_cmd_tlv(wmi_unified_t wmi_handle,
40 						      uint8_t vdev_id,
41 						      uint32_t max_retries,
42 						      uint32_t retry_interval)
43 {
44 	wmi_buf_t buf;
45 	WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param *cmd;
46 	int len;
47 
48 	len = sizeof(*cmd);
49 	buf = wmi_buf_alloc(wmi_handle, len);
50 	if (!buf) {
51 		return QDF_STATUS_E_FAILURE;
52 	}
53 
54 	cmd = (WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param *)wmi_buf_data(buf);
55 	WMITLV_SET_HDR(&cmd->tlv_header,
56 		WMITLV_TAG_STRUC_WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param,
57 		WMITLV_GET_STRUCT_TLVLEN
58 			(WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param));
59 
60 	cmd->vdev_id = vdev_id;
61 	cmd->sa_query_max_retry_count = max_retries;
62 	cmd->sa_query_retry_interval = retry_interval;
63 
64 	wmi_debug("STA sa query: vdev_id:%d interval:%u retry count:%d",
65 		 vdev_id, retry_interval, max_retries);
66 
67 	wmi_mtrace(WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID, cmd->vdev_id, 0);
68 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
69 				 WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID)) {
70 		wmi_err("Failed to offload STA SA Query");
71 		wmi_buf_free(buf);
72 		return QDF_STATUS_E_FAILURE;
73 	}
74 
75 	wmi_debug("Exit");
76 	return 0;
77 }
78 
79 /**
80  * send_set_sta_keep_alive_cmd_tlv() - set sta keep alive parameters
81  * @wmi_handle: wmi handle
82  * @params: sta keep alive parameter
83  *
84  * This function sets keep alive related parameters in fw.
85  *
86  * Return: CDF status
87  */
88 static QDF_STATUS
89 send_set_sta_keep_alive_cmd_tlv(wmi_unified_t wmi_handle,
90 				struct sta_keep_alive_params *params)
91 {
92 	wmi_buf_t buf;
93 	WMI_STA_KEEPALIVE_CMD_fixed_param *cmd;
94 	WMI_STA_KEEPALVE_ARP_RESPONSE *arp_rsp;
95 	uint8_t *buf_ptr;
96 	int len;
97 	QDF_STATUS ret;
98 
99 	wmi_debug("Enter");
100 
101 	len = sizeof(*cmd) + sizeof(*arp_rsp);
102 	buf = wmi_buf_alloc(wmi_handle, len);
103 	if (!buf) {
104 		return QDF_STATUS_E_FAILURE;
105 	}
106 
107 	cmd = (WMI_STA_KEEPALIVE_CMD_fixed_param *) wmi_buf_data(buf);
108 	buf_ptr = (uint8_t *) cmd;
109 	WMITLV_SET_HDR(&cmd->tlv_header,
110 		       WMITLV_TAG_STRUC_WMI_STA_KEEPALIVE_CMD_fixed_param,
111 		       WMITLV_GET_STRUCT_TLVLEN
112 			       (WMI_STA_KEEPALIVE_CMD_fixed_param));
113 	cmd->interval = params->timeperiod;
114 	cmd->enable = (params->timeperiod) ? 1 : 0;
115 	cmd->vdev_id = params->vdev_id;
116 	wmi_debug("Keep Alive: vdev_id:%d interval:%u method:%d",
117 		 params->vdev_id, params->timeperiod, params->method);
118 	arp_rsp = (WMI_STA_KEEPALVE_ARP_RESPONSE *) (buf_ptr + sizeof(*cmd));
119 	WMITLV_SET_HDR(&arp_rsp->tlv_header,
120 		       WMITLV_TAG_STRUC_WMI_STA_KEEPALVE_ARP_RESPONSE,
121 		       WMITLV_GET_STRUCT_TLVLEN(WMI_STA_KEEPALVE_ARP_RESPONSE));
122 
123 	if ((params->method == WMI_KEEP_ALIVE_UNSOLICIT_ARP_RSP) ||
124 	    (params->method ==
125 	     WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST)) {
126 		cmd->method = params->method;
127 		qdf_mem_copy(&arp_rsp->sender_prot_addr, params->hostv4addr,
128 			     QDF_IPV4_ADDR_SIZE);
129 		qdf_mem_copy(&arp_rsp->target_prot_addr, params->destv4addr,
130 			     QDF_IPV4_ADDR_SIZE);
131 		WMI_CHAR_ARRAY_TO_MAC_ADDR(params->destmac,
132 					   &arp_rsp->dest_mac_addr);
133 	} else if (WMI_KEEP_ALIVE_MGMT_FRAME == params->method) {
134 		cmd->method = WMI_STA_KEEPALIVE_METHOD_MGMT_VENDOR_ACTION;
135 	} else {
136 		cmd->method = WMI_STA_KEEPALIVE_METHOD_NULL_FRAME;
137 	}
138 
139 	wmi_mtrace(WMI_STA_KEEPALIVE_CMDID, cmd->vdev_id, 0);
140 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
141 				   WMI_STA_KEEPALIVE_CMDID);
142 	if (QDF_IS_STATUS_ERROR(ret)) {
143 		wmi_err("Failed to set KeepAlive");
144 		wmi_buf_free(buf);
145 	}
146 
147 	wmi_debug("Exit");
148 	return ret;
149 }
150 
151 /**
152  * send_vdev_set_gtx_cfg_cmd_tlv() - set GTX params
153  * @wmi_handle: wmi handle
154  * @if_id: vdev id
155  * @gtx_info: GTX config params
156  *
157  * This function set GTX related params in firmware.
158  *
159  * Return: QDF_STATUS_SUCCESS for success or error code
160  */
161 static QDF_STATUS send_vdev_set_gtx_cfg_cmd_tlv(wmi_unified_t wmi_handle, uint32_t if_id,
162 				  struct wmi_gtx_config *gtx_info)
163 {
164 	wmi_vdev_set_gtx_params_cmd_fixed_param *cmd;
165 	wmi_buf_t buf;
166 	QDF_STATUS ret;
167 	int len = sizeof(wmi_vdev_set_gtx_params_cmd_fixed_param);
168 
169 	buf = wmi_buf_alloc(wmi_handle, len);
170 	if (!buf) {
171 		return QDF_STATUS_E_NOMEM;
172 	}
173 	cmd = (wmi_vdev_set_gtx_params_cmd_fixed_param *) wmi_buf_data(buf);
174 	WMITLV_SET_HDR(&cmd->tlv_header,
175 		       WMITLV_TAG_STRUC_wmi_vdev_set_gtx_params_cmd_fixed_param,
176 		       WMITLV_GET_STRUCT_TLVLEN
177 			       (wmi_vdev_set_gtx_params_cmd_fixed_param));
178 	cmd->vdev_id = if_id;
179 
180 	cmd->gtxRTMask[0] = gtx_info->gtx_rt_mask[0];
181 	cmd->gtxRTMask[1] = gtx_info->gtx_rt_mask[1];
182 	cmd->userGtxMask = gtx_info->gtx_usrcfg;
183 	cmd->gtxPERThreshold = gtx_info->gtx_threshold;
184 	cmd->gtxPERMargin = gtx_info->gtx_margin;
185 	cmd->gtxTPCstep = gtx_info->gtx_tpcstep;
186 	cmd->gtxTPCMin = gtx_info->gtx_tpcmin;
187 	cmd->gtxBWMask = gtx_info->gtx_bwmask;
188 
189 	wmi_debug("Setting vdev%d GTX values:htmcs 0x%x, vhtmcs 0x%x, usermask 0x%x, \
190 		 gtxPERThreshold %d, gtxPERMargin %d, gtxTPCstep %d, gtxTPCMin %d, \
191 		 gtxBWMask 0x%x.", if_id, cmd->gtxRTMask[0], cmd->gtxRTMask[1],
192 		 cmd->userGtxMask, cmd->gtxPERThreshold, cmd->gtxPERMargin,
193 		 cmd->gtxTPCstep, cmd->gtxTPCMin, cmd->gtxBWMask);
194 
195 	wmi_mtrace(WMI_VDEV_SET_GTX_PARAMS_CMDID, cmd->vdev_id, 0);
196 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
197 				   WMI_VDEV_SET_GTX_PARAMS_CMDID);
198 	if (QDF_IS_STATUS_ERROR(ret)) {
199 		wmi_err("Failed to set GTX PARAMS");
200 		wmi_buf_free(buf);
201 	}
202 	return ret;
203 }
204 
205 /**
206  * send_process_dhcp_ind_cmd_tlv() - process dhcp indication from SME
207  * @wmi_handle: wmi handle
208  * @ta_dhcp_ind: DHCP indication parameter
209  *
210  * Return: CDF Status
211  */
212 static QDF_STATUS send_process_dhcp_ind_cmd_tlv(wmi_unified_t wmi_handle,
213 				wmi_peer_set_param_cmd_fixed_param *ta_dhcp_ind)
214 {
215 	QDF_STATUS status;
216 	wmi_buf_t buf = NULL;
217 	uint8_t *buf_ptr;
218 	wmi_peer_set_param_cmd_fixed_param *peer_set_param_fp;
219 	int len = sizeof(wmi_peer_set_param_cmd_fixed_param);
220 
221 	buf = wmi_buf_alloc(wmi_handle, len);
222 	if (!buf) {
223 		return QDF_STATUS_E_NOMEM;
224 	}
225 
226 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
227 	peer_set_param_fp = (wmi_peer_set_param_cmd_fixed_param *) buf_ptr;
228 	WMITLV_SET_HDR(&peer_set_param_fp->tlv_header,
229 		       WMITLV_TAG_STRUC_wmi_peer_set_param_cmd_fixed_param,
230 		       WMITLV_GET_STRUCT_TLVLEN
231 			       (wmi_peer_set_param_cmd_fixed_param));
232 
233 	/* fill in values */
234 	peer_set_param_fp->vdev_id = ta_dhcp_ind->vdev_id;
235 	peer_set_param_fp->param_id = ta_dhcp_ind->param_id;
236 	peer_set_param_fp->param_value = ta_dhcp_ind->param_value;
237 	qdf_mem_copy(&peer_set_param_fp->peer_macaddr,
238 		     &ta_dhcp_ind->peer_macaddr,
239 		     sizeof(ta_dhcp_ind->peer_macaddr));
240 
241 	wmi_mtrace(WMI_PEER_SET_PARAM_CMDID, NO_SESSION, 0);
242 	status = wmi_unified_cmd_send(wmi_handle, buf,
243 				      len, WMI_PEER_SET_PARAM_CMDID);
244 	if (QDF_IS_STATUS_ERROR(status)) {
245 		wmi_err("wmi_unified_cmd_send WMI_PEER_SET_PARAM_CMD"
246 			 " returned Error %d", status);
247 		wmi_buf_free(buf);
248 	}
249 
250 	return status;
251 }
252 
253 /**
254  * send_get_link_speed_cmd_tlv() -send command to get linkspeed
255  * @wmi_handle: wmi handle
256  * @pLinkSpeed: link speed info
257  *
258  * Return: CDF status
259  */
260 static QDF_STATUS send_get_link_speed_cmd_tlv(wmi_unified_t wmi_handle,
261 					      wmi_mac_addr peer_macaddr)
262 {
263 	wmi_peer_get_estimated_linkspeed_cmd_fixed_param *cmd;
264 	wmi_buf_t wmi_buf;
265 	uint32_t len;
266 	uint8_t *buf_ptr;
267 
268 	len = sizeof(wmi_peer_get_estimated_linkspeed_cmd_fixed_param);
269 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
270 	if (!wmi_buf) {
271 		return QDF_STATUS_E_NOMEM;
272 	}
273 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
274 
275 	cmd = (wmi_peer_get_estimated_linkspeed_cmd_fixed_param *) buf_ptr;
276 	WMITLV_SET_HDR(&cmd->tlv_header,
277 	       WMITLV_TAG_STRUC_wmi_peer_get_estimated_linkspeed_cmd_fixed_param,
278 	       WMITLV_GET_STRUCT_TLVLEN
279 			(wmi_peer_get_estimated_linkspeed_cmd_fixed_param));
280 
281 	/* Copy the peer macaddress to the wma buffer */
282 	qdf_mem_copy(&cmd->peer_macaddr,
283 		     &peer_macaddr,
284 		     sizeof(peer_macaddr));
285 
286 	wmi_mtrace(WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID, cmd->vdev_id, 0);
287 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
288 				 WMI_PEER_GET_ESTIMATED_LINKSPEED_CMDID)) {
289 		wmi_err("Failed to send link speed command");
290 		wmi_buf_free(wmi_buf);
291 		return QDF_STATUS_E_FAILURE;
292 	}
293 	return QDF_STATUS_SUCCESS;
294 }
295 
296 /**
297  * send_fw_profiling_cmd_tlv() - send FW profiling cmd to WLAN FW
298  * @wmi_handl: wmi handle
299  * @cmd: Profiling command index
300  * @value1: parameter1 value
301  * @value2: parameter2 value
302  *
303  * Return: QDF_STATUS_SUCCESS for success else error code
304  */
305 static QDF_STATUS send_fw_profiling_cmd_tlv(wmi_unified_t wmi_handle,
306 			uint32_t cmd, uint32_t value1, uint32_t value2)
307 {
308 	wmi_buf_t buf;
309 	int32_t len = 0;
310 	int ret;
311 	wmi_wlan_profile_trigger_cmd_fixed_param *prof_trig_cmd;
312 	wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *hist_intvl_cmd;
313 	wmi_wlan_profile_enable_profile_id_cmd_fixed_param *profile_enable_cmd;
314 	wmi_wlan_profile_get_prof_data_cmd_fixed_param *profile_getdata_cmd;
315 
316 	switch (cmd) {
317 	case WMI_WLAN_PROFILE_TRIGGER_CMDID:
318 		len = sizeof(wmi_wlan_profile_trigger_cmd_fixed_param);
319 		buf = wmi_buf_alloc(wmi_handle, len);
320 		if (!buf) {
321 			return QDF_STATUS_E_NOMEM;
322 		}
323 		prof_trig_cmd =
324 			(wmi_wlan_profile_trigger_cmd_fixed_param *)
325 				wmi_buf_data(buf);
326 		WMITLV_SET_HDR(&prof_trig_cmd->tlv_header,
327 		     WMITLV_TAG_STRUC_wmi_wlan_profile_trigger_cmd_fixed_param,
328 		     WMITLV_GET_STRUCT_TLVLEN
329 				(wmi_wlan_profile_trigger_cmd_fixed_param));
330 		prof_trig_cmd->enable = value1;
331 		wmi_mtrace(WMI_WLAN_PROFILE_TRIGGER_CMDID, NO_SESSION, 0);
332 		ret = wmi_unified_cmd_send(wmi_handle, buf, len,
333 					   WMI_WLAN_PROFILE_TRIGGER_CMDID);
334 		if (ret) {
335 			wmi_err("PROFILE_TRIGGER cmd Failed with value %d",
336 				 value1);
337 			wmi_buf_free(buf);
338 			return ret;
339 		}
340 		break;
341 
342 	case WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID:
343 		len = sizeof(wmi_wlan_profile_get_prof_data_cmd_fixed_param);
344 		buf = wmi_buf_alloc(wmi_handle, len);
345 		if (!buf) {
346 			return QDF_STATUS_E_NOMEM;
347 		}
348 		profile_getdata_cmd =
349 			(wmi_wlan_profile_get_prof_data_cmd_fixed_param *)
350 				wmi_buf_data(buf);
351 		WMITLV_SET_HDR(&profile_getdata_cmd->tlv_header,
352 		      WMITLV_TAG_STRUC_wmi_wlan_profile_get_prof_data_cmd_fixed_param,
353 		      WMITLV_GET_STRUCT_TLVLEN
354 		      (wmi_wlan_profile_get_prof_data_cmd_fixed_param));
355 		wmi_mtrace(WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
356 			   NO_SESSION, 0);
357 		ret = wmi_unified_cmd_send(wmi_handle, buf, len,
358 				WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID);
359 		if (ret) {
360 			wmi_err("PROFILE_DATA cmd Failed for id %d value %d",
361 				 value1, value2);
362 			wmi_buf_free(buf);
363 			return ret;
364 		}
365 		break;
366 
367 	case WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID:
368 		len = sizeof(wmi_wlan_profile_set_hist_intvl_cmd_fixed_param);
369 		buf = wmi_buf_alloc(wmi_handle, len);
370 		if (!buf) {
371 			return QDF_STATUS_E_NOMEM;
372 		}
373 		hist_intvl_cmd =
374 			(wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *)
375 				wmi_buf_data(buf);
376 		WMITLV_SET_HDR(&hist_intvl_cmd->tlv_header,
377 		      WMITLV_TAG_STRUC_wmi_wlan_profile_set_hist_intvl_cmd_fixed_param,
378 		      WMITLV_GET_STRUCT_TLVLEN
379 		      (wmi_wlan_profile_set_hist_intvl_cmd_fixed_param));
380 		hist_intvl_cmd->profile_id = value1;
381 		hist_intvl_cmd->value = value2;
382 		wmi_mtrace(WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
383 			   NO_SESSION, 0);
384 		ret = wmi_unified_cmd_send(wmi_handle, buf, len,
385 				WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID);
386 		if (ret) {
387 			wmi_err("HIST_INTVL cmd Failed for id %d value %d",
388 				 value1, value2);
389 			wmi_buf_free(buf);
390 			return ret;
391 		}
392 		break;
393 
394 	case WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID:
395 		len =
396 		sizeof(wmi_wlan_profile_enable_profile_id_cmd_fixed_param);
397 		buf = wmi_buf_alloc(wmi_handle, len);
398 		if (!buf) {
399 			return QDF_STATUS_E_NOMEM;
400 		}
401 		profile_enable_cmd =
402 			(wmi_wlan_profile_enable_profile_id_cmd_fixed_param *)
403 				wmi_buf_data(buf);
404 		WMITLV_SET_HDR(&profile_enable_cmd->tlv_header,
405 		      WMITLV_TAG_STRUC_wmi_wlan_profile_enable_profile_id_cmd_fixed_param,
406 		      WMITLV_GET_STRUCT_TLVLEN
407 		      (wmi_wlan_profile_enable_profile_id_cmd_fixed_param));
408 		profile_enable_cmd->profile_id = value1;
409 		profile_enable_cmd->enable = value2;
410 		wmi_mtrace(WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
411 			   NO_SESSION, 0);
412 		ret = wmi_unified_cmd_send(wmi_handle, buf, len,
413 				WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID);
414 		if (ret) {
415 			wmi_err("enable cmd Failed for id %d value %d",
416 				 value1, value2);
417 			wmi_buf_free(buf);
418 			return ret;
419 		}
420 		break;
421 
422 	default:
423 		wmi_debug("Invalid profiling command: %u", cmd);
424 		break;
425 	}
426 
427 	return 0;
428 }
429 
430 /**
431  * send_nat_keepalive_en_cmd_tlv() - enable NAT keepalive filter
432  * @wmi_handle: wmi handle
433  * @vdev_id: vdev id
434  *
435  * Return: QDF_STATUS_SUCCESS for success or error code
436  */
437 static QDF_STATUS send_nat_keepalive_en_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_id)
438 {
439 	WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param *cmd;
440 	wmi_buf_t buf;
441 	int32_t len = sizeof(*cmd);
442 
443 	wmi_debug("vdev_id: %d", vdev_id);
444 	buf = wmi_buf_alloc(wmi_handle, len);
445 	if (!buf) {
446 		return QDF_STATUS_E_NOMEM;
447 	}
448 	cmd = (WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param *)
449 		wmi_buf_data(buf);
450 	WMITLV_SET_HDR(&cmd->tlv_header,
451 	WMITLV_TAG_STRUC_WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param,
452 		  WMITLV_GET_STRUCT_TLVLEN
453 		  (WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD_fixed_param));
454 	cmd->vdev_id = vdev_id;
455 	cmd->action = IPSEC_NATKEEPALIVE_FILTER_ENABLE;
456 	wmi_mtrace(WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID, cmd->vdev_id, 0);
457 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
458 				 WMI_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID)) {
459 		wmi_err("Failed to send NAT keepalive enable command");
460 		wmi_buf_free(buf);
461 		return QDF_STATUS_E_FAILURE;
462 	}
463 
464 	return 0;
465 }
466 
467 static QDF_STATUS send_wlm_latency_level_cmd_tlv(wmi_unified_t wmi_handle,
468 				struct wlm_latency_level_param *params)
469 {
470 	wmi_wlm_config_cmd_fixed_param *cmd;
471 	wmi_buf_t buf;
472 	uint32_t len = sizeof(*cmd);
473 	static uint32_t ll[4] = {100, 60, 40, 20};
474 
475 	buf = wmi_buf_alloc(wmi_handle, len);
476 	if (!buf) {
477 		return QDF_STATUS_E_NOMEM;
478 	}
479 	cmd = (wmi_wlm_config_cmd_fixed_param *)wmi_buf_data(buf);
480 	WMITLV_SET_HDR(&cmd->tlv_header,
481 		       WMITLV_TAG_STRUC_wmi_wlm_config_cmd_fixed_param,
482 		       WMITLV_GET_STRUCT_TLVLEN
483 		       (wmi_wlm_config_cmd_fixed_param));
484 	cmd->vdev_id = params->vdev_id;
485 	cmd->latency_level = params->wlm_latency_level;
486 	cmd->ul_latency = ll[params->wlm_latency_level];
487 	cmd->dl_latency = ll[params->wlm_latency_level];
488 	cmd->flags = params->wlm_latency_flags;
489 	wmi_mtrace(WMI_WLM_CONFIG_CMDID, cmd->vdev_id, 0);
490 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
491 				 WMI_WLM_CONFIG_CMDID)) {
492 		wmi_err("Failed to send setting latency config command");
493 		wmi_buf_free(buf);
494 		return QDF_STATUS_E_FAILURE;
495 	}
496 
497 	return 0;
498 }
499 
500 #ifdef FEATURE_WLAN_TDLS
501 /**
502  * tdls_get_wmi_offchannel_mode - Get WMI tdls off channel mode
503  * @tdls_sw_mode: tdls_sw_mode
504  *
505  * This function returns wmi tdls offchannel mode
506  *
507  * Return: enum value of wmi tdls offchannel mode
508  */
509 static uint8_t tdls_get_wmi_offchannel_mode(uint8_t tdls_sw_mode)
510 {
511 	uint8_t off_chan_mode;
512 
513 	switch (tdls_sw_mode) {
514 	case ENABLE_CHANSWITCH:
515 		off_chan_mode = WMI_TDLS_ENABLE_OFFCHANNEL;
516 		break;
517 
518 	case DISABLE_CHANSWITCH:
519 		off_chan_mode = WMI_TDLS_DISABLE_OFFCHANNEL;
520 		break;
521 
522 	default:
523 		wmi_debug("unknown tdls_sw_mode: %d", tdls_sw_mode);
524 		off_chan_mode = WMI_TDLS_DISABLE_OFFCHANNEL;
525 	}
526 	return off_chan_mode;
527 }
528 
529 /**
530  * tdls_get_wmi_offchannel_bw - Get WMI tdls off channel Bandwidth
531  * @tdls_sw_mode: tdls_sw_mode
532  *
533  * This function returns wmi tdls offchannel bandwidth
534  *
535  * Return: TDLS offchannel bandwidth
536  */
537 static uint8_t tdls_get_wmi_offchannel_bw(uint16_t tdls_off_ch_bw_offset)
538 {
539 	uint8_t off_chan_bw;
540 
541 	switch (tdls_off_ch_bw_offset) {
542 	case BW20:
543 		off_chan_bw = WMI_TDLS_OFFCHAN_20MHZ;
544 		break;
545 	case BW40_LOW_PRIMARY:
546 	case BW40_HIGH_PRIMARY:
547 		off_chan_bw = WMI_TDLS_OFFCHAN_40MHZ;
548 		break;
549 	case BW80:
550 		off_chan_bw = WMI_TDLS_OFFCHAN_80MHZ;
551 		break;
552 	case BWALL:
553 		off_chan_bw = WMI_TDLS_OFFCHAN_160MHZ;
554 		break;
555 	default:
556 		wmi_debug("unknown tdls offchannel bw offset: %d",
557 			 tdls_off_ch_bw_offset);
558 		off_chan_bw = WMI_TDLS_OFFCHAN_20MHZ;
559 	}
560 	return off_chan_bw;
561 }
562 
563 /**
564  * send_set_tdls_offchan_mode_cmd_tlv() - set tdls off channel mode
565  * @wmi_handle: wmi handle
566  * @chan_switch_params: Pointer to tdls channel switch parameter structure
567  *
568  * This function sets tdls off channel mode
569  *
570  * Return: 0 on success; Negative errno otherwise
571  */
572 static QDF_STATUS send_set_tdls_offchan_mode_cmd_tlv(wmi_unified_t wmi_handle,
573 	      struct tdls_channel_switch_params *chan_switch_params)
574 {
575 	wmi_tdls_set_offchan_mode_cmd_fixed_param *cmd;
576 	wmi_buf_t wmi_buf;
577 	u_int16_t len = sizeof(wmi_tdls_set_offchan_mode_cmd_fixed_param);
578 
579 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
580 	if (!wmi_buf) {
581 		return QDF_STATUS_E_FAILURE;
582 	}
583 	cmd = (wmi_tdls_set_offchan_mode_cmd_fixed_param *)
584 		wmi_buf_data(wmi_buf);
585 	WMITLV_SET_HDR(&cmd->tlv_header,
586 		WMITLV_TAG_STRUC_wmi_tdls_set_offchan_mode_cmd_fixed_param,
587 		WMITLV_GET_STRUCT_TLVLEN(
588 			wmi_tdls_set_offchan_mode_cmd_fixed_param));
589 
590 	WMI_CHAR_ARRAY_TO_MAC_ADDR(chan_switch_params->peer_mac_addr,
591 				&cmd->peer_macaddr);
592 	cmd->vdev_id = chan_switch_params->vdev_id;
593 	cmd->offchan_mode =
594 		tdls_get_wmi_offchannel_mode(chan_switch_params->tdls_sw_mode);
595 	cmd->is_peer_responder = chan_switch_params->is_responder;
596 	cmd->offchan_freq = chan_switch_params->tdls_off_chan_freq;
597 	cmd->offchan_num = chan_switch_params->tdls_off_ch;
598 	cmd->offchan_bw_bitmap =
599 		tdls_get_wmi_offchannel_bw(
600 			chan_switch_params->tdls_off_ch_bw_offset);
601 	cmd->offchan_oper_class = chan_switch_params->oper_class;
602 
603 	wmi_debug("Peer MAC Addr mac_addr31to0: 0x%x, mac_addr47to32: 0x%x",
604 		 cmd->peer_macaddr.mac_addr31to0,
605 		 cmd->peer_macaddr.mac_addr47to32);
606 
607 	wmi_debug("vdev_id: %d, off channel mode: %d, off channel Num: %d, "
608 		 "off channel frequency: %u off channel offset: 0x%x, "
609 		 "is_peer_responder: %d, operating class: %d",
610 		 cmd->vdev_id,
611 		 cmd->offchan_mode,
612 		 cmd->offchan_num,
613 		 cmd->offchan_freq,
614 		 cmd->offchan_bw_bitmap,
615 		 cmd->is_peer_responder,
616 		 cmd->offchan_oper_class);
617 
618 	wmi_mtrace(WMI_TDLS_SET_OFFCHAN_MODE_CMDID, cmd->vdev_id, 0);
619 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
620 		WMI_TDLS_SET_OFFCHAN_MODE_CMDID)) {
621 		wmi_err("failed to send tdls off chan command");
622 		wmi_buf_free(wmi_buf);
623 		return QDF_STATUS_E_FAILURE;
624 	}
625 
626 	return QDF_STATUS_SUCCESS;
627 }
628 
629 /**
630  * send_update_fw_tdls_state_cmd_tlv() - send enable/disable tdls for a vdev
631  * @wmi_handle: wmi handle
632  * @pwmaTdlsparams: TDLS params
633  *
634  * Return: 0 for success or error code
635  */
636 static QDF_STATUS
637 send_update_fw_tdls_state_cmd_tlv(wmi_unified_t wmi_handle,
638 				  struct tdls_info *tdls_param,
639 				  enum wmi_tdls_state tdls_state)
640 {
641 	wmi_tdls_set_state_cmd_fixed_param *cmd;
642 	wmi_buf_t wmi_buf;
643 
644 	uint16_t len = sizeof(wmi_tdls_set_state_cmd_fixed_param);
645 
646 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
647 	if (!wmi_buf) {
648 		return QDF_STATUS_E_FAILURE;
649 	}
650 	cmd = (wmi_tdls_set_state_cmd_fixed_param *) wmi_buf_data(wmi_buf);
651 	WMITLV_SET_HDR(&cmd->tlv_header,
652 		  WMITLV_TAG_STRUC_wmi_tdls_set_state_cmd_fixed_param,
653 		  WMITLV_GET_STRUCT_TLVLEN
654 			(wmi_tdls_set_state_cmd_fixed_param));
655 	cmd->vdev_id = tdls_param->vdev_id;
656 	cmd->state = (A_UINT32)tdls_state;
657 	cmd->notification_interval_ms = tdls_param->notification_interval_ms;
658 	cmd->tx_discovery_threshold = tdls_param->tx_discovery_threshold;
659 	cmd->tx_teardown_threshold = tdls_param->tx_teardown_threshold;
660 	cmd->rssi_teardown_threshold = tdls_param->rssi_teardown_threshold;
661 	cmd->rssi_delta = tdls_param->rssi_delta;
662 	cmd->tdls_options = tdls_param->tdls_options;
663 	cmd->tdls_peer_traffic_ind_window = tdls_param->peer_traffic_ind_window;
664 	cmd->tdls_peer_traffic_response_timeout_ms =
665 		tdls_param->peer_traffic_response_timeout;
666 	cmd->tdls_puapsd_mask = tdls_param->puapsd_mask;
667 	cmd->tdls_puapsd_inactivity_time_ms =
668 		tdls_param->puapsd_inactivity_time;
669 	cmd->tdls_puapsd_rx_frame_threshold =
670 		tdls_param->puapsd_rx_frame_threshold;
671 	cmd->teardown_notification_ms =
672 		tdls_param->teardown_notification_ms;
673 	cmd->tdls_peer_kickout_threshold =
674 		tdls_param->tdls_peer_kickout_threshold;
675 	cmd->tdls_discovery_wake_timeout =
676 		tdls_param->tdls_discovery_wake_timeout;
677 
678 	wmi_debug("vdev %d tdls_state: %d, state: %d, "
679 		 "notification_interval_ms: %d, "
680 		 "tx_discovery_threshold: %d, "
681 		 "tx_teardown_threshold: %d, "
682 		 "rssi_teardown_threshold: %d, "
683 		 "rssi_delta: %d, "
684 		 "tdls_options: 0x%x, "
685 		 "tdls_peer_traffic_ind_window: %d, "
686 		 "tdls_peer_traffic_response_timeout: %d, "
687 		 "tdls_puapsd_mask: 0x%x, "
688 		 "tdls_puapsd_inactivity_time: %d, "
689 		 "tdls_puapsd_rx_frame_threshold: %d, "
690 		 "teardown_notification_ms: %d, "
691 		 "tdls_peer_kickout_threshold: %d, "
692 		 "tdls_discovery_wake_timeout: %d",
693 		 tdls_param->vdev_id, tdls_state, cmd->state,
694 		 cmd->notification_interval_ms,
695 		 cmd->tx_discovery_threshold,
696 		 cmd->tx_teardown_threshold,
697 		 cmd->rssi_teardown_threshold,
698 		 cmd->rssi_delta,
699 		 cmd->tdls_options,
700 		 cmd->tdls_peer_traffic_ind_window,
701 		 cmd->tdls_peer_traffic_response_timeout_ms,
702 		 cmd->tdls_puapsd_mask,
703 		 cmd->tdls_puapsd_inactivity_time_ms,
704 		 cmd->tdls_puapsd_rx_frame_threshold,
705 		 cmd->teardown_notification_ms,
706 		 cmd->tdls_peer_kickout_threshold,
707 		 cmd->tdls_discovery_wake_timeout);
708 
709 	wmi_mtrace(WMI_TDLS_SET_STATE_CMDID, cmd->vdev_id, 0);
710 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
711 				 WMI_TDLS_SET_STATE_CMDID)) {
712 		wmi_err("Failed to send tdls set state command");
713 		wmi_buf_free(wmi_buf);
714 		return QDF_STATUS_E_FAILURE;
715 	}
716 
717 	return QDF_STATUS_SUCCESS;
718 }
719 
720 /**
721  * send_update_tdls_peer_state_cmd_tlv() - update TDLS peer state
722  * @wmi_handle: wmi handle
723  * @peer_state: TDLS peer state params
724  *
725  * Return: QDF_STATUS_SUCCESS for success or error code
726  */
727 static QDF_STATUS
728 send_update_tdls_peer_state_cmd_tlv(wmi_unified_t wmi_handle,
729 				    struct tdls_peer_update_state *peer_state,
730 				    uint32_t *ch_mhz)
731 {
732 	struct tdls_peer_params *in_peer_cap;
733 	struct tdls_ch_params *in_chan_info;
734 	wmi_tdls_peer_update_cmd_fixed_param *cmd;
735 	wmi_tdls_peer_capabilities *peer_cap;
736 	wmi_channel *chan_info;
737 	wmi_buf_t wmi_buf;
738 	uint8_t *buf_ptr;
739 	uint32_t i;
740 	int32_t len = sizeof(wmi_tdls_peer_update_cmd_fixed_param) +
741 		      sizeof(wmi_tdls_peer_capabilities);
742 
743 	in_peer_cap = &peer_state->peer_cap;
744 	len += WMI_TLV_HDR_SIZE +
745 	       sizeof(wmi_channel) * in_peer_cap->peer_chanlen;
746 
747 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
748 	if (!wmi_buf) {
749 		return QDF_STATUS_E_FAILURE;
750 	}
751 
752 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
753 	cmd = (wmi_tdls_peer_update_cmd_fixed_param *) buf_ptr;
754 	WMITLV_SET_HDR(&cmd->tlv_header,
755 		       WMITLV_TAG_STRUC_wmi_tdls_peer_update_cmd_fixed_param,
756 		       WMITLV_GET_STRUCT_TLVLEN
757 			       (wmi_tdls_peer_update_cmd_fixed_param));
758 
759 	cmd->vdev_id = peer_state->vdev_id;
760 	WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_state->peer_macaddr,
761 				   &cmd->peer_macaddr);
762 
763 	cmd->peer_state = peer_state->peer_state;
764 
765 	wmi_debug("vdev_id: %d, peermac: "QDF_MAC_ADDR_FMT", "
766 		 "peer_macaddr.mac_addr31to0: 0x%x, "
767 		 "peer_macaddr.mac_addr47to32: 0x%x, peer_state: %d",
768 		 cmd->vdev_id,
769 		 QDF_MAC_ADDR_REF(peer_state->peer_macaddr),
770 		 cmd->peer_macaddr.mac_addr31to0,
771 		 cmd->peer_macaddr.mac_addr47to32, cmd->peer_state);
772 
773 	buf_ptr += sizeof(wmi_tdls_peer_update_cmd_fixed_param);
774 	peer_cap = (wmi_tdls_peer_capabilities *) buf_ptr;
775 	WMITLV_SET_HDR(&peer_cap->tlv_header,
776 		       WMITLV_TAG_STRUC_wmi_tdls_peer_capabilities,
777 		       WMITLV_GET_STRUCT_TLVLEN(wmi_tdls_peer_capabilities));
778 
779 	if ((in_peer_cap->peer_uapsd_queue & 0x08) >> 3)
780 		WMI_SET_TDLS_PEER_VO_UAPSD(peer_cap);
781 	if ((in_peer_cap->peer_uapsd_queue & 0x04) >> 2)
782 		WMI_SET_TDLS_PEER_VI_UAPSD(peer_cap);
783 	if ((in_peer_cap->peer_uapsd_queue & 0x02) >> 1)
784 		WMI_SET_TDLS_PEER_BK_UAPSD(peer_cap);
785 	if (in_peer_cap->peer_uapsd_queue & 0x01)
786 		WMI_SET_TDLS_PEER_BE_UAPSD(peer_cap);
787 
788 	/* Ack and More Data Ack are sent as 0, so no need to set
789 	 * but fill SP
790 	 */
791 	WMI_SET_TDLS_PEER_SP_UAPSD(peer_cap, in_peer_cap->peer_max_sp);
792 
793 	peer_cap->buff_sta_support = in_peer_cap->peer_buff_sta_support;
794 	peer_cap->off_chan_support = in_peer_cap->peer_off_chan_support;
795 	peer_cap->peer_curr_operclass = in_peer_cap->peer_curr_operclass;
796 	/* self curr operclass is not being used and so pass op class for
797 	 * preferred off chan in it.
798 	 */
799 	peer_cap->self_curr_operclass = in_peer_cap->opclass_for_prefoffchan;
800 	peer_cap->peer_chan_len = in_peer_cap->peer_chanlen;
801 	peer_cap->peer_operclass_len = in_peer_cap->peer_oper_classlen;
802 
803 	wmi_debug("peer_operclass_len: %d", peer_cap->peer_operclass_len);
804 	for (i = 0; i < WMI_TDLS_MAX_SUPP_OPER_CLASSES; i++) {
805 		peer_cap->peer_operclass[i] = in_peer_cap->peer_oper_class[i];
806 	}
807 	qdf_trace_hex_dump(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
808 			   (uint8_t *)peer_cap->peer_operclass,
809 			   WMI_TDLS_MAX_SUPP_OPER_CLASSES);
810 
811 	peer_cap->is_peer_responder = in_peer_cap->is_peer_responder;
812 	peer_cap->pref_offchan_freq = in_peer_cap->pref_offchan_freq;
813 	peer_cap->pref_offchan_num = in_peer_cap->pref_off_channum;
814 	peer_cap->pref_offchan_bw = in_peer_cap->pref_off_chan_bandwidth;
815 
816 	wmi_debug("peer_qos: 0x%x, buff_sta_support: %d, off_chan_support: %d, "
817 		 "peer_curr_operclass: %d, self_curr_operclass: %d, peer_chan_len: "
818 		 "%d, peer_operclass_len: %d, is_peer_responder: %d, pref_offchan_num:"
819 		 " %d, pref_offchan_bw: %d, pref_offchan_freq: %u",
820 		 peer_cap->peer_qos, peer_cap->buff_sta_support,
821 		 peer_cap->off_chan_support, peer_cap->peer_curr_operclass,
822 		 peer_cap->self_curr_operclass, peer_cap->peer_chan_len,
823 		 peer_cap->peer_operclass_len, peer_cap->is_peer_responder,
824 		 peer_cap->pref_offchan_num, peer_cap->pref_offchan_bw,
825 		 peer_cap->pref_offchan_freq);
826 
827 	/* next fill variable size array of peer chan info */
828 	buf_ptr += sizeof(wmi_tdls_peer_capabilities);
829 	WMITLV_SET_HDR(buf_ptr,
830 		       WMITLV_TAG_ARRAY_STRUC,
831 		       sizeof(wmi_channel) *
832 		       in_peer_cap->peer_chanlen);
833 
834 	chan_info = (wmi_channel *) (buf_ptr + WMI_TLV_HDR_SIZE);
835 	in_chan_info = in_peer_cap->peer_chan;
836 
837 	for (i = 0; i < in_peer_cap->peer_chanlen; ++i) {
838 		WMITLV_SET_HDR(&chan_info->tlv_header,
839 			       WMITLV_TAG_STRUC_wmi_channel,
840 			       WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
841 		chan_info->mhz = ch_mhz[i];
842 		chan_info->band_center_freq1 = chan_info->mhz;
843 		chan_info->band_center_freq2 = 0;
844 
845 		wmi_debug("chan[%d] = %u", i, chan_info->mhz);
846 
847 		if (in_chan_info->dfs_set) {
848 			WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_PASSIVE);
849 			wmi_debug("chan[%d] DFS[%d]",
850 				 in_chan_info->chan_id,
851 				 in_chan_info->dfs_set);
852 		}
853 
854 		if (chan_info->mhz < WMI_2_4_GHZ_MAX_FREQ)
855 			WMI_SET_CHANNEL_MODE(chan_info, MODE_11G);
856 		else
857 			WMI_SET_CHANNEL_MODE(chan_info, MODE_11A);
858 
859 		WMI_SET_CHANNEL_MAX_TX_POWER(chan_info, in_chan_info->pwr);
860 		WMI_SET_CHANNEL_REG_POWER(chan_info, in_chan_info->pwr);
861 		wmi_debug("Channel TX power[%d] = %u: %d", i, chan_info->mhz,
862 			 in_chan_info->pwr);
863 
864 		chan_info++;
865 		in_chan_info++;
866 	}
867 
868 	wmi_mtrace(WMI_TDLS_PEER_UPDATE_CMDID, cmd->vdev_id, 0);
869 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
870 				 WMI_TDLS_PEER_UPDATE_CMDID)) {
871 		wmi_err("Failed to send tdls peer update state command");
872 		wmi_buf_free(wmi_buf);
873 		return QDF_STATUS_E_FAILURE;
874 	}
875 
876 	return QDF_STATUS_SUCCESS;
877 }
878 
879 /**
880  * extract_vdev_tdls_ev_param_tlv() - extract vdev tdls param from event
881  * @wmi_handle: wmi handle
882  * @param evt_buf: pointer to event buffer
883  * @param param: Pointer to hold vdev tdls param
884  *
885  * Return: QDF_STATUS_SUCCESS for success or error code
886  */
887 static QDF_STATUS extract_vdev_tdls_ev_param_tlv(wmi_unified_t wmi_handle,
888 	void *evt_buf, struct tdls_event_info *param)
889 {
890 	WMI_TDLS_PEER_EVENTID_param_tlvs *param_buf;
891 	wmi_tdls_peer_event_fixed_param *evt;
892 
893 	param_buf = (WMI_TDLS_PEER_EVENTID_param_tlvs *)evt_buf;
894 	if (!param_buf) {
895 		wmi_err("NULL param_buf");
896 		return QDF_STATUS_E_NULL_VALUE;
897 	}
898 
899 	evt = param_buf->fixed_param;
900 
901 	qdf_mem_zero(param, sizeof(*param));
902 
903 	param->vdev_id = evt->vdev_id;
904 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&evt->peer_macaddr,
905 				   param->peermac.bytes);
906 	switch (evt->peer_status) {
907 	case WMI_TDLS_SHOULD_DISCOVER:
908 		param->message_type = TDLS_SHOULD_DISCOVER;
909 		break;
910 	case WMI_TDLS_SHOULD_TEARDOWN:
911 		param->message_type = TDLS_SHOULD_TEARDOWN;
912 		break;
913 	case WMI_TDLS_PEER_DISCONNECTED:
914 		param->message_type = TDLS_PEER_DISCONNECTED;
915 		break;
916 	case WMI_TDLS_CONNECTION_TRACKER_NOTIFICATION:
917 		param->message_type = TDLS_CONNECTION_TRACKER_NOTIFY;
918 		break;
919 	default:
920 		wmi_err("Discarding unknown tdls event %d from target",
921 			evt->peer_status);
922 		return QDF_STATUS_E_INVAL;
923 	};
924 
925 	switch (evt->peer_reason) {
926 	case WMI_TDLS_TEARDOWN_REASON_TX:
927 		param->peer_reason = TDLS_TEARDOWN_TX;
928 		break;
929 	case WMI_TDLS_TEARDOWN_REASON_RSSI:
930 		param->peer_reason = TDLS_TEARDOWN_RSSI;
931 		break;
932 	case WMI_TDLS_TEARDOWN_REASON_SCAN:
933 		param->peer_reason = TDLS_TEARDOWN_SCAN;
934 		break;
935 	case WMI_TDLS_DISCONNECTED_REASON_PEER_DELETE:
936 		param->peer_reason = TDLS_DISCONNECTED_PEER_DELETE;
937 		break;
938 	case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
939 		param->peer_reason = TDLS_TEARDOWN_PTR_TIMEOUT;
940 		break;
941 	case WMI_TDLS_TEARDOWN_REASON_BAD_PTR:
942 		param->peer_reason = TDLS_TEARDOWN_BAD_PTR;
943 		break;
944 	case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
945 		param->peer_reason = TDLS_TEARDOWN_NO_RSP;
946 		break;
947 	case WMI_TDLS_ENTER_BUF_STA:
948 		param->peer_reason = TDLS_PEER_ENTER_BUF_STA;
949 		break;
950 	case WMI_TDLS_EXIT_BUF_STA:
951 		param->peer_reason = TDLS_PEER_EXIT_BUF_STA;
952 		break;
953 	case WMI_TDLS_ENTER_BT_BUSY_MODE:
954 		param->peer_reason = TDLS_ENTER_BT_BUSY;
955 		break;
956 	case WMI_TDLS_EXIT_BT_BUSY_MODE:
957 		param->peer_reason = TDLS_EXIT_BT_BUSY;
958 		break;
959 	case WMI_TDLS_SCAN_STARTED_EVENT:
960 		param->peer_reason = TDLS_SCAN_STARTED;
961 		break;
962 	case WMI_TDLS_SCAN_COMPLETED_EVENT:
963 		param->peer_reason = TDLS_SCAN_COMPLETED;
964 		break;
965 
966 	default:
967 		wmi_err("Unknown reason %d in tdls event %d from target",
968 			evt->peer_reason, evt->peer_status);
969 		return QDF_STATUS_E_INVAL;
970 	};
971 
972 	wmi_debug("tdls event, peer: "QDF_MAC_ADDR_FMT", type: 0x%x, reason: %d, vdev: %d",
973 		 QDF_MAC_ADDR_REF(param->peermac.bytes),
974 		 param->message_type,
975 		 param->peer_reason, param->vdev_id);
976 
977 	return QDF_STATUS_SUCCESS;
978 }
979 
980 void wmi_tdls_attach_tlv(struct wmi_unified *wmi_handle)
981 {
982 	struct wmi_ops *ops = wmi_handle->ops;
983 
984 	ops->send_set_tdls_offchan_mode_cmd =
985 		send_set_tdls_offchan_mode_cmd_tlv;
986 	ops->send_update_fw_tdls_state_cmd =
987 		send_update_fw_tdls_state_cmd_tlv;
988 	ops->send_update_tdls_peer_state_cmd =
989 		send_update_tdls_peer_state_cmd_tlv;
990 	ops->extract_vdev_tdls_ev_param = extract_vdev_tdls_ev_param_tlv;
991 }
992 #endif /* FEATURE_WLAN_TDLS */
993 
994 /*
995  * send_process_set_ie_info_cmd_tlv() - Function to send IE info to firmware
996  * @wmi_handle:    Pointer to WMi handle
997  * @ie_data:       Pointer for ie data
998  *
999  * This function sends IE information to firmware
1000  *
1001  * Return: QDF_STATUS_SUCCESS for success otherwise failure
1002  *
1003  */
1004 static QDF_STATUS send_process_set_ie_info_cmd_tlv(wmi_unified_t wmi_handle,
1005 				   struct vdev_ie_info_param *ie_info)
1006 {
1007 	wmi_vdev_set_ie_cmd_fixed_param *cmd;
1008 	wmi_buf_t buf;
1009 	uint8_t *buf_ptr;
1010 	uint32_t len, ie_len_aligned;
1011 	QDF_STATUS ret;
1012 
1013 	ie_len_aligned = roundup(ie_info->length, sizeof(uint32_t));
1014 	/* Allocate memory for the WMI command */
1015 	len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + ie_len_aligned;
1016 
1017 	buf = wmi_buf_alloc(wmi_handle, len);
1018 	if (!buf) {
1019 		return QDF_STATUS_E_NOMEM;
1020 	}
1021 
1022 	buf_ptr = wmi_buf_data(buf);
1023 	qdf_mem_zero(buf_ptr, len);
1024 
1025 	/* Populate the WMI command */
1026 	cmd = (wmi_vdev_set_ie_cmd_fixed_param *)buf_ptr;
1027 
1028 	WMITLV_SET_HDR(&cmd->tlv_header,
1029 		       WMITLV_TAG_STRUC_wmi_vdev_set_ie_cmd_fixed_param,
1030 		       WMITLV_GET_STRUCT_TLVLEN(
1031 				wmi_vdev_set_ie_cmd_fixed_param));
1032 	cmd->vdev_id = ie_info->vdev_id;
1033 	cmd->ie_id = ie_info->ie_id;
1034 	cmd->ie_len = ie_info->length;
1035 	cmd->band = ie_info->band;
1036 
1037 	wmi_debug("IE:%d of size:%d sent for vdev:%d", ie_info->ie_id,
1038 		 ie_info->length, ie_info->vdev_id);
1039 
1040 	buf_ptr += sizeof(*cmd);
1041 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned);
1042 	buf_ptr += WMI_TLV_HDR_SIZE;
1043 
1044 	qdf_mem_copy(buf_ptr, ie_info->data, cmd->ie_len);
1045 
1046 	wmi_mtrace(WMI_VDEV_SET_IE_CMDID, cmd->vdev_id, 0);
1047 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1048 				   WMI_VDEV_SET_IE_CMDID);
1049 	if (QDF_IS_STATUS_ERROR(ret)) {
1050 		wmi_err("Failed to send set IE command ret = %d", ret);
1051 		wmi_buf_free(buf);
1052 	}
1053 
1054 	return ret;
1055 }
1056 
1057 /**
1058  * send_set_base_macaddr_indicate_cmd_tlv() - set base mac address in fw
1059  * @wmi_handle: wmi handle
1060  * @custom_addr: base mac address
1061  *
1062  * Return: QDF_STATUS_SUCCESS for success or error code
1063  */
1064 static QDF_STATUS send_set_base_macaddr_indicate_cmd_tlv(wmi_unified_t wmi_handle,
1065 					 uint8_t *custom_addr)
1066 {
1067 	wmi_pdev_set_base_macaddr_cmd_fixed_param *cmd;
1068 	wmi_buf_t buf;
1069 	int err;
1070 
1071 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
1072 	if (!buf) {
1073 		return QDF_STATUS_E_NOMEM;
1074 	}
1075 
1076 	cmd = (wmi_pdev_set_base_macaddr_cmd_fixed_param *) wmi_buf_data(buf);
1077 	qdf_mem_zero(cmd, sizeof(*cmd));
1078 
1079 	WMITLV_SET_HDR(&cmd->tlv_header,
1080 		WMITLV_TAG_STRUC_wmi_pdev_set_base_macaddr_cmd_fixed_param,
1081 		       WMITLV_GET_STRUCT_TLVLEN
1082 			       (wmi_pdev_set_base_macaddr_cmd_fixed_param));
1083 	WMI_CHAR_ARRAY_TO_MAC_ADDR(custom_addr, &cmd->base_macaddr);
1084 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1085 							wmi_handle,
1086 							WMI_HOST_PDEV_ID_SOC);
1087 	wmi_mtrace(WMI_PDEV_SET_BASE_MACADDR_CMDID, NO_SESSION, 0);
1088 	err = wmi_unified_cmd_send(wmi_handle, buf,
1089 				   sizeof(*cmd),
1090 				   WMI_PDEV_SET_BASE_MACADDR_CMDID);
1091 	if (err) {
1092 		wmi_err("Failed to send set_base_macaddr cmd");
1093 		wmi_buf_free(buf);
1094 		return QDF_STATUS_E_FAILURE;
1095 	}
1096 
1097 	return 0;
1098 }
1099 
1100 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(FEATURE_BLACKLIST_MGR)
1101 
1102 static WMI_BSSID_DISALLOW_LIST_TYPE
1103 wmi_get_wmi_reject_ap_type(enum blm_reject_ap_type reject_ap_type)
1104 {
1105 	switch (reject_ap_type) {
1106 	case USERSPACE_AVOID_TYPE:
1107 		return WMI_BSSID_DISALLOW_USER_SPACE_AVOID_LIST;
1108 	case DRIVER_AVOID_TYPE:
1109 		return WMI_BSSID_DISALLOW_DRIVER_AVOID_LIST;
1110 	case USERSPACE_BLACKLIST_TYPE:
1111 		return WMI_BSSID_DISALLOW_USER_SPACE_BLACK_LIST;
1112 	case DRIVER_BLACKLIST_TYPE:
1113 		return WMI_BSSID_DISALLOW_DRIVER_BLACK_LIST;
1114 	case DRIVER_RSSI_REJECT_TYPE:
1115 		return WMI_BSSID_DISALLOW_RSSI_REJECT_LIST;
1116 	default:
1117 		return WMI_BSSID_DISALLOW_DRIVER_AVOID_LIST;
1118 	}
1119 }
1120 
1121 static WMI_BLACKLIST_REASON_ID
1122 wmi_get_reject_reason(enum blm_reject_ap_reason reject_reason)
1123 {
1124 	switch(reject_reason) {
1125 	case REASON_NUD_FAILURE:
1126 		return WMI_BL_REASON_NUD_FAILURE;
1127 	case REASON_STA_KICKOUT:
1128 		return WMI_BL_REASON_STA_KICKOUT;
1129 	case REASON_ROAM_HO_FAILURE:
1130 		return WMI_BL_REASON_ROAM_HO_FAILURE;
1131 	case REASON_ASSOC_REJECT_POOR_RSSI:
1132 		return WMI_BL_REASON_ASSOC_REJECT_POOR_RSSI;
1133 	case REASON_ASSOC_REJECT_OCE:
1134 		return WMI_BL_REASON_ASSOC_REJECT_OCE;
1135 	case REASON_USERSPACE_BL:
1136 		return WMI_BL_REASON_USERSPACE_BL;
1137 	case REASON_USERSPACE_AVOID_LIST:
1138 		return WMI_BL_REASON_USERSPACE_AVOID_LIST;
1139 	case REASON_BTM_DISASSOC_IMMINENT:
1140 		return WMI_BL_REASON_BTM_DIASSOC_IMMINENT;
1141 	case REASON_BTM_BSS_TERMINATION:
1142 		return WMI_BL_REASON_BTM_BSS_TERMINATION;
1143 	case REASON_BTM_MBO_RETRY:
1144 		return WMI_BL_REASON_BTM_MBO_RETRY;
1145 	case REASON_REASSOC_RSSI_REJECT:
1146 		return WMI_BL_REASON_REASSOC_RSSI_REJECT;
1147 	case REASON_REASSOC_NO_MORE_STAS:
1148 		return WMI_BL_REASON_REASSOC_NO_MORE_STAS;
1149 	default:
1150 		return 0;
1151 	}
1152 }
1153 
1154 static QDF_STATUS
1155 send_reject_ap_list_cmd_tlv(wmi_unified_t wmi_handle,
1156 			    struct reject_ap_params *reject_params)
1157 {
1158 	wmi_buf_t buf;
1159 	QDF_STATUS status;
1160 	uint32_t len, list_tlv_len;
1161 	int i;
1162 	uint8_t *buf_ptr;
1163 	wmi_pdev_dsm_filter_fixed_param *chan_list_fp;
1164 	wmi_pdev_bssid_disallow_list_config_param *chan_list;
1165 	struct reject_ap_config_params *reject_list = reject_params->bssid_list;
1166 	uint8_t num_of_reject_bssid = reject_params->num_of_reject_bssid;
1167 
1168 	list_tlv_len = sizeof(*chan_list) * num_of_reject_bssid;
1169 
1170 	len = sizeof(*chan_list_fp) + list_tlv_len + WMI_TLV_HDR_SIZE;
1171 	buf = wmi_buf_alloc(wmi_handle, len);
1172 	if (!buf)
1173 		return QDF_STATUS_E_NOMEM;
1174 
1175 	wmi_debug("num of reject BSSIDs %d", num_of_reject_bssid);
1176 
1177 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
1178 	chan_list_fp = (wmi_pdev_dsm_filter_fixed_param *)buf_ptr;
1179 	WMITLV_SET_HDR(&chan_list_fp->tlv_header,
1180 		       WMITLV_TAG_STRUC_wmi_pdev_dsm_filter_fixed_param,
1181 		       WMITLV_GET_STRUCT_TLVLEN
1182 			       (wmi_pdev_dsm_filter_fixed_param));
1183 
1184 	buf_ptr += sizeof(wmi_pdev_dsm_filter_fixed_param);
1185 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, list_tlv_len);
1186 
1187 	buf_ptr += WMI_TLV_HDR_SIZE;
1188 	chan_list = (wmi_pdev_bssid_disallow_list_config_param *)buf_ptr;
1189 	for (i = 0; i < num_of_reject_bssid; i++) {
1190 
1191 		WMITLV_SET_HDR(&chan_list->tlv_header,
1192 		     WMITLV_TAG_STRUC_wmi_pdev_bssid_disallow_list_config_param,
1193 			       WMITLV_GET_STRUCT_TLVLEN
1194 				  (wmi_pdev_bssid_disallow_list_config_param));
1195 		WMI_CHAR_ARRAY_TO_MAC_ADDR(reject_list[i].bssid.bytes,
1196 					   &chan_list->bssid);
1197 		chan_list->bssid_type =
1198 		    wmi_get_wmi_reject_ap_type(reject_list[i].reject_ap_type);
1199 		chan_list->expected_rssi = reject_list[i].expected_rssi;
1200 		chan_list->remaining_disallow_duration =
1201 					reject_list[i].reject_duration;
1202 		chan_list->reason =
1203 			wmi_get_reject_reason(reject_list[i].reject_reason);
1204 		chan_list->original_timeout = reject_list[i].original_timeout;
1205 		chan_list->timestamp = reject_list[i].received_time;
1206 		chan_list->source = reject_list[i].source;
1207 		chan_list++;
1208 	}
1209 
1210 	wmi_mtrace(WMI_PDEV_DSM_FILTER_CMDID, NO_SESSION, 0);
1211 	status = wmi_unified_cmd_send(wmi_handle, buf,
1212 				      len, WMI_PDEV_DSM_FILTER_CMDID);
1213 	if (QDF_IS_STATUS_ERROR(status)) {
1214 		wmi_err("wmi_unified_cmd_send WMI_PDEV_DSM_FILTER_CMDID returned Error %d",
1215 			 status);
1216 		goto error;
1217 	}
1218 
1219 	return QDF_STATUS_SUCCESS;
1220 error:
1221 	wmi_buf_free(buf);
1222 	return status;
1223 }
1224 
1225 void wmi_blacklist_mgr_attach_tlv(struct wmi_unified *wmi_handle)
1226 {
1227 	struct wmi_ops *ops = wmi_handle->ops;
1228 
1229 	ops->send_reject_ap_list_cmd = send_reject_ap_list_cmd_tlv;
1230 }
1231 #endif
1232 
1233 /**
1234  * send_sar_limit_cmd_tlv() - send sar limit cmd to fw
1235  * @wmi_handle: wmi handle
1236  * @params: sar limit params
1237  *
1238  * Return: QDF_STATUS_SUCCESS for success or error code
1239  */
1240 static QDF_STATUS send_sar_limit_cmd_tlv(wmi_unified_t wmi_handle,
1241 		struct sar_limit_cmd_params *sar_limit_params)
1242 {
1243 	wmi_buf_t buf;
1244 	QDF_STATUS qdf_status;
1245 	wmi_sar_limits_cmd_fixed_param *cmd;
1246 	int i;
1247 	uint8_t *buf_ptr;
1248 	wmi_sar_limit_cmd_row *wmi_sar_rows_list;
1249 	struct sar_limit_cmd_row *sar_rows_list;
1250 	uint32_t len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
1251 
1252 	len += sizeof(wmi_sar_limit_cmd_row) * sar_limit_params->num_limit_rows;
1253 	buf = wmi_buf_alloc(wmi_handle, len);
1254 	if (!buf) {
1255 		qdf_status = QDF_STATUS_E_NOMEM;
1256 		goto end;
1257 	}
1258 
1259 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1260 	cmd = (wmi_sar_limits_cmd_fixed_param *) buf_ptr;
1261 	WMITLV_SET_HDR(&cmd->tlv_header,
1262 		       WMITLV_TAG_STRUC_wmi_sar_limits_cmd_fixed_param,
1263 		       WMITLV_GET_STRUCT_TLVLEN
1264 				(wmi_sar_limits_cmd_fixed_param));
1265 	cmd->sar_enable = sar_limit_params->sar_enable;
1266 	cmd->commit_limits = sar_limit_params->commit_limits;
1267 	cmd->num_limit_rows = sar_limit_params->num_limit_rows;
1268 
1269 	wmi_debug("no of sar rows = %d, len = %d",
1270 		 sar_limit_params->num_limit_rows, len);
1271 	buf_ptr += sizeof(*cmd);
1272 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1273 		       sizeof(wmi_sar_limit_cmd_row) *
1274 			      sar_limit_params->num_limit_rows);
1275 	if (cmd->num_limit_rows == 0)
1276 		goto send_sar_limits;
1277 
1278 	wmi_sar_rows_list = (wmi_sar_limit_cmd_row *)
1279 				(buf_ptr + WMI_TLV_HDR_SIZE);
1280 	sar_rows_list = sar_limit_params->sar_limit_row_list;
1281 
1282 	for (i = 0; i < sar_limit_params->num_limit_rows; i++) {
1283 		WMITLV_SET_HDR(&wmi_sar_rows_list->tlv_header,
1284 			       WMITLV_TAG_STRUC_wmi_sar_limit_cmd_row,
1285 			       WMITLV_GET_STRUCT_TLVLEN(wmi_sar_limit_cmd_row));
1286 		wmi_sar_rows_list->band_id = sar_rows_list->band_id;
1287 		wmi_sar_rows_list->chain_id = sar_rows_list->chain_id;
1288 		wmi_sar_rows_list->mod_id = sar_rows_list->mod_id;
1289 		wmi_sar_rows_list->limit_value = sar_rows_list->limit_value;
1290 		wmi_sar_rows_list->validity_bitmap =
1291 						sar_rows_list->validity_bitmap;
1292 		wmi_debug("row %d, band_id = %d, chain_id = %d, mod_id = %d, limit_value = %d, validity_bitmap = %d",
1293 			 i, wmi_sar_rows_list->band_id,
1294 			 wmi_sar_rows_list->chain_id,
1295 			 wmi_sar_rows_list->mod_id,
1296 			 wmi_sar_rows_list->limit_value,
1297 			 wmi_sar_rows_list->validity_bitmap);
1298 		sar_rows_list++;
1299 		wmi_sar_rows_list++;
1300 	}
1301 send_sar_limits:
1302 	wmi_mtrace(WMI_SAR_LIMITS_CMDID, NO_SESSION, 0);
1303 	qdf_status = wmi_unified_cmd_send(wmi_handle, buf, len,
1304 					  WMI_SAR_LIMITS_CMDID);
1305 
1306 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
1307 		wmi_err("Failed to send WMI_SAR_LIMITS_CMDID");
1308 		wmi_buf_free(buf);
1309 	}
1310 
1311 end:
1312 	return qdf_status;
1313 }
1314 
1315 static QDF_STATUS get_sar_limit_cmd_tlv(wmi_unified_t wmi_handle)
1316 {
1317 	wmi_sar_get_limits_cmd_fixed_param *cmd;
1318 	wmi_buf_t wmi_buf;
1319 	uint32_t len;
1320 	QDF_STATUS status;
1321 
1322 	wmi_debug("Enter");
1323 
1324 	len = sizeof(*cmd);
1325 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
1326 	if (!wmi_buf) {
1327 		return QDF_STATUS_E_NOMEM;
1328 	}
1329 
1330 	cmd = (wmi_sar_get_limits_cmd_fixed_param *)wmi_buf_data(wmi_buf);
1331 
1332 	WMITLV_SET_HDR(&cmd->tlv_header,
1333 		       WMITLV_TAG_STRUC_wmi_sar_get_limits_cmd_fixed_param,
1334 		       WMITLV_GET_STRUCT_TLVLEN
1335 				(wmi_sar_get_limits_cmd_fixed_param));
1336 
1337 	cmd->reserved = 0;
1338 
1339 	wmi_mtrace(WMI_SAR_GET_LIMITS_CMDID, NO_SESSION, 0);
1340 	status = wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
1341 				      WMI_SAR_GET_LIMITS_CMDID);
1342 	if (QDF_IS_STATUS_ERROR(status)) {
1343 		wmi_err("Failed to send get SAR limit cmd: %d", status);
1344 		wmi_buf_free(wmi_buf);
1345 	}
1346 
1347 	wmi_debug("Exit");
1348 
1349 	return status;
1350 }
1351 
1352 /**
1353  * wmi_sar2_result_string() - return string conversion of sar2 result
1354  * @result: sar2 result value
1355  *
1356  * This utility function helps log string conversion of sar2 result.
1357  *
1358  * Return: string conversion of sar 2 result, if match found;
1359  *	   "Unknown response" otherwise.
1360  */
1361 static const char *wmi_sar2_result_string(uint32_t result)
1362 {
1363 	switch (result) {
1364 	CASE_RETURN_STRING(WMI_SAR2_SUCCESS);
1365 	CASE_RETURN_STRING(WMI_SAR2_INVALID_ANTENNA_INDEX);
1366 	CASE_RETURN_STRING(WMI_SAR2_INVALID_TABLE_INDEX);
1367 	CASE_RETURN_STRING(WMI_SAR2_STATE_ERROR);
1368 	CASE_RETURN_STRING(WMI_SAR2_BDF_NO_TABLE);
1369 	default:
1370 		return "Unknown response";
1371 	}
1372 }
1373 
1374 /**
1375  * extract_sar2_result_event_tlv() -  process sar response event from FW.
1376  * @handle: wma handle
1377  * @event: event buffer
1378  * @len: buffer length
1379  *
1380  * Return: 0 for success or error code
1381  */
1382 static QDF_STATUS extract_sar2_result_event_tlv(void *handle,
1383 						uint8_t *event,
1384 						uint32_t len)
1385 {
1386 	wmi_sar2_result_event_fixed_param *sar2_fixed_param;
1387 
1388 	WMI_SAR2_RESULT_EVENTID_param_tlvs *param_buf =
1389 		(WMI_SAR2_RESULT_EVENTID_param_tlvs *)event;
1390 
1391 	if (!param_buf) {
1392 		wmi_err("Invalid sar2 result event buffer");
1393 		return QDF_STATUS_E_INVAL;
1394 	}
1395 
1396 	sar2_fixed_param = param_buf->fixed_param;
1397 	if (!sar2_fixed_param) {
1398 		wmi_err("Invalid sar2 result event fixed param buffer");
1399 		return QDF_STATUS_E_INVAL;
1400 	}
1401 
1402 	wmi_debug("SAR2 result: %s",
1403 		 wmi_sar2_result_string(sar2_fixed_param->result));
1404 
1405 	return QDF_STATUS_SUCCESS;
1406 }
1407 
1408 static QDF_STATUS extract_sar_limit_event_tlv(wmi_unified_t wmi_handle,
1409 					      uint8_t *evt_buf,
1410 					      struct sar_limit_event *event)
1411 {
1412 	wmi_sar_get_limits_event_fixed_param *fixed_param;
1413 	WMI_SAR_GET_LIMITS_EVENTID_param_tlvs *param_buf;
1414 	wmi_sar_get_limit_event_row *row_in;
1415 	struct sar_limit_event_row *row_out;
1416 	uint32_t row;
1417 
1418 	if (!evt_buf) {
1419 		wmi_err("input event is NULL");
1420 		return QDF_STATUS_E_INVAL;
1421 	}
1422 	if (!event) {
1423 		wmi_err("output event is NULL");
1424 		return QDF_STATUS_E_INVAL;
1425 	}
1426 
1427 	param_buf = (WMI_SAR_GET_LIMITS_EVENTID_param_tlvs *)evt_buf;
1428 
1429 	fixed_param = param_buf->fixed_param;
1430 	if (!fixed_param) {
1431 		wmi_err("Invalid fixed param");
1432 		return QDF_STATUS_E_INVAL;
1433 	}
1434 
1435 	event->sar_enable = fixed_param->sar_enable;
1436 	event->num_limit_rows = fixed_param->num_limit_rows;
1437 
1438 	if (event->num_limit_rows > param_buf->num_sar_get_limits) {
1439 		wmi_err("Num rows %d exceeds sar_get_limits rows len %d",
1440 			 event->num_limit_rows, param_buf->num_sar_get_limits);
1441 		return QDF_STATUS_E_INVAL;
1442 	}
1443 
1444 	if (event->num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
1445 		QDF_ASSERT(0);
1446 		wmi_err("Num rows %d exceeds max of %d",
1447 			 event->num_limit_rows,
1448 			 MAX_SAR_LIMIT_ROWS_SUPPORTED);
1449 		event->num_limit_rows = MAX_SAR_LIMIT_ROWS_SUPPORTED;
1450 	}
1451 
1452 	row_in = param_buf->sar_get_limits;
1453 	if (!row_in) {
1454 		wmi_debug("sar_get_limits is NULL");
1455 	} else {
1456 		row_out = &event->sar_limit_row[0];
1457 		for (row = 0; row < event->num_limit_rows; row++) {
1458 			row_out->band_id = row_in->band_id;
1459 			row_out->chain_id = row_in->chain_id;
1460 			row_out->mod_id = row_in->mod_id;
1461 			row_out->limit_value = row_in->limit_value;
1462 			row_out++;
1463 			row_in++;
1464 		}
1465 	}
1466 
1467 	return QDF_STATUS_SUCCESS;
1468 }
1469 
1470 /**
1471  * send_set_del_pmkid_cache_cmd_tlv() - send wmi cmd of set del pmkid
1472  * @wmi_handle: wmi handler
1473  * @pmk_info: pointer to PMK cache entry
1474  * @vdev_id: vdev id
1475  *
1476  * Return: 0 for success and non zero for failure
1477  */
1478 static QDF_STATUS send_set_del_pmkid_cache_cmd_tlv(wmi_unified_t wmi_handle,
1479 				struct wmi_unified_pmk_cache *pmk_info)
1480 {
1481 	wmi_pdev_update_pmk_cache_cmd_fixed_param *cmd;
1482 	wmi_buf_t buf;
1483 	QDF_STATUS status;
1484 	uint8_t *buf_ptr;
1485 	wmi_pmk_cache *pmksa;
1486 	uint32_t len = sizeof(*cmd);
1487 
1488 	if (!pmk_info)
1489 		return QDF_STATUS_E_INVAL;
1490 
1491 	if (!pmk_info->is_flush_all)
1492 		len += WMI_TLV_HDR_SIZE + sizeof(*pmksa);
1493 
1494 	buf = wmi_buf_alloc(wmi_handle, len);
1495 	if (!buf) {
1496 		return QDF_STATUS_E_NOMEM;
1497 	}
1498 
1499 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1500 	cmd = (wmi_pdev_update_pmk_cache_cmd_fixed_param *) buf_ptr;
1501 
1502 	WMITLV_SET_HDR(&cmd->tlv_header,
1503 		 WMITLV_TAG_STRUC_wmi_pdev_update_pmk_cache_cmd_fixed_param,
1504 		 WMITLV_GET_STRUCT_TLVLEN(
1505 			wmi_pdev_update_pmk_cache_cmd_fixed_param));
1506 
1507 	cmd->vdev_id = pmk_info->vdev_id;
1508 
1509 	/* If pmk_info->is_flush_all is true, this is a flush request */
1510 	if (pmk_info->is_flush_all) {
1511 		cmd->op_flag = WMI_PMK_CACHE_OP_FLAG_FLUSH_ALL;
1512 		cmd->num_cache = 0;
1513 		goto send_cmd;
1514 	}
1515 
1516 	cmd->num_cache = 1;
1517 	buf_ptr += sizeof(*cmd);
1518 
1519 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
1520 			sizeof(*pmksa));
1521 	buf_ptr += WMI_TLV_HDR_SIZE;
1522 
1523 	pmksa = (wmi_pmk_cache *)buf_ptr;
1524 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_STRUC_wmi_pmk_cache,
1525 			WMITLV_GET_STRUCT_TLVLEN
1526 				(wmi_pmk_cache));
1527 	pmksa->pmk_len = pmk_info->pmk_len;
1528 	qdf_mem_copy(pmksa->pmk, pmk_info->pmk, pmksa->pmk_len);
1529 	pmksa->pmkid_len = pmk_info->pmkid_len;
1530 	qdf_mem_copy(pmksa->pmkid, pmk_info->pmkid, pmksa->pmkid_len);
1531 	qdf_mem_copy(&(pmksa->bssid), &(pmk_info->bssid), sizeof(wmi_mac_addr));
1532 	pmksa->ssid.ssid_len = pmk_info->ssid.length;
1533 	qdf_mem_copy(&(pmksa->ssid.ssid), &(pmk_info->ssid.ssid),
1534 		     pmksa->ssid.ssid_len);
1535 	pmksa->cache_id = pmk_info->cache_id;
1536 	pmksa->cat_flag = pmk_info->cat_flag;
1537 	pmksa->action_flag = pmk_info->action_flag;
1538 
1539 send_cmd:
1540 	wmi_mtrace(WMI_PDEV_UPDATE_PMK_CACHE_CMDID, cmd->vdev_id, 0);
1541 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
1542 				      WMI_PDEV_UPDATE_PMK_CACHE_CMDID);
1543 	if (status != QDF_STATUS_SUCCESS) {
1544 		wmi_err("Failed to send set del pmkid cache command %d",
1545 			status);
1546 		wmi_buf_free(buf);
1547 	}
1548 
1549 	return status;
1550 }
1551 
1552 /**
1553  * send_del_ts_cmd_tlv() - send DELTS request to fw
1554  * @wmi_handle: wmi handle
1555  * @msg: delts params
1556  *
1557  * Return: CDF status
1558  */
1559 static QDF_STATUS send_del_ts_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_id,
1560 				uint8_t ac)
1561 {
1562 	wmi_vdev_wmm_delts_cmd_fixed_param *cmd;
1563 	wmi_buf_t buf;
1564 	int32_t len = sizeof(*cmd);
1565 
1566 	buf = wmi_buf_alloc(wmi_handle, len);
1567 	if (!buf) {
1568 		return QDF_STATUS_E_NOMEM;
1569 	}
1570 	cmd = (wmi_vdev_wmm_delts_cmd_fixed_param *) wmi_buf_data(buf);
1571 	WMITLV_SET_HDR(&cmd->tlv_header,
1572 		       WMITLV_TAG_STRUC_wmi_vdev_wmm_delts_cmd_fixed_param,
1573 		       WMITLV_GET_STRUCT_TLVLEN
1574 			       (wmi_vdev_wmm_delts_cmd_fixed_param));
1575 	cmd->vdev_id = vdev_id;
1576 	cmd->ac = ac;
1577 
1578 	wmi_debug("Delts vdev:%d, ac:%d", cmd->vdev_id, cmd->ac);
1579 	wmi_mtrace(WMI_VDEV_WMM_DELTS_CMDID, cmd->vdev_id, 0);
1580 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
1581 				 WMI_VDEV_WMM_DELTS_CMDID)) {
1582 		wmi_err("Failed to send vdev DELTS command");
1583 		wmi_buf_free(buf);
1584 		return QDF_STATUS_E_FAILURE;
1585 	}
1586 
1587 	return QDF_STATUS_SUCCESS;
1588 }
1589 
1590 /**
1591  * send_aggr_qos_cmd_tlv() - send aggr qos request to fw
1592  * @wmi_handle: handle to wmi
1593  * @aggr_qos_rsp_msg - combined struct for all ADD_TS requests.
1594  *
1595  * A function to handle WMI_AGGR_QOS_REQ. This will send out
1596  * ADD_TS requests to firmware in loop for all the ACs with
1597  * active flow.
1598  *
1599  * Return: CDF status
1600  */
1601 static QDF_STATUS send_aggr_qos_cmd_tlv(wmi_unified_t wmi_handle,
1602 		      struct aggr_add_ts_param *aggr_qos_rsp_msg)
1603 {
1604 	int i = 0;
1605 	wmi_vdev_wmm_addts_cmd_fixed_param *cmd;
1606 	wmi_buf_t buf;
1607 	int32_t len = sizeof(*cmd);
1608 
1609 	for (i = 0; i < WMI_QOS_NUM_AC_MAX; i++) {
1610 		/* if flow in this AC is active */
1611 		if (((1 << i) & aggr_qos_rsp_msg->tspecIdx)) {
1612 			/*
1613 			 * as per implementation of wma_add_ts_req() we
1614 			 * are not waiting any response from firmware so
1615 			 * apart from sending ADDTS to firmware just send
1616 			 * success to upper layers
1617 			 */
1618 			aggr_qos_rsp_msg->status[i] = QDF_STATUS_SUCCESS;
1619 
1620 			buf = wmi_buf_alloc(wmi_handle, len);
1621 			if (!buf) {
1622 				return QDF_STATUS_E_NOMEM;
1623 			}
1624 			cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *)
1625 				wmi_buf_data(buf);
1626 			WMITLV_SET_HDR(&cmd->tlv_header,
1627 			       WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param,
1628 			       WMITLV_GET_STRUCT_TLVLEN
1629 				       (wmi_vdev_wmm_addts_cmd_fixed_param));
1630 			cmd->vdev_id = aggr_qos_rsp_msg->vdev_id;
1631 			cmd->ac =
1632 				WMI_TID_TO_AC(aggr_qos_rsp_msg->tspec[i].tsinfo.
1633 					      traffic.userPrio);
1634 			cmd->medium_time_us =
1635 				aggr_qos_rsp_msg->tspec[i].mediumTime * 32;
1636 			cmd->downgrade_type = WMM_AC_DOWNGRADE_DEPRIO;
1637 			wmi_debug("Addts vdev:%d, ac:%d, mediumTime:%d downgrade_type:%d",
1638 				 cmd->vdev_id, cmd->ac,
1639 				 cmd->medium_time_us, cmd->downgrade_type);
1640 			wmi_mtrace(WMI_VDEV_WMM_ADDTS_CMDID, cmd->vdev_id, 0);
1641 			if (wmi_unified_cmd_send(wmi_handle, buf, len,
1642 						 WMI_VDEV_WMM_ADDTS_CMDID)) {
1643 				wmi_err("Failed to send vdev ADDTS command");
1644 				aggr_qos_rsp_msg->status[i] =
1645 							QDF_STATUS_E_FAILURE;
1646 				wmi_buf_free(buf);
1647 				return QDF_STATUS_E_FAILURE;
1648 			}
1649 		}
1650 	}
1651 
1652 	return QDF_STATUS_SUCCESS;
1653 }
1654 
1655 /**
1656  * send_add_ts_cmd_tlv() - send ADDTS request to fw
1657  * @wmi_handle: wmi handle
1658  * @msg: ADDTS params
1659  *
1660  * Return: CDF status
1661  */
1662 static QDF_STATUS send_add_ts_cmd_tlv(wmi_unified_t wmi_handle,
1663 		 struct add_ts_param *msg)
1664 {
1665 	wmi_vdev_wmm_addts_cmd_fixed_param *cmd;
1666 	wmi_buf_t buf;
1667 	int32_t len = sizeof(*cmd);
1668 
1669 	msg->status = QDF_STATUS_SUCCESS;
1670 
1671 	buf = wmi_buf_alloc(wmi_handle, len);
1672 	if (!buf) {
1673 		return QDF_STATUS_E_NOMEM;
1674 	}
1675 	cmd = (wmi_vdev_wmm_addts_cmd_fixed_param *) wmi_buf_data(buf);
1676 	WMITLV_SET_HDR(&cmd->tlv_header,
1677 		       WMITLV_TAG_STRUC_wmi_vdev_wmm_addts_cmd_fixed_param,
1678 		       WMITLV_GET_STRUCT_TLVLEN
1679 			       (wmi_vdev_wmm_addts_cmd_fixed_param));
1680 	cmd->vdev_id = msg->vdev_id;
1681 	cmd->ac = msg->tspec.tsinfo.traffic.userPrio;
1682 	cmd->medium_time_us = msg->tspec.mediumTime * 32;
1683 	cmd->downgrade_type = WMM_AC_DOWNGRADE_DROP;
1684 	wmi_debug("Addts vdev:%d, ac:%d, mediumTime:%d, downgrade_type:%d",
1685 		 cmd->vdev_id, cmd->ac, cmd->medium_time_us,
1686 		 cmd->downgrade_type);
1687 	wmi_mtrace(WMI_VDEV_WMM_ADDTS_CMDID, cmd->vdev_id, 0);
1688 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
1689 				 WMI_VDEV_WMM_ADDTS_CMDID)) {
1690 		wmi_err("Failed to send vdev ADDTS command");
1691 		msg->status = QDF_STATUS_E_FAILURE;
1692 		wmi_buf_free(buf);
1693 		return QDF_STATUS_E_FAILURE;
1694 	}
1695 
1696 	return QDF_STATUS_SUCCESS;
1697 }
1698 
1699 /**
1700  * send_process_add_periodic_tx_ptrn_cmd_tlv() - add periodic tx pattern
1701  * @wmi_handle: wmi handle
1702  * @pattern: tx pattern params
1703  * @vdev_id: vdev id
1704  *
1705  * Return: QDF status
1706  */
1707 static QDF_STATUS send_process_add_periodic_tx_ptrn_cmd_tlv(
1708 					wmi_unified_t wmi_handle,
1709 					struct periodic_tx_pattern *pattern,
1710 					uint8_t vdev_id)
1711 {
1712 	WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *cmd;
1713 	wmi_buf_t wmi_buf;
1714 	uint32_t len;
1715 	uint8_t *buf_ptr;
1716 	uint32_t ptrn_len, ptrn_len_aligned;
1717 	int j;
1718 
1719 	ptrn_len = pattern->ucPtrnSize;
1720 	ptrn_len_aligned = roundup(ptrn_len, sizeof(uint32_t));
1721 	len = sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param) +
1722 	      WMI_TLV_HDR_SIZE + ptrn_len_aligned;
1723 
1724 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
1725 	if (!wmi_buf) {
1726 		return QDF_STATUS_E_NOMEM;
1727 	}
1728 
1729 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
1730 
1731 	cmd = (WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *) buf_ptr;
1732 	WMITLV_SET_HDR(&cmd->tlv_header,
1733 	       WMITLV_TAG_STRUC_WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param,
1734 	       WMITLV_GET_STRUCT_TLVLEN
1735 	       (WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param));
1736 
1737 	/* Pass the pattern id to delete for the corresponding vdev id */
1738 	cmd->vdev_id = vdev_id;
1739 	cmd->pattern_id = pattern->ucPtrnId;
1740 	cmd->timeout = pattern->usPtrnIntervalMs;
1741 	cmd->length = pattern->ucPtrnSize;
1742 
1743 	/* Pattern info */
1744 	buf_ptr += sizeof(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param);
1745 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ptrn_len_aligned);
1746 	buf_ptr += WMI_TLV_HDR_SIZE;
1747 	qdf_mem_copy(buf_ptr, pattern->ucPattern, ptrn_len);
1748 	for (j = 0; j < pattern->ucPtrnSize; j++)
1749 		wmi_debug("Add Ptrn: %02x", buf_ptr[j] & 0xff);
1750 
1751 	wmi_debug("Add ptrn id: %d vdev_id: %d",
1752 		 cmd->pattern_id, cmd->vdev_id);
1753 
1754 	wmi_mtrace(WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID, cmd->vdev_id, 0);
1755 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
1756 				 WMI_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID)) {
1757 		wmi_err("Failed to add pattern set state command");
1758 		wmi_buf_free(wmi_buf);
1759 		return QDF_STATUS_E_FAILURE;
1760 	}
1761 	return QDF_STATUS_SUCCESS;
1762 }
1763 
1764 /**
1765  * send_process_del_periodic_tx_ptrn_cmd_tlv() - del periodic tx pattern
1766  * @wmi_handle: wmi handle
1767  * @vdev_id: vdev id
1768  * @pattern_id: pattern id
1769  *
1770  * Return: QDF status
1771  */
1772 static QDF_STATUS send_process_del_periodic_tx_ptrn_cmd_tlv(
1773 						wmi_unified_t wmi_handle,
1774 						uint8_t vdev_id,
1775 						uint8_t pattern_id)
1776 {
1777 	WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *cmd;
1778 	wmi_buf_t wmi_buf;
1779 	uint32_t len =
1780 		sizeof(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param);
1781 
1782 	wmi_buf = wmi_buf_alloc(wmi_handle, len);
1783 	if (!wmi_buf) {
1784 		return QDF_STATUS_E_NOMEM;
1785 	}
1786 
1787 	cmd = (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param *)
1788 		wmi_buf_data(wmi_buf);
1789 	WMITLV_SET_HDR(&cmd->tlv_header,
1790 	       WMITLV_TAG_STRUC_WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param,
1791 	       WMITLV_GET_STRUCT_TLVLEN
1792 	       (WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD_fixed_param));
1793 
1794 	/* Pass the pattern id to delete for the corresponding vdev id */
1795 	cmd->vdev_id = vdev_id;
1796 	cmd->pattern_id = pattern_id;
1797 	wmi_debug("Del ptrn id: %d vdev_id: %d",
1798 		 cmd->pattern_id, cmd->vdev_id);
1799 
1800 	wmi_mtrace(WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID, cmd->vdev_id, 0);
1801 	if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
1802 				 WMI_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID)) {
1803 		wmi_err("Failed to send del pattern command");
1804 		wmi_buf_free(wmi_buf);
1805 		return QDF_STATUS_E_FAILURE;
1806 	}
1807 	return QDF_STATUS_SUCCESS;
1808 }
1809 
1810 /**
1811  * send_set_auto_shutdown_timer_cmd_tlv() - sets auto shutdown timer in firmware
1812  * @wmi_handle: wmi handle
1813  * @timer_val: auto shutdown timer value
1814  *
1815  * Return: CDF status
1816  */
1817 static QDF_STATUS send_set_auto_shutdown_timer_cmd_tlv(wmi_unified_t wmi_handle,
1818 						  uint32_t timer_val)
1819 {
1820 	QDF_STATUS status;
1821 	wmi_buf_t buf = NULL;
1822 	uint8_t *buf_ptr;
1823 	wmi_host_auto_shutdown_cfg_cmd_fixed_param *wmi_auto_sh_cmd;
1824 	int len = sizeof(wmi_host_auto_shutdown_cfg_cmd_fixed_param);
1825 
1826 	wmi_debug("Set WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID:TIMER_VAL=%d",
1827 		 timer_val);
1828 
1829 	buf = wmi_buf_alloc(wmi_handle, len);
1830 	if (!buf) {
1831 		return QDF_STATUS_E_NOMEM;
1832 	}
1833 
1834 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1835 	wmi_auto_sh_cmd =
1836 		(wmi_host_auto_shutdown_cfg_cmd_fixed_param *) buf_ptr;
1837 	wmi_auto_sh_cmd->timer_value = timer_val;
1838 
1839 	WMITLV_SET_HDR(&wmi_auto_sh_cmd->tlv_header,
1840 	       WMITLV_TAG_STRUC_wmi_host_auto_shutdown_cfg_cmd_fixed_param,
1841 	       WMITLV_GET_STRUCT_TLVLEN
1842 	       (wmi_host_auto_shutdown_cfg_cmd_fixed_param));
1843 
1844 	wmi_mtrace(WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID, NO_SESSION, 0);
1845 	status = wmi_unified_cmd_send(wmi_handle, buf,
1846 				      len, WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID);
1847 	if (QDF_IS_STATUS_ERROR(status)) {
1848 		wmi_err("WMI_HOST_AUTO_SHUTDOWN_CFG_CMDID Err %d", status);
1849 		wmi_buf_free(buf);
1850 	}
1851 
1852 	return status;
1853 }
1854 
1855 /**
1856  * send_set_led_flashing_cmd_tlv() - set led flashing in fw
1857  * @wmi_handle: wmi handle
1858  * @flashing: flashing request
1859  *
1860  * Return: CDF status
1861  */
1862 static QDF_STATUS send_set_led_flashing_cmd_tlv(wmi_unified_t wmi_handle,
1863 				struct flashing_req_params *flashing)
1864 {
1865 	wmi_set_led_flashing_cmd_fixed_param *cmd;
1866 	QDF_STATUS status;
1867 	wmi_buf_t buf;
1868 	uint8_t *buf_ptr;
1869 	int32_t len = sizeof(wmi_set_led_flashing_cmd_fixed_param);
1870 
1871 	buf = wmi_buf_alloc(wmi_handle, len);
1872 	if (!buf) {
1873 		return QDF_STATUS_E_NOMEM;
1874 	}
1875 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1876 	cmd = (wmi_set_led_flashing_cmd_fixed_param *) buf_ptr;
1877 	WMITLV_SET_HDR(&cmd->tlv_header,
1878 		       WMITLV_TAG_STRUC_wmi_set_led_flashing_cmd_fixed_param,
1879 		       WMITLV_GET_STRUCT_TLVLEN
1880 			       (wmi_set_led_flashing_cmd_fixed_param));
1881 	cmd->pattern_id = flashing->pattern_id;
1882 	cmd->led_x0 = flashing->led_x0;
1883 	cmd->led_x1 = flashing->led_x1;
1884 
1885 	wmi_mtrace(WMI_PDEV_SET_LED_FLASHING_CMDID, NO_SESSION, 0);
1886 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
1887 				      WMI_PDEV_SET_LED_FLASHING_CMDID);
1888 	if (QDF_IS_STATUS_ERROR(status)) {
1889 		wmi_err("wmi_unified_cmd_send WMI_PEER_SET_PARAM_CMD"
1890 			 " returned Error %d", status);
1891 		wmi_buf_free(buf);
1892 	}
1893 
1894 	return status;
1895 }
1896 
1897 /**
1898  * send_process_ch_avoid_update_cmd_tlv() - handles channel avoid update request
1899  * @wmi_handle: wmi handle
1900  * @ch_avoid_update_req: channel avoid update params
1901  *
1902  * Return: CDF status
1903  */
1904 static QDF_STATUS send_process_ch_avoid_update_cmd_tlv(wmi_unified_t wmi_handle)
1905 {
1906 	QDF_STATUS status;
1907 	wmi_buf_t buf = NULL;
1908 	uint8_t *buf_ptr;
1909 	wmi_chan_avoid_update_cmd_param *ch_avoid_update_fp;
1910 	int len = sizeof(wmi_chan_avoid_update_cmd_param);
1911 
1912 	buf = wmi_buf_alloc(wmi_handle, len);
1913 	if (!buf) {
1914 		return QDF_STATUS_E_NOMEM;
1915 	}
1916 
1917 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1918 	ch_avoid_update_fp = (wmi_chan_avoid_update_cmd_param *) buf_ptr;
1919 	WMITLV_SET_HDR(&ch_avoid_update_fp->tlv_header,
1920 		       WMITLV_TAG_STRUC_wmi_chan_avoid_update_cmd_param,
1921 		       WMITLV_GET_STRUCT_TLVLEN
1922 			       (wmi_chan_avoid_update_cmd_param));
1923 
1924 	wmi_mtrace(WMI_CHAN_AVOID_UPDATE_CMDID, NO_SESSION, 0);
1925 	status = wmi_unified_cmd_send(wmi_handle, buf,
1926 				      len, WMI_CHAN_AVOID_UPDATE_CMDID);
1927 	if (QDF_IS_STATUS_ERROR(status)) {
1928 		wmi_err("wmi_unified_cmd_send"
1929 			" WMITLV_TABLE_WMI_CHAN_AVOID_UPDATE"
1930 			" returned Error %d", status);
1931 		wmi_buf_free(buf);
1932 	}
1933 
1934 	return status;
1935 }
1936 
1937 /**
1938  * send_pdev_set_pcl_cmd_tlv() - Send WMI_SOC_SET_PCL_CMDID to FW
1939  * @wmi_handle: wmi handle
1940  * @msg: PCL structure containing the PCL and the number of channels
1941  *
1942  * WMI_PDEV_SET_PCL_CMDID provides a Preferred Channel List (PCL) to the WLAN
1943  * firmware. The DBS Manager is the consumer of this information in the WLAN
1944  * firmware. The channel list will be used when a Virtual DEVice (VDEV) needs
1945  * to migrate to a new channel without host driver involvement. An example of
1946  * this behavior is Legacy Fast Roaming (LFR 3.0). Generally, the host will
1947  * manage the channel selection without firmware involvement.
1948  *
1949  * WMI_PDEV_SET_PCL_CMDID will carry only the weight list and not the actual
1950  * channel list. The weights corresponds to the channels sent in
1951  * WMI_SCAN_CHAN_LIST_CMDID. The channels from PCL would be having a higher
1952  * weightage compared to the non PCL channels.
1953  *
1954  * Return: Success if the cmd is sent successfully to the firmware
1955  */
1956 static QDF_STATUS send_pdev_set_pcl_cmd_tlv(wmi_unified_t wmi_handle,
1957 				struct wmi_pcl_chan_weights *msg)
1958 {
1959 	wmi_pdev_set_pcl_cmd_fixed_param *cmd;
1960 	wmi_buf_t buf;
1961 	uint8_t *buf_ptr;
1962 	uint32_t *cmd_args, i, len;
1963 	uint32_t chan_len;
1964 
1965 	chan_len = msg->saved_num_chan;
1966 
1967 	len = sizeof(*cmd) +
1968 		WMI_TLV_HDR_SIZE + (chan_len * sizeof(uint32_t));
1969 
1970 	buf = wmi_buf_alloc(wmi_handle, len);
1971 	if (!buf) {
1972 		return QDF_STATUS_E_NOMEM;
1973 	}
1974 
1975 	cmd = (wmi_pdev_set_pcl_cmd_fixed_param *) wmi_buf_data(buf);
1976 	buf_ptr = (uint8_t *) cmd;
1977 	WMITLV_SET_HDR(&cmd->tlv_header,
1978 		WMITLV_TAG_STRUC_wmi_pdev_set_pcl_cmd_fixed_param,
1979 		WMITLV_GET_STRUCT_TLVLEN(wmi_pdev_set_pcl_cmd_fixed_param));
1980 
1981 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
1982 							wmi_handle,
1983 							WMI_HOST_PDEV_ID_SOC);
1984 	cmd->num_chan = chan_len;
1985 	buf_ptr += sizeof(wmi_pdev_set_pcl_cmd_fixed_param);
1986 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1987 			(chan_len * sizeof(uint32_t)));
1988 	cmd_args = (uint32_t *) (buf_ptr + WMI_TLV_HDR_SIZE);
1989 	for (i = 0; i < chan_len ; i++)
1990 		cmd_args[i] = msg->weighed_valid_list[i];
1991 	wmi_mtrace(WMI_PDEV_SET_PCL_CMDID, NO_SESSION, 0);
1992 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
1993 				 WMI_PDEV_SET_PCL_CMDID)) {
1994 		wmi_err("Failed to send WMI_PDEV_SET_PCL_CMDID");
1995 		wmi_buf_free(buf);
1996 		return QDF_STATUS_E_FAILURE;
1997 	}
1998 	return QDF_STATUS_SUCCESS;
1999 }
2000 
2001 #ifdef WLAN_POLICY_MGR_ENABLE
2002 /**
2003  * send_pdev_set_dual_mac_config_cmd_tlv() - Set dual mac config to FW
2004  * @wmi_handle: wmi handle
2005  * @msg: Dual MAC config parameters
2006  *
2007  * Configures WLAN firmware with the dual MAC features
2008  *
2009  * Return: QDF_STATUS. 0 on success.
2010  */
2011 static
2012 QDF_STATUS send_pdev_set_dual_mac_config_cmd_tlv(wmi_unified_t wmi_handle,
2013 		struct policy_mgr_dual_mac_config *msg)
2014 {
2015 	wmi_pdev_set_mac_config_cmd_fixed_param *cmd;
2016 	wmi_buf_t buf;
2017 	uint32_t len;
2018 
2019 	len = sizeof(*cmd);
2020 
2021 	buf = wmi_buf_alloc(wmi_handle, len);
2022 	if (!buf) {
2023 		return QDF_STATUS_E_FAILURE;
2024 	}
2025 
2026 	cmd = (wmi_pdev_set_mac_config_cmd_fixed_param *) wmi_buf_data(buf);
2027 	WMITLV_SET_HDR(&cmd->tlv_header,
2028 		WMITLV_TAG_STRUC_wmi_pdev_set_mac_config_cmd_fixed_param,
2029 		WMITLV_GET_STRUCT_TLVLEN(
2030 			wmi_pdev_set_mac_config_cmd_fixed_param));
2031 
2032 	cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
2033 							wmi_handle,
2034 							WMI_HOST_PDEV_ID_SOC);
2035 	cmd->concurrent_scan_config_bits = msg->scan_config;
2036 	cmd->fw_mode_config_bits = msg->fw_mode_config;
2037 	wmi_debug("scan_config:%x fw_mode_config:%x",
2038 		 msg->scan_config, msg->fw_mode_config);
2039 
2040 	wmi_mtrace(WMI_PDEV_SET_MAC_CONFIG_CMDID, NO_SESSION, 0);
2041 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
2042 				 WMI_PDEV_SET_MAC_CONFIG_CMDID)) {
2043 		wmi_err("Failed to send WMI_PDEV_SET_MAC_CONFIG_CMDID");
2044 		wmi_buf_free(buf);
2045 		return QDF_STATUS_E_FAILURE;
2046 	}
2047 	return QDF_STATUS_SUCCESS;
2048 }
2049 
2050 void wmi_policy_mgr_attach_tlv(struct wmi_unified *wmi_handle)
2051 {
2052 	struct wmi_ops *ops = wmi_handle->ops;
2053 
2054 	ops->send_pdev_set_dual_mac_config_cmd =
2055 		send_pdev_set_dual_mac_config_cmd_tlv;
2056 }
2057 #endif /* WLAN_POLICY_MGR_ENABLE */
2058 
2059 /**
2060  * send_adapt_dwelltime_params_cmd_tlv() - send wmi cmd of adaptive dwelltime
2061  * configuration params
2062  * @wma_handle:  wma handler
2063  * @dwelltime_params: pointer to dwelltime_params
2064  *
2065  * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure
2066  */
2067 static
2068 QDF_STATUS send_adapt_dwelltime_params_cmd_tlv(wmi_unified_t wmi_handle,
2069 		struct wmi_adaptive_dwelltime_params *dwelltime_params)
2070 {
2071 	wmi_scan_adaptive_dwell_config_fixed_param *dwell_param;
2072 	wmi_scan_adaptive_dwell_parameters_tlv *cmd;
2073 	wmi_buf_t buf;
2074 	uint8_t *buf_ptr;
2075 	int32_t err;
2076 	int len;
2077 
2078 	len = sizeof(wmi_scan_adaptive_dwell_config_fixed_param);
2079 	len += WMI_TLV_HDR_SIZE; /* TLV for ext_thresholds*/
2080 	len += sizeof(wmi_scan_adaptive_dwell_parameters_tlv);
2081 	buf = wmi_buf_alloc(wmi_handle, len);
2082 	if (!buf) {
2083 		return QDF_STATUS_E_NOMEM;
2084 	}
2085 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
2086 	dwell_param = (wmi_scan_adaptive_dwell_config_fixed_param *) buf_ptr;
2087 	WMITLV_SET_HDR(&dwell_param->tlv_header,
2088 		WMITLV_TAG_STRUC_wmi_scan_adaptive_dwell_config_fixed_param,
2089 		WMITLV_GET_STRUCT_TLVLEN
2090 		(wmi_scan_adaptive_dwell_config_fixed_param));
2091 
2092 	dwell_param->enable = dwelltime_params->is_enabled;
2093 	buf_ptr += sizeof(wmi_scan_adaptive_dwell_config_fixed_param);
2094 	WMITLV_SET_HDR(buf_ptr,
2095 		       WMITLV_TAG_ARRAY_STRUC,
2096 		       sizeof(wmi_scan_adaptive_dwell_parameters_tlv));
2097 	buf_ptr += WMI_TLV_HDR_SIZE;
2098 
2099 	cmd = (wmi_scan_adaptive_dwell_parameters_tlv *) buf_ptr;
2100 	WMITLV_SET_HDR(&cmd->tlv_header,
2101 		       WMITLV_TAG_STRUC_wmi_scan_adaptive_dwell_parameters_tlv,
2102 		       WMITLV_GET_STRUCT_TLVLEN(
2103 		       wmi_scan_adaptive_dwell_parameters_tlv));
2104 
2105 	cmd->default_adaptive_dwell_mode = dwelltime_params->dwelltime_mode;
2106 	cmd->adapative_lpf_weight = dwelltime_params->lpf_weight;
2107 	cmd->passive_monitor_interval_ms = dwelltime_params->passive_mon_intval;
2108 	cmd->wifi_activity_threshold_pct = dwelltime_params->wifi_act_threshold;
2109 	wmi_mtrace(WMI_SCAN_ADAPTIVE_DWELL_CONFIG_CMDID, NO_SESSION, 0);
2110 	err = wmi_unified_cmd_send(wmi_handle, buf,
2111 				   len, WMI_SCAN_ADAPTIVE_DWELL_CONFIG_CMDID);
2112 	if (err) {
2113 		wmi_err("Failed to send adapt dwelltime cmd err=%d", err);
2114 		wmi_buf_free(buf);
2115 		return QDF_STATUS_E_FAILURE;
2116 	}
2117 
2118 	return QDF_STATUS_SUCCESS;
2119 }
2120 
2121 /**
2122  * send_dbs_scan_sel_params_cmd_tlv() - send wmi cmd of DBS scan selection
2123  * configuration params
2124  * @wmi_handle: wmi handler
2125  * @dbs_scan_params: pointer to wmi_dbs_scan_sel_params
2126  *
2127  * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure
2128  */
2129 static QDF_STATUS send_dbs_scan_sel_params_cmd_tlv(wmi_unified_t wmi_handle,
2130 			struct wmi_dbs_scan_sel_params *dbs_scan_params)
2131 {
2132 	wmi_scan_dbs_duty_cycle_fixed_param *dbs_scan_param;
2133 	wmi_scan_dbs_duty_cycle_tlv_param *cmd;
2134 	wmi_buf_t buf;
2135 	uint8_t *buf_ptr;
2136 	QDF_STATUS err;
2137 	uint32_t i;
2138 	int len;
2139 
2140 	len = sizeof(*dbs_scan_param);
2141 	len += WMI_TLV_HDR_SIZE;
2142 	len += dbs_scan_params->num_clients * sizeof(*cmd);
2143 
2144 	buf = wmi_buf_alloc(wmi_handle, len);
2145 	if (!buf) {
2146 		return QDF_STATUS_E_NOMEM;
2147 	}
2148 
2149 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
2150 	dbs_scan_param = (wmi_scan_dbs_duty_cycle_fixed_param *) buf_ptr;
2151 	WMITLV_SET_HDR(&dbs_scan_param->tlv_header,
2152 		       WMITLV_TAG_STRUC_wmi_scan_dbs_duty_cycle_fixed_param,
2153 		       WMITLV_GET_STRUCT_TLVLEN
2154 				(wmi_scan_dbs_duty_cycle_fixed_param));
2155 
2156 	dbs_scan_param->num_clients = dbs_scan_params->num_clients;
2157 	dbs_scan_param->pdev_id = dbs_scan_params->pdev_id;
2158 	buf_ptr += sizeof(*dbs_scan_param);
2159 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
2160 		       (sizeof(*cmd) * dbs_scan_params->num_clients));
2161 	buf_ptr = buf_ptr + (uint8_t) WMI_TLV_HDR_SIZE;
2162 
2163 	for (i = 0; i < dbs_scan_params->num_clients; i++) {
2164 		cmd = (wmi_scan_dbs_duty_cycle_tlv_param *) buf_ptr;
2165 		WMITLV_SET_HDR(&cmd->tlv_header,
2166 			WMITLV_TAG_STRUC_wmi_scan_dbs_duty_cycle_param_tlv,
2167 			WMITLV_GET_STRUCT_TLVLEN(
2168 					wmi_scan_dbs_duty_cycle_tlv_param));
2169 		cmd->module_id = dbs_scan_params->module_id[i];
2170 		cmd->num_dbs_scans = dbs_scan_params->num_dbs_scans[i];
2171 		cmd->num_non_dbs_scans = dbs_scan_params->num_non_dbs_scans[i];
2172 		buf_ptr = buf_ptr + (uint8_t) sizeof(*cmd);
2173 	}
2174 
2175 	wmi_mtrace(WMI_SET_SCAN_DBS_DUTY_CYCLE_CMDID, NO_SESSION, 0);
2176 	err = wmi_unified_cmd_send(wmi_handle, buf,
2177 				   len, WMI_SET_SCAN_DBS_DUTY_CYCLE_CMDID);
2178 	if (QDF_IS_STATUS_ERROR(err)) {
2179 		wmi_err("Failed to send dbs scan selection cmd err=%d", err);
2180 		wmi_buf_free(buf);
2181 		return QDF_STATUS_E_FAILURE;
2182 	}
2183 
2184 	return QDF_STATUS_SUCCESS;
2185 }
2186 
2187 /**
2188  * send_set_arp_stats_req_cmd_tlv() - send wmi cmd to set arp stats request
2189  * @wmi_handle: wmi handler
2190  * @req_buf: set arp stats request buffer
2191  *
2192  * Return: 0 for success and non zero for failure
2193  */
2194 static QDF_STATUS send_set_arp_stats_req_cmd_tlv(wmi_unified_t wmi_handle,
2195 					  struct set_arp_stats *req_buf)
2196 {
2197 	wmi_buf_t buf = NULL;
2198 	QDF_STATUS status;
2199 	int len;
2200 	uint8_t *buf_ptr;
2201 	wmi_vdev_set_arp_stats_cmd_fixed_param *wmi_set_arp;
2202 
2203 	len = sizeof(wmi_vdev_set_arp_stats_cmd_fixed_param);
2204 	if (req_buf->pkt_type_bitmap) {
2205 		len += WMI_TLV_HDR_SIZE;
2206 		len += sizeof(wmi_vdev_set_connectivity_check_stats);
2207 	}
2208 	buf = wmi_buf_alloc(wmi_handle, len);
2209 	if (!buf) {
2210 		return QDF_STATUS_E_NOMEM;
2211 	}
2212 
2213 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
2214 	wmi_set_arp =
2215 		(wmi_vdev_set_arp_stats_cmd_fixed_param *) buf_ptr;
2216 	WMITLV_SET_HDR(&wmi_set_arp->tlv_header,
2217 		       WMITLV_TAG_STRUC_wmi_vdev_set_arp_stats_cmd_fixed_param,
2218 		       WMITLV_GET_STRUCT_TLVLEN
2219 				(wmi_vdev_set_arp_stats_cmd_fixed_param));
2220 
2221 	/* fill in per roam config values */
2222 	wmi_set_arp->vdev_id = req_buf->vdev_id;
2223 
2224 	wmi_set_arp->set_clr = req_buf->flag;
2225 	wmi_set_arp->pkt_type = req_buf->pkt_type;
2226 	wmi_set_arp->ipv4 = req_buf->ip_addr;
2227 
2228 	wmi_debug("NUD Stats: vdev_id %u set_clr %u pkt_type:%u ipv4 %u",
2229 		 wmi_set_arp->vdev_id, wmi_set_arp->set_clr,
2230 		 wmi_set_arp->pkt_type, wmi_set_arp->ipv4);
2231 
2232 	/*
2233 	 * pkt_type_bitmap should be non-zero to ensure
2234 	 * presence of additional stats.
2235 	 */
2236 	if (req_buf->pkt_type_bitmap) {
2237 		wmi_vdev_set_connectivity_check_stats *wmi_set_connect_stats;
2238 
2239 		buf_ptr += sizeof(wmi_vdev_set_arp_stats_cmd_fixed_param);
2240 		WMITLV_SET_HDR(buf_ptr,
2241 			       WMITLV_TAG_ARRAY_STRUC,
2242 			       sizeof(wmi_vdev_set_connectivity_check_stats));
2243 		buf_ptr += WMI_TLV_HDR_SIZE;
2244 		wmi_set_connect_stats =
2245 			(wmi_vdev_set_connectivity_check_stats *)buf_ptr;
2246 		WMITLV_SET_HDR(&wmi_set_connect_stats->tlv_header,
2247 			WMITLV_TAG_STRUC_wmi_vdev_set_connectivity_check_stats,
2248 			WMITLV_GET_STRUCT_TLVLEN(
2249 					wmi_vdev_set_connectivity_check_stats));
2250 		wmi_set_connect_stats->pkt_type_bitmap =
2251 						req_buf->pkt_type_bitmap;
2252 		wmi_set_connect_stats->tcp_src_port = req_buf->tcp_src_port;
2253 		wmi_set_connect_stats->tcp_dst_port = req_buf->tcp_dst_port;
2254 		wmi_set_connect_stats->icmp_ipv4 = req_buf->icmp_ipv4;
2255 
2256 		wmi_debug("Connectivity Stats: pkt_type_bitmap %u tcp_src_port:%u tcp_dst_port %u icmp_ipv4 %u",
2257 			 wmi_set_connect_stats->pkt_type_bitmap,
2258 			 wmi_set_connect_stats->tcp_src_port,
2259 			 wmi_set_connect_stats->tcp_dst_port,
2260 			 wmi_set_connect_stats->icmp_ipv4);
2261 	}
2262 
2263 	/* Send per roam config parameters */
2264 	wmi_mtrace(WMI_VDEV_SET_ARP_STAT_CMDID, NO_SESSION, 0);
2265 	status = wmi_unified_cmd_send(wmi_handle, buf,
2266 				      len, WMI_VDEV_SET_ARP_STAT_CMDID);
2267 	if (QDF_IS_STATUS_ERROR(status)) {
2268 		wmi_err("WMI_SET_ARP_STATS_CMDID failed, Error %d", status);
2269 		goto error;
2270 	}
2271 
2272 	wmi_debug("set arp stats flag=%d, vdev=%d",
2273 		 req_buf->flag, req_buf->vdev_id);
2274 	return QDF_STATUS_SUCCESS;
2275 error:
2276 	wmi_buf_free(buf);
2277 
2278 	return status;
2279 }
2280 
2281 /**
2282  * send_get_arp_stats_req_cmd_tlv() - send wmi cmd to get arp stats request
2283  * @wmi_handle: wmi handler
2284  * @req_buf: get arp stats request buffer
2285  *
2286  * Return: 0 for success and non zero for failure
2287  */
2288 static QDF_STATUS send_get_arp_stats_req_cmd_tlv(wmi_unified_t wmi_handle,
2289 					  struct get_arp_stats *req_buf)
2290 {
2291 	wmi_buf_t buf = NULL;
2292 	QDF_STATUS status;
2293 	int len;
2294 	uint8_t *buf_ptr;
2295 	wmi_vdev_get_arp_stats_cmd_fixed_param *get_arp_stats;
2296 
2297 	len = sizeof(wmi_vdev_get_arp_stats_cmd_fixed_param);
2298 	buf = wmi_buf_alloc(wmi_handle, len);
2299 	if (!buf) {
2300 		return QDF_STATUS_E_NOMEM;
2301 	}
2302 
2303 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
2304 	get_arp_stats =
2305 		(wmi_vdev_get_arp_stats_cmd_fixed_param *) buf_ptr;
2306 	WMITLV_SET_HDR(&get_arp_stats->tlv_header,
2307 		       WMITLV_TAG_STRUC_wmi_vdev_get_arp_stats_cmd_fixed_param,
2308 		       WMITLV_GET_STRUCT_TLVLEN
2309 				(wmi_vdev_get_arp_stats_cmd_fixed_param));
2310 
2311 	/* fill in arp stats req cmd values */
2312 	get_arp_stats->vdev_id = req_buf->vdev_id;
2313 
2314 	wmi_debug("vdev=%d", req_buf->vdev_id);
2315 	/* Send per roam config parameters */
2316 	wmi_mtrace(WMI_VDEV_GET_ARP_STAT_CMDID, NO_SESSION, 0);
2317 	status = wmi_unified_cmd_send(wmi_handle, buf,
2318 				      len, WMI_VDEV_GET_ARP_STAT_CMDID);
2319 	if (QDF_IS_STATUS_ERROR(status)) {
2320 		wmi_err("WMI_GET_ARP_STATS_CMDID failed, Error %d", status);
2321 		goto error;
2322 	}
2323 
2324 	return QDF_STATUS_SUCCESS;
2325 error:
2326 	wmi_buf_free(buf);
2327 
2328 	return status;
2329 }
2330 
2331 /**
2332  * send_peer_unmap_conf_cmd_tlv() - send PEER UNMAP conf command to fw
2333  * @wmi: wmi handle
2334  * @vdev_id: vdev id
2335  * @peer_id_cnt: no. of peer ids
2336  * @peer_id_list: list of peer ids
2337  *
2338  * Return: QDF_STATUS_SUCCESS for success or error code
2339  */
2340 static QDF_STATUS send_peer_unmap_conf_cmd_tlv(wmi_unified_t wmi,
2341 					       uint8_t vdev_id,
2342 					       uint32_t peer_id_cnt,
2343 					       uint16_t *peer_id_list)
2344 {
2345 	int i;
2346 	wmi_buf_t buf;
2347 	uint8_t *buf_ptr;
2348 	A_UINT32 *peer_ids;
2349 	wmi_peer_unmap_response_cmd_fixed_param *cmd;
2350 	uint32_t peer_id_list_len;
2351 	uint32_t len = sizeof(*cmd);
2352 	QDF_STATUS status;
2353 
2354 	if (!peer_id_cnt || !peer_id_list)
2355 		return QDF_STATUS_E_FAILURE;
2356 
2357 	len += WMI_TLV_HDR_SIZE;
2358 
2359 	peer_id_list_len = peer_id_cnt * sizeof(A_UINT32);
2360 
2361 	len += peer_id_list_len;
2362 
2363 	buf = wmi_buf_alloc(wmi, len);
2364 
2365 	if (!buf) {
2366 		wmi_err("wmi_buf_alloc failed");
2367 		return QDF_STATUS_E_NOMEM;
2368 	}
2369 
2370 	cmd = (wmi_peer_unmap_response_cmd_fixed_param *)wmi_buf_data(buf);
2371 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
2372 
2373 	WMITLV_SET_HDR(&cmd->tlv_header,
2374 		       WMITLV_TAG_STRUC_wmi_peer_unmap_response_cmd_fixed_param,
2375 		       WMITLV_GET_STRUCT_TLVLEN
2376 			       (wmi_peer_unmap_response_cmd_fixed_param));
2377 
2378 	buf_ptr += sizeof(wmi_peer_unmap_response_cmd_fixed_param);
2379 
2380 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
2381 		       peer_id_list_len);
2382 
2383 	peer_ids = (A_UINT32 *)(buf_ptr + WMI_TLV_HDR_SIZE);
2384 
2385 	for (i = 0; i < peer_id_cnt; i++)
2386 		peer_ids[i] = peer_id_list[i];
2387 
2388 	wmi_debug("vdev_id %d peer_id_cnt %d", vdev_id, peer_id_cnt);
2389 	wmi_mtrace(WMI_PEER_UNMAP_RESPONSE_CMDID, vdev_id, 0);
2390 	status = wmi_unified_cmd_send(wmi, buf, len,
2391 				      WMI_PEER_UNMAP_RESPONSE_CMDID);
2392 	if (QDF_IS_STATUS_ERROR(status)) {
2393 		wmi_err("Failed to send peer unmap conf command: Err[%d]",
2394 			 status);
2395 		wmi_buf_free(buf);
2396 		return status;
2397 	}
2398 
2399 	return QDF_STATUS_SUCCESS;
2400 }
2401 
2402 void wmi_sta_attach_tlv(wmi_unified_t wmi_handle)
2403 {
2404 	struct wmi_ops *ops = wmi_handle->ops;
2405 
2406 	ops->send_set_sta_sa_query_param_cmd =
2407 		send_set_sta_sa_query_param_cmd_tlv;
2408 	ops->send_set_sta_keep_alive_cmd = send_set_sta_keep_alive_cmd_tlv;
2409 	ops->send_vdev_set_gtx_cfg_cmd = send_vdev_set_gtx_cfg_cmd_tlv;
2410 	ops->send_process_dhcp_ind_cmd = send_process_dhcp_ind_cmd_tlv;
2411 	ops->send_get_link_speed_cmd = send_get_link_speed_cmd_tlv;
2412 	ops->send_fw_profiling_cmd = send_fw_profiling_cmd_tlv;
2413 	ops->send_nat_keepalive_en_cmd = send_nat_keepalive_en_cmd_tlv;
2414 	ops->send_wlm_latency_level_cmd = send_wlm_latency_level_cmd_tlv;
2415 	ops->send_process_set_ie_info_cmd = send_process_set_ie_info_cmd_tlv;
2416 	ops->send_set_base_macaddr_indicate_cmd =
2417 		 send_set_base_macaddr_indicate_cmd_tlv;
2418 	ops->send_sar_limit_cmd = send_sar_limit_cmd_tlv;
2419 	ops->get_sar_limit_cmd = get_sar_limit_cmd_tlv;
2420 	ops->extract_sar_limit_event = extract_sar_limit_event_tlv;
2421 	ops->extract_sar2_result_event = extract_sar2_result_event_tlv;
2422 	ops->send_set_del_pmkid_cache_cmd = send_set_del_pmkid_cache_cmd_tlv;
2423 	ops->send_del_ts_cmd = send_del_ts_cmd_tlv;
2424 	ops->send_aggr_qos_cmd = send_aggr_qos_cmd_tlv;
2425 	ops->send_add_ts_cmd = send_add_ts_cmd_tlv;
2426 	ops->send_process_add_periodic_tx_ptrn_cmd =
2427 		send_process_add_periodic_tx_ptrn_cmd_tlv;
2428 	ops->send_process_del_periodic_tx_ptrn_cmd =
2429 		send_process_del_periodic_tx_ptrn_cmd_tlv;
2430 	ops->send_set_auto_shutdown_timer_cmd =
2431 		send_set_auto_shutdown_timer_cmd_tlv;
2432 	ops->send_set_led_flashing_cmd = send_set_led_flashing_cmd_tlv;
2433 	ops->send_process_ch_avoid_update_cmd =
2434 		send_process_ch_avoid_update_cmd_tlv;
2435 	ops->send_pdev_set_pcl_cmd = send_pdev_set_pcl_cmd_tlv;
2436 	ops->send_adapt_dwelltime_params_cmd =
2437 		send_adapt_dwelltime_params_cmd_tlv;
2438 	ops->send_dbs_scan_sel_params_cmd =
2439 		send_dbs_scan_sel_params_cmd_tlv;
2440 	ops->send_set_arp_stats_req_cmd = send_set_arp_stats_req_cmd_tlv;
2441 	ops->send_get_arp_stats_req_cmd = send_get_arp_stats_req_cmd_tlv;
2442 	ops->send_peer_unmap_conf_cmd = send_peer_unmap_conf_cmd_tlv;
2443 
2444 	wmi_tdls_attach_tlv(wmi_handle);
2445 	wmi_policy_mgr_attach_tlv(wmi_handle);
2446 	wmi_blacklist_mgr_attach_tlv(wmi_handle);
2447 }
2448 
2449