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