xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_pmo_tlv.c (revision 91f4b92931d69a209476018f97baf5ae3672e84d)
1 /*
2  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <osdep.h>
21 #include "wmi.h"
22 #include "wmi_unified_priv.h"
23 #include "wmi_unified_pmo_api.h"
24 
25 #ifdef FEATURE_WLAN_D0WOW
26 /**
27  *  send_d0wow_enable_cmd_tlv() - WMI d0 wow enable function
28  *  @wmi_handle: handle to WMI.
29  *  @mac_id: radio context
30  *
31  *  Return: 0  on success  and  error code on failure.
32  */
33 static QDF_STATUS send_d0wow_enable_cmd_tlv(wmi_unified_t wmi_handle,
34 					    uint8_t mac_id)
35 {
36 	wmi_d0_wow_enable_disable_cmd_fixed_param *cmd;
37 	wmi_buf_t buf;
38 	int32_t len;
39 	QDF_STATUS status;
40 
41 	len = sizeof(wmi_d0_wow_enable_disable_cmd_fixed_param);
42 
43 	buf = wmi_buf_alloc(wmi_handle, len);
44 	if (!buf) {
45 		return QDF_STATUS_E_NOMEM;
46 	}
47 	cmd = (wmi_d0_wow_enable_disable_cmd_fixed_param *) wmi_buf_data(buf);
48 	WMITLV_SET_HDR(&cmd->tlv_header,
49 		WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param,
50 		WMITLV_GET_STRUCT_TLVLEN
51 			(wmi_d0_wow_enable_disable_cmd_fixed_param));
52 
53 	cmd->enable = true;
54 
55 	wmi_mtrace(WMI_D0_WOW_ENABLE_DISABLE_CMDID, NO_SESSION, 0);
56 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
57 				      WMI_D0_WOW_ENABLE_DISABLE_CMDID);
58 	if (QDF_IS_STATUS_ERROR(status))
59 		wmi_buf_free(buf);
60 
61 	return status;
62 }
63 
64 /**
65  *  send_d0wow_disable_cmd_tlv() - WMI d0 wow disable function
66  *  @wmi_handle: handle to WMI.
67  *  @mac_id: radio context
68  *
69  *  Return: 0  on success  and  error code on failure.
70  */
71 static QDF_STATUS send_d0wow_disable_cmd_tlv(wmi_unified_t wmi_handle,
72 					     uint8_t mac_id)
73 {
74 	wmi_d0_wow_enable_disable_cmd_fixed_param *cmd;
75 	wmi_buf_t buf;
76 	int32_t len;
77 	QDF_STATUS status;
78 
79 	len = sizeof(wmi_d0_wow_enable_disable_cmd_fixed_param);
80 
81 	buf = wmi_buf_alloc(wmi_handle, len);
82 	if (!buf) {
83 		return QDF_STATUS_E_NOMEM;
84 	}
85 	cmd = (wmi_d0_wow_enable_disable_cmd_fixed_param *) wmi_buf_data(buf);
86 	WMITLV_SET_HDR(&cmd->tlv_header,
87 		WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param,
88 		WMITLV_GET_STRUCT_TLVLEN
89 			(wmi_d0_wow_enable_disable_cmd_fixed_param));
90 
91 	cmd->enable = false;
92 
93 	wmi_mtrace(WMI_D0_WOW_ENABLE_DISABLE_CMDID, NO_SESSION, 0);
94 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
95 				      WMI_D0_WOW_ENABLE_DISABLE_CMDID);
96 	if (QDF_IS_STATUS_ERROR(status))
97 		wmi_buf_free(buf);
98 
99 	return status;
100 }
101 
102 void wmi_d0wow_attach_tlv(struct wmi_unified *wmi_handle)
103 {
104 	struct wmi_ops *ops = wmi_handle->ops;
105 
106 	ops->send_d0wow_enable_cmd = send_d0wow_enable_cmd_tlv;
107 	ops->send_d0wow_disable_cmd = send_d0wow_disable_cmd_tlv;
108 }
109 #endif /* FEATURE_WLAN_D0WOW */
110 
111 /**
112  * send_add_wow_wakeup_event_cmd_tlv() -  Configures wow wakeup events.
113  * @wmi_handle: wmi handle
114  * @vdev_id: vdev id
115  * @bitmap: Event bitmap
116  * @enable: enable/disable
117  *
118  * Return: QDF status
119  */
120 static QDF_STATUS send_add_wow_wakeup_event_cmd_tlv(wmi_unified_t wmi_handle,
121 						    uint32_t vdev_id,
122 						    uint32_t *bitmap,
123 						    bool enable)
124 {
125 	WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *cmd;
126 	uint16_t len;
127 	wmi_buf_t buf;
128 	int ret;
129 
130 	len = sizeof(WMI_WOW_ADD_DEL_EVT_CMD_fixed_param);
131 	buf = wmi_buf_alloc(wmi_handle, len);
132 	if (!buf) {
133 		return QDF_STATUS_E_NOMEM;
134 	}
135 	cmd = (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *) wmi_buf_data(buf);
136 	WMITLV_SET_HDR(&cmd->tlv_header,
137 		       WMITLV_TAG_STRUC_WMI_WOW_ADD_DEL_EVT_CMD_fixed_param,
138 		       WMITLV_GET_STRUCT_TLVLEN
139 			       (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param));
140 	cmd->vdev_id = vdev_id;
141 	cmd->is_add = enable;
142 	qdf_mem_copy(&(cmd->event_bitmaps[0]), bitmap, sizeof(uint32_t) *
143 		     WMI_WOW_MAX_EVENT_BM_LEN);
144 
145 	wmi_debug("Wakeup pattern 0x%x%x%x%x %s in fw", cmd->event_bitmaps[0],
146 		 cmd->event_bitmaps[1], cmd->event_bitmaps[2],
147 		 cmd->event_bitmaps[3], enable ? "enabled" : "disabled");
148 
149 	wmi_mtrace(WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, cmd->vdev_id, 0);
150 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
151 				   WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
152 	if (ret) {
153 		wmi_err("Failed to config wow wakeup event");
154 		wmi_buf_free(buf);
155 		return QDF_STATUS_E_FAILURE;
156 	}
157 
158 	return QDF_STATUS_SUCCESS;
159 }
160 
161 /**
162  * send_wow_patterns_to_fw_cmd_tlv() - Sends WOW patterns to FW.
163  * @wmi_handle: wmi handle
164  * @vdev_id: vdev id
165  * @ptrn_id: pattern id
166  * @ptrn: pattern
167  * @ptrn_len: pattern length
168  * @ptrn_offset: pattern offset
169  * @mask: mask
170  * @mask_len: mask length
171  * @user: true for user configured pattern and false for default pattern
172  * @default_patterns: default patterns
173  *
174  * Return: QDF status
175  */
176 static QDF_STATUS send_wow_patterns_to_fw_cmd_tlv(wmi_unified_t wmi_handle,
177 				uint8_t vdev_id, uint8_t ptrn_id,
178 				const uint8_t *ptrn, uint8_t ptrn_len,
179 				uint8_t ptrn_offset, const uint8_t *mask,
180 				uint8_t mask_len, bool user,
181 				uint8_t default_patterns)
182 {
183 	WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
184 	WOW_BITMAP_PATTERN_T *bitmap_pattern;
185 	wmi_buf_t buf;
186 	uint8_t *buf_ptr;
187 	int32_t len;
188 	int ret;
189 
190 	len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
191 		WMI_TLV_HDR_SIZE +
192 		1 * sizeof(WOW_BITMAP_PATTERN_T) +
193 		WMI_TLV_HDR_SIZE +
194 		0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
195 		WMI_TLV_HDR_SIZE +
196 		0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
197 		WMI_TLV_HDR_SIZE +
198 		0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
199 		WMI_TLV_HDR_SIZE +
200 		0 * sizeof(uint32_t) + WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
201 
202 	buf = wmi_buf_alloc(wmi_handle, len);
203 	if (!buf) {
204 		return QDF_STATUS_E_NOMEM;
205 	}
206 
207 	cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
208 	buf_ptr = (uint8_t *) cmd;
209 
210 	WMITLV_SET_HDR(&cmd->tlv_header,
211 		       WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
212 		       WMITLV_GET_STRUCT_TLVLEN
213 			       (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
214 	cmd->vdev_id = vdev_id;
215 	cmd->pattern_id = ptrn_id;
216 
217 	cmd->pattern_type = WOW_BITMAP_PATTERN;
218 	buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
219 
220 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
221 		       sizeof(WOW_BITMAP_PATTERN_T));
222 	buf_ptr += WMI_TLV_HDR_SIZE;
223 	bitmap_pattern = (WOW_BITMAP_PATTERN_T *) buf_ptr;
224 
225 	WMITLV_SET_HDR(&bitmap_pattern->tlv_header,
226 		       WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T,
227 		       WMITLV_GET_STRUCT_TLVLEN(WOW_BITMAP_PATTERN_T));
228 
229 	qdf_mem_copy(&bitmap_pattern->patternbuf[0], ptrn, ptrn_len);
230 	qdf_mem_copy(&bitmap_pattern->bitmaskbuf[0], mask, mask_len);
231 
232 	bitmap_pattern->pattern_offset = ptrn_offset;
233 	bitmap_pattern->pattern_len = ptrn_len;
234 
235 	if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMAP_PATTERN_SIZE)
236 		bitmap_pattern->pattern_len = WOW_DEFAULT_BITMAP_PATTERN_SIZE;
237 
238 	if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMASK_SIZE)
239 		bitmap_pattern->pattern_len = WOW_DEFAULT_BITMASK_SIZE;
240 
241 	bitmap_pattern->bitmask_len = bitmap_pattern->pattern_len;
242 	bitmap_pattern->pattern_id = ptrn_id;
243 
244 	wmi_debug("vdev: %d, ptrn id: %d, ptrn len: %d, ptrn offset: %d user %d",
245 		 cmd->vdev_id, cmd->pattern_id, bitmap_pattern->pattern_len,
246 		 bitmap_pattern->pattern_offset, user);
247 	wmi_debug("Pattern: ");
248 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
249 			   &bitmap_pattern->patternbuf[0],
250 			   bitmap_pattern->pattern_len);
251 
252 	wmi_debug("Mask: ");
253 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
254 			   &bitmap_pattern->bitmaskbuf[0],
255 			   bitmap_pattern->pattern_len);
256 
257 	buf_ptr += sizeof(WOW_BITMAP_PATTERN_T);
258 
259 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
260 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
261 	buf_ptr += WMI_TLV_HDR_SIZE;
262 
263 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
264 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
265 	buf_ptr += WMI_TLV_HDR_SIZE;
266 
267 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
268 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
269 	buf_ptr += WMI_TLV_HDR_SIZE;
270 
271 	/* Fill TLV for pattern_info_timeout but no data. */
272 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
273 	buf_ptr += WMI_TLV_HDR_SIZE;
274 
275 	/* Fill TLV for ratelimit_interval with dummy data as this fix elem */
276 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 1 * sizeof(uint32_t));
277 	buf_ptr += WMI_TLV_HDR_SIZE;
278 	*(uint32_t *) buf_ptr = 0;
279 
280 	wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
281 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
282 				   WMI_WOW_ADD_WAKE_PATTERN_CMDID);
283 	if (ret) {
284 		wmi_err("Failed to send wow ptrn to fw");
285 		wmi_buf_free(buf);
286 		return QDF_STATUS_E_FAILURE;
287 	}
288 
289 	return QDF_STATUS_SUCCESS;
290 }
291 
292 /**
293  * fill_arp_offload_params_tlv() - Fill ARP offload data
294  * @wmi_handle: wmi handle
295  * @offload_req: offload request
296  * @buf_ptr: buffer pointer
297  *
298  * To fill ARP offload data to firmware
299  * when target goes to wow mode.
300  *
301  * Return: None
302  */
303 static void fill_arp_offload_params_tlv(wmi_unified_t wmi_handle,
304 		struct pmo_arp_offload_params *offload_req, uint8_t **buf_ptr)
305 {
306 
307 	int i;
308 	WMI_ARP_OFFLOAD_TUPLE *arp_tuple;
309 	bool enable_or_disable = offload_req->enable;
310 
311 	WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
312 		(WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE)));
313 	*buf_ptr += WMI_TLV_HDR_SIZE;
314 	for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {
315 		arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *)*buf_ptr;
316 		WMITLV_SET_HDR(&arp_tuple->tlv_header,
317 			WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE,
318 			WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE));
319 
320 		/* Fill data for ARP and NS in the first tuple for LA */
321 		if ((enable_or_disable & PMO_OFFLOAD_ENABLE) && (i == 0)) {
322 			/* Copy the target ip addr and flags */
323 			arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
324 			qdf_mem_copy(&arp_tuple->target_ipaddr,
325 					offload_req->host_ipv4_addr,
326 					WMI_IPV4_ADDR_LEN);
327 			wmi_debug("ARPOffload IP4 address: %pI4",
328 				 offload_req->host_ipv4_addr);
329 		}
330 		*buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE);
331 	}
332 }
333 
334 #ifdef WLAN_NS_OFFLOAD
335 /**
336  * fill_ns_offload_params_tlv() - Fill NS offload data
337  * @wmi_handle: wmi handle
338  * @ns_req: offload request
339  * @buf_ptr: buffer pointer
340  *
341  * To fill NS offload data to firmware
342  * when target goes to wow mode.
343  *
344  * Return: None
345  */
346 static void fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,
347 		struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
348 {
349 
350 	int i;
351 	WMI_NS_OFFLOAD_TUPLE *ns_tuple;
352 
353 	WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
354 		       (WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE)));
355 	*buf_ptr += WMI_TLV_HDR_SIZE;
356 	for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) {
357 		ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr;
358 		WMITLV_SET_HDR(&ns_tuple->tlv_header,
359 			WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
360 			(sizeof(WMI_NS_OFFLOAD_TUPLE) - WMI_TLV_HDR_SIZE));
361 
362 		/*
363 		 * Fill data only for NS offload in the first ARP tuple for LA
364 		 */
365 		if ((ns_req->enable & PMO_OFFLOAD_ENABLE)) {
366 			ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
367 			/* Copy the target/solicitation/remote ip addr */
368 			if (ns_req->target_ipv6_addr_valid[i])
369 				qdf_mem_copy(&ns_tuple->target_ipaddr[0],
370 					&ns_req->target_ipv6_addr[i],
371 					sizeof(WMI_IPV6_ADDR));
372 			qdf_mem_copy(&ns_tuple->solicitation_ipaddr,
373 				&ns_req->self_ipv6_addr[i],
374 				sizeof(WMI_IPV6_ADDR));
375 			if (ns_req->target_ipv6_addr_ac_type[i]) {
376 				ns_tuple->flags |=
377 					WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
378 			}
379 			wmi_debug("Index %d NS solicitedIp %pI6, targetIp %pI6",
380 				i, &ns_req->self_ipv6_addr[i],
381 				&ns_req->target_ipv6_addr[i]);
382 
383 			/* target MAC is optional, check if it is valid,
384 			 * if this is not valid, the target will use the known
385 			 * local MAC address rather than the tuple
386 			 */
387 			WMI_CHAR_ARRAY_TO_MAC_ADDR(
388 				ns_req->self_macaddr.bytes,
389 				&ns_tuple->target_mac);
390 			if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
391 				(ns_tuple->target_mac.mac_addr47to32 != 0)) {
392 				ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
393 			}
394 		}
395 		*buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
396 	}
397 }
398 
399 /**
400  * fill_nsoffload_ext_tlv() - Fill NS offload ext data
401  * @wmi_handle: wmi handle
402  * @ns_req: offload request
403  * @buf_ptr: buffer pointer
404  *
405  * To fill extended NS offload extended data to firmware
406  * when target goes to wow mode.
407  *
408  * Return: None
409  */
410 static void fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,
411 		struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
412 {
413 	int i;
414 	WMI_NS_OFFLOAD_TUPLE *ns_tuple;
415 	uint32_t count, num_ns_ext_tuples;
416 
417 	count = ns_req->num_ns_offload_count;
418 	num_ns_ext_tuples = ns_req->num_ns_offload_count -
419 		WMI_MAX_NS_OFFLOADS;
420 
421 	/* Populate extended NS offload tuples */
422 	WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
423 		(num_ns_ext_tuples * sizeof(WMI_NS_OFFLOAD_TUPLE)));
424 	*buf_ptr += WMI_TLV_HDR_SIZE;
425 	for (i = WMI_MAX_NS_OFFLOADS; i < count; i++) {
426 		ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr;
427 		WMITLV_SET_HDR(&ns_tuple->tlv_header,
428 			WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
429 			(sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE));
430 
431 		/*
432 		 * Fill data only for NS offload in the first ARP tuple for LA
433 		 */
434 		if ((ns_req->enable & PMO_OFFLOAD_ENABLE)) {
435 			ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
436 			/* Copy the target/solicitation/remote ip addr */
437 			if (ns_req->target_ipv6_addr_valid[i])
438 				qdf_mem_copy(&ns_tuple->target_ipaddr[0],
439 					&ns_req->target_ipv6_addr[i],
440 					sizeof(WMI_IPV6_ADDR));
441 			qdf_mem_copy(&ns_tuple->solicitation_ipaddr,
442 				&ns_req->self_ipv6_addr[i],
443 				sizeof(WMI_IPV6_ADDR));
444 			if (ns_req->target_ipv6_addr_ac_type[i]) {
445 				ns_tuple->flags |=
446 					WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
447 			}
448 			wmi_debug("Index %d NS solicitedIp %pI6, targetIp %pI6",
449 				i, &ns_req->self_ipv6_addr[i],
450 				&ns_req->target_ipv6_addr[i]);
451 
452 			/* target MAC is optional, check if it is valid,
453 			 * if this is not valid, the target will use the
454 			 * known local MAC address rather than the tuple
455 			 */
456 			 WMI_CHAR_ARRAY_TO_MAC_ADDR(
457 				ns_req->self_macaddr.bytes,
458 				&ns_tuple->target_mac);
459 			if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
460 				(ns_tuple->target_mac.mac_addr47to32 != 0)) {
461 				ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
462 			}
463 		}
464 		*buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
465 	}
466 }
467 #else
468 static void fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,
469 		struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
470 {
471 }
472 
473 static void fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,
474 		struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
475 {
476 }
477 #endif
478 
479 /**
480  * send_enable_arp_ns_offload_cmd_tlv() - enable ARP NS offload
481  * @wmi_handle: wmi handle
482  * @arp_offload_req: arp offload request
483  * @ns_offload_req: ns offload request
484  * @vdev_id: vdev ID
485  *
486  * To configure ARP NS off load data to firmware
487  * when target goes to wow mode.
488  *
489  * Return: QDF Status
490  */
491 static QDF_STATUS send_enable_arp_ns_offload_cmd_tlv(wmi_unified_t wmi_handle,
492 			   struct pmo_arp_offload_params *arp_offload_req,
493 			   struct pmo_ns_offload_params *ns_offload_req,
494 			   uint8_t vdev_id)
495 {
496 	int32_t res;
497 	WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd;
498 	uint8_t *buf_ptr;
499 	wmi_buf_t buf;
500 	int32_t len;
501 	uint32_t count = 0, num_ns_ext_tuples = 0;
502 
503 	count = ns_offload_req->num_ns_offload_count;
504 
505 	/*
506 	 * TLV place holder size for array of NS tuples
507 	 * TLV place holder size for array of ARP tuples
508 	 */
509 	len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) +
510 		WMI_TLV_HDR_SIZE +
511 		WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE) +
512 		WMI_TLV_HDR_SIZE +
513 		WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE);
514 
515 	/*
516 	 * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate
517 	 * extra length for extended NS offload tuples which follows ARP offload
518 	 * tuples. Host needs to fill this structure in following format:
519 	 * 2 NS ofload tuples
520 	 * 2 ARP offload tuples
521 	 * N numbers of extended NS offload tuples if HDD has given more than
522 	 * 2 NS offload addresses
523 	 */
524 	if (count > WMI_MAX_NS_OFFLOADS) {
525 		num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS;
526 		len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples
527 			   * sizeof(WMI_NS_OFFLOAD_TUPLE);
528 	}
529 
530 	buf = wmi_buf_alloc(wmi_handle, len);
531 	if (!buf) {
532 		return QDF_STATUS_E_NOMEM;
533 	}
534 
535 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
536 	cmd = (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *) buf_ptr;
537 	WMITLV_SET_HDR(&cmd->tlv_header,
538 		       WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param,
539 		       WMITLV_GET_STRUCT_TLVLEN
540 			       (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param));
541 	cmd->flags = 0;
542 	cmd->vdev_id = vdev_id;
543 	cmd->num_ns_ext_tuples = num_ns_ext_tuples;
544 
545 	wmi_debug("ARP NS Offload vdev_id: %d", cmd->vdev_id);
546 
547 	buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param);
548 	fill_ns_offload_params_tlv(wmi_handle, ns_offload_req, &buf_ptr);
549 	fill_arp_offload_params_tlv(wmi_handle, arp_offload_req, &buf_ptr);
550 	if (num_ns_ext_tuples)
551 		fill_nsoffload_ext_tlv(wmi_handle, ns_offload_req, &buf_ptr);
552 
553 	wmi_mtrace(WMI_SET_ARP_NS_OFFLOAD_CMDID, cmd->vdev_id, 0);
554 	res = wmi_unified_cmd_send(wmi_handle, buf, len,
555 				     WMI_SET_ARP_NS_OFFLOAD_CMDID);
556 	if (res) {
557 		wmi_err("Failed to enable ARP NDP/NSffload");
558 		wmi_buf_free(buf);
559 		return QDF_STATUS_E_FAILURE;
560 	}
561 
562 	return QDF_STATUS_SUCCESS;
563 }
564 
565 /**
566  * send_add_clear_mcbc_filter_cmd_tlv() - set mcast filter command to fw
567  * @wmi_handle: wmi handle
568  * @vdev_id: vdev id
569  * @multicast_addr: mcast address
570  * @clearList: clear list flag
571  *
572  * Return: QDF_STATUS_SUCCESS for success or error code
573  */
574 static QDF_STATUS send_add_clear_mcbc_filter_cmd_tlv(wmi_unified_t wmi_handle,
575 				     uint8_t vdev_id,
576 				     struct qdf_mac_addr multicast_addr,
577 				     bool clearList)
578 {
579 	WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
580 	wmi_buf_t buf;
581 	int err;
582 
583 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
584 	if (!buf) {
585 		return QDF_STATUS_E_NOMEM;
586 	}
587 
588 	cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
589 	qdf_mem_zero(cmd, sizeof(*cmd));
590 
591 	WMITLV_SET_HDR(&cmd->tlv_header,
592 	       WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param,
593 	       WMITLV_GET_STRUCT_TLVLEN
594 	       (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param));
595 	cmd->action =
596 		(clearList ? WMI_MCAST_FILTER_DELETE : WMI_MCAST_FILTER_SET);
597 	cmd->vdev_id = vdev_id;
598 	WMI_CHAR_ARRAY_TO_MAC_ADDR(multicast_addr.bytes, &cmd->mcastbdcastaddr);
599 
600 	wmi_debug("Action:%d; vdev_id:%d; clearList:%d; MCBC MAC Addr: "QDF_MAC_ADDR_FMT,
601 		 cmd->action, vdev_id, clearList,
602 		 QDF_MAC_ADDR_REF(multicast_addr.bytes));
603 
604 	wmi_mtrace(WMI_SET_MCASTBCAST_FILTER_CMDID, cmd->vdev_id, 0);
605 	err = wmi_unified_cmd_send(wmi_handle, buf,
606 				   sizeof(*cmd),
607 				   WMI_SET_MCASTBCAST_FILTER_CMDID);
608 	if (err) {
609 		wmi_err("Failed to send set_param cmd");
610 		wmi_buf_free(buf);
611 		return QDF_STATUS_E_FAILURE;
612 	}
613 
614 	return QDF_STATUS_SUCCESS;
615 }
616 
617 /**
618  * send_multiple_add_clear_mcbc_filter_cmd_tlv() - send multiple  mcast filter
619  *						   command to fw
620  * @wmi_handle: wmi handle
621  * @vdev_id: vdev id
622  * @filter_param: mcast filter params
623  *
624  * Return: QDF_STATUS_SUCCESS for success or error code
625  */
626 static QDF_STATUS send_multiple_add_clear_mcbc_filter_cmd_tlv(
627 				wmi_unified_t wmi_handle,
628 				uint8_t vdev_id,
629 				struct pmo_mcast_filter_params *filter_param)
630 
631 {
632 	WMI_SET_MULTIPLE_MCAST_FILTER_CMD_fixed_param *cmd;
633 	uint8_t *buf_ptr;
634 	wmi_buf_t buf;
635 	int err;
636 	int i;
637 	uint8_t *mac_addr_src_ptr = NULL;
638 	wmi_mac_addr *mac_addr_dst_ptr;
639 	uint32_t len = sizeof(*cmd) + WMI_TLV_HDR_SIZE +
640 		       sizeof(wmi_mac_addr) * filter_param->multicast_addr_cnt;
641 
642 	buf = wmi_buf_alloc(wmi_handle, len);
643 	if (!buf) {
644 		return QDF_STATUS_E_NOMEM;
645 	}
646 
647 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
648 	cmd = (WMI_SET_MULTIPLE_MCAST_FILTER_CMD_fixed_param *)
649 		wmi_buf_data(buf);
650 	qdf_mem_zero(cmd, sizeof(*cmd));
651 
652 	WMITLV_SET_HDR(&cmd->tlv_header,
653 	       WMITLV_TAG_STRUC_wmi_set_multiple_mcast_filter_cmd_fixed_param,
654 	       WMITLV_GET_STRUCT_TLVLEN
655 	       (WMI_SET_MULTIPLE_MCAST_FILTER_CMD_fixed_param));
656 	cmd->operation =
657 		((filter_param->action == 0) ? WMI_MULTIPLE_MCAST_FILTER_DELETE
658 					: WMI_MULTIPLE_MCAST_FILTER_ADD);
659 	cmd->vdev_id = vdev_id;
660 	cmd->num_mcastaddrs = filter_param->multicast_addr_cnt;
661 
662 	buf_ptr += sizeof(*cmd);
663 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
664 		       sizeof(wmi_mac_addr) *
665 			       filter_param->multicast_addr_cnt);
666 
667 	if (filter_param->multicast_addr_cnt == 0)
668 		goto send_cmd;
669 
670 	mac_addr_src_ptr = (uint8_t *)&filter_param->multicast_addr;
671 	mac_addr_dst_ptr = (wmi_mac_addr *)
672 			(buf_ptr + WMI_TLV_HDR_SIZE);
673 
674 	wmi_debug("multicast addr cnt: %u", filter_param->multicast_addr_cnt);
675 	for (i = 0; i < filter_param->multicast_addr_cnt; i++) {
676 		WMI_CHAR_ARRAY_TO_MAC_ADDR(mac_addr_src_ptr, mac_addr_dst_ptr);
677 		wmi_nofl_debug("mac addr[%d]: " QDF_MAC_ADDR_FMT, i,
678 			       QDF_MAC_ADDR_REF(
679 					filter_param->multicast_addr[i].bytes));
680 		mac_addr_src_ptr += ATH_MAC_LEN;
681 		mac_addr_dst_ptr++;
682 	}
683 
684 send_cmd:
685 	wmi_mtrace(WMI_SET_MULTIPLE_MCAST_FILTER_CMDID, cmd->vdev_id, 0);
686 	err = wmi_unified_cmd_send(wmi_handle, buf,
687 				   len,
688 				   WMI_SET_MULTIPLE_MCAST_FILTER_CMDID);
689 	if (err) {
690 		wmi_err("Failed to send set_param cmd");
691 		wmi_buf_free(buf);
692 		return QDF_STATUS_E_FAILURE;
693 	}
694 
695 	return QDF_STATUS_SUCCESS;
696 }
697 
698 static QDF_STATUS send_conf_hw_filter_cmd_tlv(wmi_unified_t wmi,
699 					      struct pmo_hw_filter_params *req)
700 {
701 	QDF_STATUS status;
702 	wmi_hw_data_filter_cmd_fixed_param *cmd;
703 	wmi_buf_t wmi_buf;
704 
705 	if (!req) {
706 		wmi_err("req is null");
707 		return QDF_STATUS_E_INVAL;
708 	}
709 
710 	wmi_buf = wmi_buf_alloc(wmi, sizeof(*cmd));
711 	if (!wmi_buf) {
712 		return QDF_STATUS_E_NOMEM;
713 	}
714 
715 	cmd = (wmi_hw_data_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
716 	WMITLV_SET_HDR(&cmd->tlv_header,
717 		  WMITLV_TAG_STRUC_wmi_hw_data_filter_cmd_fixed_param,
718 		  WMITLV_GET_STRUCT_TLVLEN(wmi_hw_data_filter_cmd_fixed_param));
719 	cmd->vdev_id = req->vdev_id;
720 	cmd->enable = req->enable;
721 	/* Set all modes in case of disable */
722 	if (!cmd->enable)
723 		cmd->hw_filter_bitmap = ((uint32_t)~0U);
724 	else
725 		cmd->hw_filter_bitmap = req->mode_bitmap;
726 
727 	wmi_debug("Send %s hw filter mode: 0x%X for vdev id %d",
728 		 req->enable ? "enable" : "disable", req->mode_bitmap,
729 		 req->vdev_id);
730 
731 	wmi_mtrace(WMI_HW_DATA_FILTER_CMDID, cmd->vdev_id, 0);
732 	status = wmi_unified_cmd_send(wmi, wmi_buf, sizeof(*cmd),
733 				      WMI_HW_DATA_FILTER_CMDID);
734 	if (QDF_IS_STATUS_ERROR(status)) {
735 		wmi_err("Failed to configure hw filter");
736 		wmi_buf_free(wmi_buf);
737 	}
738 
739 	return status;
740 }
741 
742 static void
743 fill_fils_tlv_params(WMI_GTK_OFFLOAD_CMD_fixed_param *cmd,
744 			  uint8_t vdev_id,
745 			  struct pmo_gtk_req *params)
746 {
747 	uint8_t *buf_ptr;
748 	wmi_gtk_offload_fils_tlv_param *ext_param;
749 
750 	buf_ptr = (uint8_t *) cmd + sizeof(*cmd);
751 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
752 		       sizeof(*ext_param));
753 	buf_ptr += WMI_TLV_HDR_SIZE;
754 
755 	ext_param = (wmi_gtk_offload_fils_tlv_param *)buf_ptr;
756 	WMITLV_SET_HDR(&ext_param->tlv_header,
757 		       WMITLV_TAG_STRUC_wmi_gtk_offload_extended_tlv_param,
758 		       WMITLV_GET_STRUCT_TLVLEN(
759 				wmi_gtk_offload_fils_tlv_param));
760 	ext_param->vdev_id = vdev_id;
761 	ext_param->flags = cmd->flags;
762 	ext_param->kek_len = params->kek_len;
763 	qdf_mem_copy(ext_param->KEK, params->kek, params->kek_len);
764 	qdf_mem_copy(ext_param->KCK, params->kck,
765 		     WMI_GTK_OFFLOAD_KCK_BYTES);
766 	qdf_mem_copy(ext_param->replay_counter, &params->replay_counter,
767 		     GTK_REPLAY_COUNTER_BYTES);
768 }
769 
770 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
771 /**
772  * send_igmp_offload_cmd_tlv() - send IGMP offload command to fw
773  * @wmi_handle: wmi handle
774  * @pmo_igmp_req: IGMP offload parameters
775  *
776  * Return: QDF status
777  */
778 static
779 QDF_STATUS send_igmp_offload_cmd_tlv(wmi_unified_t wmi_handle,
780 				     struct pmo_igmp_offload_req *pmo_igmp_req)
781 {
782 	wmi_buf_t buf;
783 	uint8_t *buf_ptr;
784 	int len;
785 	int i = 0;
786 	WMI_IPV4_ADDR *ipv4_list;
787 	wmi_igmp_offload_fixed_param *cmd;
788 	QDF_STATUS status = QDF_STATUS_SUCCESS;
789 
790 	len = sizeof(wmi_igmp_offload_fixed_param) + WMI_TLV_HDR_SIZE +
791 	     (pmo_igmp_req->num_grp_ip_address) * sizeof(WMI_IPV4_ADDR);
792 	/* alloc wmi buffer */
793 	buf = wmi_buf_alloc(wmi_handle, len);
794 	if (!buf) {
795 		status = QDF_STATUS_E_NOMEM;
796 		goto out;
797 	}
798 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
799 	cmd = (wmi_igmp_offload_fixed_param *)wmi_buf_data(buf);
800 
801 	WMITLV_SET_HDR(&cmd->tlv_header,
802 		       WMITLV_TAG_STRUC_wmi_igmp_offload_fixed_param,
803 		       WMITLV_GET_STRUCT_TLVLEN(wmi_igmp_offload_fixed_param));
804 
805 	cmd->vdev_id = pmo_igmp_req->vdev_id;
806 	cmd->enable = pmo_igmp_req->enable;
807 	cmd->version_support_bitmask =
808 				pmo_igmp_req->version_support;
809 
810 	buf_ptr += sizeof(*cmd);
811 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
812 		       sizeof(WMI_IPV4_ADDR) *
813 		       pmo_igmp_req->num_grp_ip_address);
814 
815 	ipv4_list = (WMI_IPV4_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE);
816 
817 	while (i < pmo_igmp_req->num_grp_ip_address) {
818 		qdf_mem_copy((void *)((*(ipv4_list + i)).address),
819 			     (void *)&(pmo_igmp_req->grp_ip_address[i]),
820 			     WMI_IPV4_ADDR_LEN);
821 		wmi_debug("piv4[%d]:%x", i, *(uint32_t *)(ipv4_list + i));
822 		i++;
823 	}
824 
825 	wmi_debug("VDEVID:%d, FLAG:x%x version support:%d",
826 		  cmd->vdev_id, cmd->enable,
827 		  cmd->version_support_bitmask);
828 
829 	/* send the wmi command */
830 	wmi_mtrace(WMI_VDEV_IGMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
831 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
832 				 WMI_VDEV_IGMP_OFFLOAD_CMDID)) {
833 		wmi_err("Failed to send WMI_VDEV_IGMP_OFFLOAD_CMDID");
834 		wmi_buf_free(buf);
835 		status = QDF_STATUS_E_FAILURE;
836 	}
837 out:
838 	return status;
839 }
840 #endif
841 
842 /**
843  * send_gtk_offload_cmd_tlv() - send GTK offload command to fw
844  * @wmi_handle: wmi handle
845  * @vdev_id: vdev id
846  * @params: GTK offload parameters
847  * @enable_offload: true to enable the offload
848  * @gtk_offload_opcode: GTK offload opcode
849  *
850  * Return: QDF status
851  */
852 static
853 QDF_STATUS send_gtk_offload_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_id,
854 				    struct pmo_gtk_req *params,
855 				    bool enable_offload,
856 				    uint32_t gtk_offload_opcode)
857 {
858 	int len;
859 	uint8_t *buf_ptr;
860 	wmi_buf_t buf;
861 	WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
862 	QDF_STATUS status = QDF_STATUS_SUCCESS;
863 
864 	len = sizeof(*cmd);
865 
866 	len += WMI_TLV_HDR_SIZE;
867 	if (params->is_fils_connection)
868 		len += sizeof(wmi_gtk_offload_fils_tlv_param);
869 
870 	if (params->kck_len > 16)
871 		len += WMI_TLV_HDR_SIZE +
872 		       roundup(params->kek_len, sizeof(uint32_t)) +
873 		       WMI_TLV_HDR_SIZE +
874 		       roundup(params->kck_len, sizeof(uint32_t));
875 
876 	/* alloc wmi buffer */
877 	buf = wmi_buf_alloc(wmi_handle, len);
878 	if (!buf) {
879 		status = QDF_STATUS_E_NOMEM;
880 		goto out;
881 	}
882 
883 	cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
884 	WMITLV_SET_HDR(&cmd->tlv_header,
885 		       WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
886 		       WMITLV_GET_STRUCT_TLVLEN
887 			       (WMI_GTK_OFFLOAD_CMD_fixed_param));
888 
889 	buf_ptr = wmi_buf_data(buf);
890 	cmd->vdev_id = vdev_id;
891 
892 	/* Request target to enable GTK offload */
893 	if (enable_offload == PMO_GTK_OFFLOAD_ENABLE) {
894 		cmd->flags = gtk_offload_opcode;
895 
896 		/* Copy the keys and replay counter */
897 		qdf_mem_copy(cmd->KCK, params->kck, sizeof(cmd->KCK));
898 		qdf_mem_copy(cmd->KEK, params->kek, sizeof(cmd->KEK));
899 		qdf_mem_copy(cmd->replay_counter, &params->replay_counter,
900 			     GTK_REPLAY_COUNTER_BYTES);
901 	} else {
902 		cmd->flags = gtk_offload_opcode;
903 	}
904 
905 	buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
906 
907 	if (params->is_fils_connection) {
908 		fill_fils_tlv_params(cmd, vdev_id, params);
909 		buf_ptr += sizeof(wmi_gtk_offload_fils_tlv_param);
910 	} else {
911 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
912 		buf_ptr += WMI_TLV_HDR_SIZE;
913 	}
914 
915 	if (params->kck_len > 16) {
916 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
917 			       roundup(params->kek_len, sizeof(uint32_t)));
918 		buf_ptr += WMI_TLV_HDR_SIZE;
919 
920 		qdf_mem_copy(buf_ptr, params->kek, params->kek_len);
921 		buf_ptr += roundup(params->kek_len, sizeof(uint32_t));
922 
923 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
924 			       roundup(params->kck_len, sizeof(uint32_t)));
925 		buf_ptr += WMI_TLV_HDR_SIZE;
926 
927 		qdf_mem_copy(buf_ptr, params->kck, params->kck_len);
928 		buf_ptr += roundup(params->kck_len, sizeof(uint32_t));
929 	}
930 
931 	wmi_debug("VDEVID: %d, GTK_FLAGS: x%x kek len %d",
932 		 vdev_id, cmd->flags, params->kek_len);
933 	/* send the wmi command */
934 	wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0);
935 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
936 				 WMI_GTK_OFFLOAD_CMDID)) {
937 		wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID");
938 		wmi_buf_free(buf);
939 		status = QDF_STATUS_E_FAILURE;
940 	}
941 
942 out:
943 	return status;
944 }
945 
946 /**
947  * send_process_gtk_offload_getinfo_cmd_tlv() - send GTK offload cmd to fw
948  * @wmi_handle: wmi handle
949  * @vdev_id: vdev id
950  * @offload_req_opcode: GTK offload request opcode
951  *
952  * Return: QDF status
953  */
954 static QDF_STATUS send_process_gtk_offload_getinfo_cmd_tlv(
955 			wmi_unified_t wmi_handle,
956 			uint8_t vdev_id,
957 			uint64_t offload_req_opcode)
958 {
959 	int len;
960 	wmi_buf_t buf;
961 	WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
962 	QDF_STATUS status = QDF_STATUS_SUCCESS;
963 
964 	len = sizeof(*cmd);
965 
966 	/* alloc wmi buffer */
967 	buf = wmi_buf_alloc(wmi_handle, len);
968 	if (!buf) {
969 		status = QDF_STATUS_E_NOMEM;
970 		goto out;
971 	}
972 
973 	cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
974 	WMITLV_SET_HDR(&cmd->tlv_header,
975 		       WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
976 		       WMITLV_GET_STRUCT_TLVLEN
977 			       (WMI_GTK_OFFLOAD_CMD_fixed_param));
978 
979 	/* Request for GTK offload status */
980 	cmd->flags = offload_req_opcode;
981 	cmd->vdev_id = vdev_id;
982 
983 	/* send the wmi command */
984 	wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0);
985 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
986 				 WMI_GTK_OFFLOAD_CMDID)) {
987 		wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID for req info");
988 		wmi_buf_free(buf);
989 		status = QDF_STATUS_E_FAILURE;
990 	}
991 
992 out:
993 	return status;
994 }
995 
996 /**
997  * send_enable_enhance_multicast_offload_tlv() - send enhance multicast offload
998  * @wmi_handle: wmi handle
999  * @vdev_id: vdev id
1000  * @action: true for enable else false
1001  *
1002  * To enable enhance multicast offload to firmware
1003  * when target goes to wow mode.
1004  *
1005  * Return: QDF Status
1006  */
1007 
1008 static
1009 QDF_STATUS send_enable_enhance_multicast_offload_tlv(
1010 		wmi_unified_t wmi_handle,
1011 		uint8_t vdev_id, bool action)
1012 {
1013 	QDF_STATUS status;
1014 	wmi_buf_t buf;
1015 	wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
1016 
1017 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
1018 	if (!buf) {
1019 		return QDF_STATUS_E_NOMEM;
1020 	}
1021 
1022 	cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
1023 							wmi_buf_data(buf);
1024 
1025 	WMITLV_SET_HDR(&cmd->tlv_header,
1026 		WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
1027 		WMITLV_GET_STRUCT_TLVLEN(
1028 			wmi_config_enhanced_mcast_filter_cmd_fixed_param));
1029 
1030 	cmd->vdev_id = vdev_id;
1031 	cmd->enable = ((action == 0) ? ENHANCED_MCAST_FILTER_DISABLED :
1032 			ENHANCED_MCAST_FILTER_ENABLED);
1033 	wmi_debug("config enhance multicast offload action %d for vdev %d",
1034 		 action, vdev_id);
1035 	wmi_mtrace(WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID, cmd->vdev_id, 0);
1036 	status = wmi_unified_cmd_send(wmi_handle, buf,
1037 			sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
1038 	if (status != QDF_STATUS_SUCCESS) {
1039 		wmi_buf_free(buf);
1040 		wmi_err("Failed to send ENHANCED_MCAST_FILTER_CMDID");
1041 	}
1042 
1043 	return status;
1044 }
1045 
1046 /**
1047  * extract_gtk_rsp_event_tlv() - extract gtk rsp params from event
1048  * @wmi_handle: wmi handle
1049  * @evt_buf: pointer to event buffer
1050  * @gtk_rsp_param: Pointer to extraction buffer
1051  * @len: length of the @evt_buf event buffer
1052  *
1053  * Return: QDF_STATUS_SUCCESS for success or error code
1054  */
1055 static QDF_STATUS extract_gtk_rsp_event_tlv(wmi_unified_t wmi_handle,
1056 	void *evt_buf, struct pmo_gtk_rsp_params *gtk_rsp_param, uint32_t len)
1057 {
1058 	WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *fixed_param;
1059 	WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
1060 
1061 	param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *)evt_buf;
1062 	if (!param_buf) {
1063 		wmi_err("gtk param_buf is NULL");
1064 		return QDF_STATUS_E_INVAL;
1065 	}
1066 
1067 	if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
1068 		wmi_err("Invalid length for GTK status");
1069 		return QDF_STATUS_E_INVAL;
1070 	}
1071 
1072 	fixed_param = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *)
1073 		param_buf->fixed_param;
1074 
1075 	if (fixed_param->vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) {
1076 		wmi_err_rl("Invalid vdev_id %u", fixed_param->vdev_id);
1077 		return QDF_STATUS_E_INVAL;
1078 	}
1079 
1080 	gtk_rsp_param->vdev_id = fixed_param->vdev_id;
1081 	gtk_rsp_param->status_flag = QDF_STATUS_SUCCESS;
1082 	gtk_rsp_param->refresh_cnt = fixed_param->refresh_cnt;
1083 	qdf_mem_copy(&gtk_rsp_param->replay_counter,
1084 		&fixed_param->replay_counter,
1085 		GTK_REPLAY_COUNTER_BYTES);
1086 
1087 	return QDF_STATUS_SUCCESS;
1088 
1089 }
1090 
1091 #ifdef FEATURE_WLAN_RA_FILTERING
1092 /**
1093  * send_wow_sta_ra_filter_cmd_tlv() - set RA filter pattern in fw
1094  * @wmi_handle: wmi handle
1095  * @vdev_id: vdev id
1096  * @default_pattern: default pattern
1097  * @rate_limit_interval: ra packets interval
1098  *
1099  * Return: QDF status
1100  */
1101 static QDF_STATUS send_wow_sta_ra_filter_cmd_tlv(wmi_unified_t wmi_handle,
1102 						 uint8_t vdev_id,
1103 						 uint8_t default_pattern,
1104 						 uint16_t rate_limit_interval)
1105 {
1106 
1107 	WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
1108 	wmi_buf_t buf;
1109 	uint8_t *buf_ptr;
1110 	int32_t len;
1111 	int ret;
1112 
1113 	len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
1114 	      WMI_TLV_HDR_SIZE +
1115 	      0 * sizeof(WOW_BITMAP_PATTERN_T) +
1116 	      WMI_TLV_HDR_SIZE +
1117 	      0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
1118 	      WMI_TLV_HDR_SIZE +
1119 	      0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
1120 	      WMI_TLV_HDR_SIZE +
1121 	      0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
1122 	      WMI_TLV_HDR_SIZE +
1123 	      0 * sizeof(uint32_t) + WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
1124 
1125 	buf = wmi_buf_alloc(wmi_handle, len);
1126 	if (!buf) {
1127 		return QDF_STATUS_E_NOMEM;
1128 	}
1129 
1130 	cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1131 	buf_ptr = (uint8_t *) cmd;
1132 
1133 	WMITLV_SET_HDR(&cmd->tlv_header,
1134 		       WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
1135 		       WMITLV_GET_STRUCT_TLVLEN
1136 			       (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
1137 	cmd->vdev_id = vdev_id;
1138 	cmd->pattern_id = default_pattern,
1139 	cmd->pattern_type = WOW_IPV6_RA_PATTERN;
1140 	buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
1141 
1142 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
1143 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1144 	buf_ptr += WMI_TLV_HDR_SIZE;
1145 
1146 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
1147 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1148 	buf_ptr += WMI_TLV_HDR_SIZE;
1149 
1150 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
1151 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1152 	buf_ptr += WMI_TLV_HDR_SIZE;
1153 
1154 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
1155 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1156 	buf_ptr += WMI_TLV_HDR_SIZE;
1157 
1158 	/* Fill TLV for pattern_info_timeout but no data. */
1159 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
1160 	buf_ptr += WMI_TLV_HDR_SIZE;
1161 
1162 	/* Fill TLV for ra_ratelimit_interval. */
1163 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
1164 	buf_ptr += WMI_TLV_HDR_SIZE;
1165 
1166 	*((uint32_t *) buf_ptr) = rate_limit_interval;
1167 
1168 	wmi_debug("send RA rate limit [%d] to fw vdev = %d",
1169 		 rate_limit_interval, vdev_id);
1170 
1171 	wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
1172 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1173 				   WMI_WOW_ADD_WAKE_PATTERN_CMDID);
1174 	if (ret) {
1175 		wmi_err("Failed to send RA rate limit to fw");
1176 		wmi_buf_free(buf);
1177 		return QDF_STATUS_E_FAILURE;
1178 	}
1179 
1180 	return QDF_STATUS_SUCCESS;
1181 }
1182 
1183 void wmi_ra_filtering_attach_tlv(struct wmi_unified *wmi_handle)
1184 {
1185 	struct wmi_ops *ops = wmi_handle->ops;
1186 
1187 	ops->send_wow_sta_ra_filter_cmd = send_wow_sta_ra_filter_cmd_tlv;
1188 }
1189 #endif /* FEATURE_WLAN_RA_FILTERING */
1190 
1191 /**
1192  * send_action_frame_patterns_cmd_tlv() - send wmi cmd of action filter params
1193  * @wmi_handle: wmi handler
1194  * @action_params: pointer to action_params
1195  *
1196  * Return: 0 for success, otherwise appropriate error code
1197  */
1198 static QDF_STATUS send_action_frame_patterns_cmd_tlv(wmi_unified_t wmi_handle,
1199 		struct pmo_action_wakeup_set_params *action_params)
1200 {
1201 	WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *cmd;
1202 	wmi_buf_t buf;
1203 	int i;
1204 	int32_t err;
1205 	uint32_t len = 0, *cmd_args;
1206 	uint8_t *buf_ptr;
1207 
1208 	len = (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t))
1209 				+ WMI_TLV_HDR_SIZE + sizeof(*cmd);
1210 	buf = wmi_buf_alloc(wmi_handle, len);
1211 	if (!buf) {
1212 		return QDF_STATUS_E_NOMEM;
1213 	}
1214 	cmd = (WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *) wmi_buf_data(buf);
1215 	buf_ptr = (uint8_t *)cmd;
1216 	WMITLV_SET_HDR(&cmd->tlv_header,
1217 		WMITLV_TAG_STRUC_wmi_wow_set_action_wake_up_cmd_fixed_param,
1218 		WMITLV_GET_STRUCT_TLVLEN(
1219 				WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param));
1220 
1221 	cmd->vdev_id = action_params->vdev_id;
1222 	cmd->operation = action_params->operation;
1223 
1224 	for (i = 0; i < MAX_SUPPORTED_ACTION_CATEGORY_ELE_LIST; i++)
1225 		cmd->action_category_map[i] =
1226 				action_params->action_category_map[i];
1227 
1228 	buf_ptr += sizeof(WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param);
1229 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1230 		       (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t)));
1231 	buf_ptr += WMI_TLV_HDR_SIZE;
1232 	cmd_args = (uint32_t *) buf_ptr;
1233 	for (i = 0; i < PMO_SUPPORTED_ACTION_CATE; i++)
1234 		cmd_args[i] = action_params->action_per_category[i];
1235 
1236 	wmi_mtrace(WMI_WOW_SET_ACTION_WAKE_UP_CMDID, cmd->vdev_id, 0);
1237 	err = wmi_unified_cmd_send(wmi_handle, buf,
1238 				   len, WMI_WOW_SET_ACTION_WAKE_UP_CMDID);
1239 	if (err) {
1240 		wmi_err("Failed to send ap_ps_egap cmd");
1241 		wmi_buf_free(buf);
1242 		return QDF_STATUS_E_FAILURE;
1243 	}
1244 
1245 	return QDF_STATUS_SUCCESS;
1246 }
1247 
1248 #ifdef FEATURE_WLAN_LPHB
1249 /**
1250  * send_lphb_config_hbenable_cmd_tlv() - enable command of LPHB configuration
1251  * @wmi_handle: wmi handle
1252  * @params: LPHB configuration info
1253  *
1254  * Return: QDF status
1255  */
1256 static QDF_STATUS send_lphb_config_hbenable_cmd_tlv(wmi_unified_t wmi_handle,
1257 				wmi_hb_set_enable_cmd_fixed_param *params)
1258 {
1259 	QDF_STATUS status;
1260 	wmi_buf_t buf = NULL;
1261 	uint8_t *buf_ptr;
1262 	wmi_hb_set_enable_cmd_fixed_param *hb_enable_fp;
1263 	int len = sizeof(wmi_hb_set_enable_cmd_fixed_param);
1264 
1265 	buf = wmi_buf_alloc(wmi_handle, len);
1266 	if (!buf) {
1267 		return QDF_STATUS_E_NOMEM;
1268 	}
1269 
1270 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1271 	hb_enable_fp = (wmi_hb_set_enable_cmd_fixed_param *) buf_ptr;
1272 	WMITLV_SET_HDR(&hb_enable_fp->tlv_header,
1273 		       WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param,
1274 		       WMITLV_GET_STRUCT_TLVLEN
1275 			       (wmi_hb_set_enable_cmd_fixed_param));
1276 
1277 	/* fill in values */
1278 	hb_enable_fp->vdev_id = params->session;
1279 	hb_enable_fp->enable = params->enable;
1280 	hb_enable_fp->item = params->item;
1281 	hb_enable_fp->session = params->session;
1282 
1283 	wmi_mtrace(WMI_HB_SET_ENABLE_CMDID, NO_SESSION, 0);
1284 	status = wmi_unified_cmd_send(wmi_handle, buf,
1285 				      len, WMI_HB_SET_ENABLE_CMDID);
1286 	if (QDF_IS_STATUS_ERROR(status)) {
1287 		wmi_err("cmd_send WMI_HB_SET_ENABLE returned Error %d",
1288 			 status);
1289 		wmi_buf_free(buf);
1290 	}
1291 
1292 	return status;
1293 }
1294 
1295 /**
1296  * send_lphb_config_tcp_params_cmd_tlv() - set tcp params of LPHB configuration
1297  * @wmi_handle: wmi handle
1298  * @lphb_conf_req: lphb config request
1299  *
1300  * Return: QDF status
1301  */
1302 static QDF_STATUS send_lphb_config_tcp_params_cmd_tlv(wmi_unified_t wmi_handle,
1303 	    wmi_hb_set_tcp_params_cmd_fixed_param *lphb_conf_req)
1304 {
1305 	QDF_STATUS status;
1306 	wmi_buf_t buf = NULL;
1307 	uint8_t *buf_ptr;
1308 	wmi_hb_set_tcp_params_cmd_fixed_param *hb_tcp_params_fp;
1309 	int len = sizeof(wmi_hb_set_tcp_params_cmd_fixed_param);
1310 
1311 	buf = wmi_buf_alloc(wmi_handle, len);
1312 	if (!buf) {
1313 		return QDF_STATUS_E_NOMEM;
1314 	}
1315 
1316 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1317 	hb_tcp_params_fp = (wmi_hb_set_tcp_params_cmd_fixed_param *) buf_ptr;
1318 	WMITLV_SET_HDR(&hb_tcp_params_fp->tlv_header,
1319 		       WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param,
1320 		       WMITLV_GET_STRUCT_TLVLEN
1321 			       (wmi_hb_set_tcp_params_cmd_fixed_param));
1322 
1323 	/* fill in values */
1324 	hb_tcp_params_fp->vdev_id = lphb_conf_req->vdev_id;
1325 	hb_tcp_params_fp->srv_ip = lphb_conf_req->srv_ip;
1326 	hb_tcp_params_fp->dev_ip = lphb_conf_req->dev_ip;
1327 	hb_tcp_params_fp->seq = lphb_conf_req->seq;
1328 	hb_tcp_params_fp->src_port = lphb_conf_req->src_port;
1329 	hb_tcp_params_fp->dst_port = lphb_conf_req->dst_port;
1330 	hb_tcp_params_fp->interval = lphb_conf_req->interval;
1331 	hb_tcp_params_fp->timeout = lphb_conf_req->timeout;
1332 	hb_tcp_params_fp->session = lphb_conf_req->session;
1333 	qdf_mem_copy(&hb_tcp_params_fp->gateway_mac,
1334 		     &lphb_conf_req->gateway_mac,
1335 		     sizeof(hb_tcp_params_fp->gateway_mac));
1336 
1337 	wmi_mtrace(WMI_HB_SET_TCP_PARAMS_CMDID, NO_SESSION, 0);
1338 	status = wmi_unified_cmd_send(wmi_handle, buf,
1339 				      len, WMI_HB_SET_TCP_PARAMS_CMDID);
1340 	if (QDF_IS_STATUS_ERROR(status)) {
1341 		wmi_err("cmd_send WMI_HB_SET_TCP_PARAMS returned Error %d",
1342 			 status);
1343 		wmi_buf_free(buf);
1344 	}
1345 
1346 	return status;
1347 }
1348 
1349 /**
1350  * send_lphb_config_tcp_pkt_filter_cmd_tlv() - configure tcp packet filter cmd
1351  * @wmi_handle: wmi handle
1352  * @g_hb_tcp_filter_fp: tcp packet filter params
1353  *
1354  * Return: QDF status
1355  */
1356 static
1357 QDF_STATUS send_lphb_config_tcp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,
1358 		wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *g_hb_tcp_filter_fp)
1359 {
1360 	QDF_STATUS status;
1361 	wmi_buf_t buf = NULL;
1362 	uint8_t *buf_ptr;
1363 	wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *hb_tcp_filter_fp;
1364 	int len = sizeof(wmi_hb_set_tcp_pkt_filter_cmd_fixed_param);
1365 
1366 	buf = wmi_buf_alloc(wmi_handle, len);
1367 	if (!buf) {
1368 		return QDF_STATUS_E_NOMEM;
1369 	}
1370 
1371 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1372 	hb_tcp_filter_fp =
1373 		(wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *) buf_ptr;
1374 	WMITLV_SET_HDR(&hb_tcp_filter_fp->tlv_header,
1375 		WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param,
1376 		WMITLV_GET_STRUCT_TLVLEN
1377 		       (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param));
1378 
1379 	/* fill in values */
1380 	hb_tcp_filter_fp->vdev_id = g_hb_tcp_filter_fp->vdev_id;
1381 	hb_tcp_filter_fp->length = g_hb_tcp_filter_fp->length;
1382 	hb_tcp_filter_fp->offset = g_hb_tcp_filter_fp->offset;
1383 	hb_tcp_filter_fp->session = g_hb_tcp_filter_fp->session;
1384 	memcpy((void *)&hb_tcp_filter_fp->filter,
1385 	       (void *)&g_hb_tcp_filter_fp->filter,
1386 	       WMI_WLAN_HB_MAX_FILTER_SIZE);
1387 
1388 	wmi_mtrace(WMI_HB_SET_TCP_PKT_FILTER_CMDID, NO_SESSION, 0);
1389 	status = wmi_unified_cmd_send(wmi_handle, buf,
1390 				      len, WMI_HB_SET_TCP_PKT_FILTER_CMDID);
1391 	if (QDF_IS_STATUS_ERROR(status)) {
1392 		wmi_err("cmd_send WMI_HB_SET_TCP_PKT_FILTER returned Error %d",
1393 			 status);
1394 		wmi_buf_free(buf);
1395 	}
1396 
1397 	return status;
1398 }
1399 
1400 /**
1401  * send_lphb_config_udp_params_cmd_tlv() - configure udp param command of LPHB
1402  * @wmi_handle: wmi handle
1403  * @lphb_conf_req: lphb config request
1404  *
1405  * Return: QDF status
1406  */
1407 static QDF_STATUS send_lphb_config_udp_params_cmd_tlv(wmi_unified_t wmi_handle,
1408 		   wmi_hb_set_udp_params_cmd_fixed_param *lphb_conf_req)
1409 {
1410 	QDF_STATUS status;
1411 	wmi_buf_t buf = NULL;
1412 	uint8_t *buf_ptr;
1413 	wmi_hb_set_udp_params_cmd_fixed_param *hb_udp_params_fp;
1414 	int len = sizeof(wmi_hb_set_udp_params_cmd_fixed_param);
1415 
1416 	buf = wmi_buf_alloc(wmi_handle, len);
1417 	if (!buf) {
1418 		return QDF_STATUS_E_NOMEM;
1419 	}
1420 
1421 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1422 	hb_udp_params_fp = (wmi_hb_set_udp_params_cmd_fixed_param *) buf_ptr;
1423 	WMITLV_SET_HDR(&hb_udp_params_fp->tlv_header,
1424 		       WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param,
1425 		       WMITLV_GET_STRUCT_TLVLEN
1426 			       (wmi_hb_set_udp_params_cmd_fixed_param));
1427 
1428 	/* fill in values */
1429 	hb_udp_params_fp->vdev_id = lphb_conf_req->vdev_id;
1430 	hb_udp_params_fp->srv_ip = lphb_conf_req->srv_ip;
1431 	hb_udp_params_fp->dev_ip = lphb_conf_req->dev_ip;
1432 	hb_udp_params_fp->src_port = lphb_conf_req->src_port;
1433 	hb_udp_params_fp->dst_port = lphb_conf_req->dst_port;
1434 	hb_udp_params_fp->interval = lphb_conf_req->interval;
1435 	hb_udp_params_fp->timeout = lphb_conf_req->timeout;
1436 	hb_udp_params_fp->session = lphb_conf_req->session;
1437 	qdf_mem_copy(&hb_udp_params_fp->gateway_mac,
1438 		     &lphb_conf_req->gateway_mac,
1439 		     sizeof(lphb_conf_req->gateway_mac));
1440 
1441 	wmi_mtrace(WMI_HB_SET_UDP_PARAMS_CMDID, NO_SESSION, 0);
1442 	status = wmi_unified_cmd_send(wmi_handle, buf,
1443 				      len, WMI_HB_SET_UDP_PARAMS_CMDID);
1444 	if (QDF_IS_STATUS_ERROR(status)) {
1445 		wmi_err("cmd_send WMI_HB_SET_UDP_PARAMS returned Error %d",
1446 			 status);
1447 		wmi_buf_free(buf);
1448 	}
1449 
1450 	return status;
1451 }
1452 
1453 /**
1454  * send_lphb_config_udp_pkt_filter_cmd_tlv() - configure udp pkt filter command
1455  * @wmi_handle: wmi handle
1456  * @lphb_conf_req: lphb config request
1457  *
1458  * Return: QDF status
1459  */
1460 static
1461 QDF_STATUS send_lphb_config_udp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,
1462 		wmi_hb_set_udp_pkt_filter_cmd_fixed_param *lphb_conf_req)
1463 {
1464 	QDF_STATUS status;
1465 	wmi_buf_t buf = NULL;
1466 	uint8_t *buf_ptr;
1467 	wmi_hb_set_udp_pkt_filter_cmd_fixed_param *hb_udp_filter_fp;
1468 	int len = sizeof(wmi_hb_set_udp_pkt_filter_cmd_fixed_param);
1469 
1470 	buf = wmi_buf_alloc(wmi_handle, len);
1471 	if (!buf) {
1472 		return QDF_STATUS_E_NOMEM;
1473 	}
1474 
1475 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1476 	hb_udp_filter_fp =
1477 		(wmi_hb_set_udp_pkt_filter_cmd_fixed_param *) buf_ptr;
1478 	WMITLV_SET_HDR(&hb_udp_filter_fp->tlv_header,
1479 		WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param,
1480 		WMITLV_GET_STRUCT_TLVLEN
1481 		       (wmi_hb_set_udp_pkt_filter_cmd_fixed_param));
1482 
1483 	/* fill in values */
1484 	hb_udp_filter_fp->vdev_id = lphb_conf_req->vdev_id;
1485 	hb_udp_filter_fp->length = lphb_conf_req->length;
1486 	hb_udp_filter_fp->offset = lphb_conf_req->offset;
1487 	hb_udp_filter_fp->session = lphb_conf_req->session;
1488 	memcpy((void *)&hb_udp_filter_fp->filter,
1489 	       (void *)&lphb_conf_req->filter,
1490 	       WMI_WLAN_HB_MAX_FILTER_SIZE);
1491 
1492 	wmi_mtrace(WMI_HB_SET_UDP_PKT_FILTER_CMDID, NO_SESSION, 0);
1493 	status = wmi_unified_cmd_send(wmi_handle, buf,
1494 				      len, WMI_HB_SET_UDP_PKT_FILTER_CMDID);
1495 	if (QDF_IS_STATUS_ERROR(status)) {
1496 		wmi_err("cmd_send WMI_HB_SET_UDP_PKT_FILTER returned Error %d",
1497 			 status);
1498 		wmi_buf_free(buf);
1499 	}
1500 
1501 	return status;
1502 }
1503 
1504 void wmi_lphb_attach_tlv(struct wmi_unified *wmi_handle)
1505 {
1506 	struct wmi_ops *ops = wmi_handle->ops;
1507 
1508 	ops->send_lphb_config_hbenable_cmd =
1509 		send_lphb_config_hbenable_cmd_tlv;
1510 	ops->send_lphb_config_tcp_params_cmd =
1511 		send_lphb_config_tcp_params_cmd_tlv;
1512 	ops->send_lphb_config_tcp_pkt_filter_cmd =
1513 		send_lphb_config_tcp_pkt_filter_cmd_tlv;
1514 	ops->send_lphb_config_udp_params_cmd =
1515 		send_lphb_config_udp_params_cmd_tlv;
1516 	ops->send_lphb_config_udp_pkt_filter_cmd =
1517 		send_lphb_config_udp_pkt_filter_cmd_tlv;
1518 }
1519 #endif /* FEATURE_WLAN_LPHB */
1520 
1521 #ifdef WLAN_FEATURE_PACKET_FILTERING
1522 /**
1523  * send_enable_disable_packet_filter_cmd_tlv() - enable/disable packet filter
1524  * @wmi_handle: wmi handle
1525  * @vdev_id: vdev id
1526  * @enable: Flag to enable/disable packet filter
1527  *
1528  * Return: QDF_STATUS_SUCCESS for success or error code
1529  */
1530 static QDF_STATUS send_enable_disable_packet_filter_cmd_tlv(
1531 		wmi_unified_t wmi_handle, uint8_t vdev_id, bool enable)
1532 {
1533 	int32_t len;
1534 	int ret = 0;
1535 	wmi_buf_t buf;
1536 	WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *cmd;
1537 
1538 	len = sizeof(WMI_PACKET_FILTER_ENABLE_CMD_fixed_param);
1539 
1540 	buf = wmi_buf_alloc(wmi_handle, len);
1541 	if (!buf) {
1542 		return QDF_STATUS_E_NOMEM;
1543 	}
1544 
1545 	cmd = (WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *) wmi_buf_data(buf);
1546 	WMITLV_SET_HDR(&cmd->tlv_header,
1547 		WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param,
1548 		WMITLV_GET_STRUCT_TLVLEN(
1549 			WMI_PACKET_FILTER_ENABLE_CMD_fixed_param));
1550 
1551 	cmd->vdev_id = vdev_id;
1552 	if (enable)
1553 		cmd->enable = PACKET_FILTER_SET_ENABLE;
1554 	else
1555 		cmd->enable = PACKET_FILTER_SET_DISABLE;
1556 
1557 	wmi_err("Packet filter enable %d for vdev_id %d", cmd->enable, vdev_id);
1558 
1559 	wmi_mtrace(WMI_PACKET_FILTER_ENABLE_CMDID, cmd->vdev_id, 0);
1560 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1561 				   WMI_PACKET_FILTER_ENABLE_CMDID);
1562 	if (ret) {
1563 		wmi_err("Failed to send packet filter wmi cmd to fw");
1564 		wmi_buf_free(buf);
1565 	}
1566 
1567 	return ret;
1568 }
1569 
1570 /**
1571  * send_config_packet_filter_cmd_tlv() - configure packet filter in target
1572  * @wmi_handle: wmi handle
1573  * @vdev_id: vdev id
1574  * @rcv_filter_param: Packet filter parameters
1575  * @filter_id: Filter id
1576  * @enable: Flag to add/delete packet filter configuration
1577  *
1578  * Return: QDF_STATUS_SUCCESS for success or error code
1579  */
1580 static QDF_STATUS send_config_packet_filter_cmd_tlv(wmi_unified_t wmi_handle,
1581 		uint8_t vdev_id, struct pmo_rcv_pkt_fltr_cfg *rcv_filter_param,
1582 		uint8_t filter_id, bool enable)
1583 {
1584 	int len, i;
1585 	int err = 0;
1586 	wmi_buf_t buf;
1587 	WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *cmd;
1588 
1589 	/* allocate the memory */
1590 	len = sizeof(*cmd);
1591 	buf = wmi_buf_alloc(wmi_handle, len);
1592 	if (!buf) {
1593 		return QDF_STATUS_E_NOMEM;
1594 	}
1595 
1596 	cmd = (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *)wmi_buf_data(buf);
1597 	WMITLV_SET_HDR(&cmd->tlv_header,
1598 		WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param,
1599 		WMITLV_GET_STRUCT_TLVLEN
1600 			       (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param));
1601 
1602 	cmd->vdev_id = vdev_id;
1603 	cmd->filter_id = filter_id;
1604 	if (enable)
1605 		cmd->filter_action = PACKET_FILTER_SET_ACTIVE;
1606 	else
1607 		cmd->filter_action = PACKET_FILTER_SET_INACTIVE;
1608 
1609 	if (enable) {
1610 		cmd->num_params = QDF_MIN(
1611 			WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER,
1612 			rcv_filter_param->num_params);
1613 		cmd->filter_type = rcv_filter_param->filter_type;
1614 		cmd->coalesce_time = rcv_filter_param->coalesce_time;
1615 
1616 		for (i = 0; i < cmd->num_params; i++) {
1617 			cmd->paramsData[i].proto_type =
1618 				rcv_filter_param->params_data[i].protocol_layer;
1619 			cmd->paramsData[i].cmp_type =
1620 				rcv_filter_param->params_data[i].compare_flag;
1621 			cmd->paramsData[i].data_length =
1622 				rcv_filter_param->params_data[i].data_length;
1623 			cmd->paramsData[i].data_offset =
1624 				rcv_filter_param->params_data[i].data_offset;
1625 			memcpy(&cmd->paramsData[i].compareData,
1626 				rcv_filter_param->params_data[i].compare_data,
1627 				sizeof(cmd->paramsData[i].compareData));
1628 			memcpy(&cmd->paramsData[i].dataMask,
1629 				rcv_filter_param->params_data[i].data_mask,
1630 				sizeof(cmd->paramsData[i].dataMask));
1631 		}
1632 	}
1633 
1634 	wmi_err("Packet filter action %d filter with id: %d, num_params=%d",
1635 		 cmd->filter_action, cmd->filter_id, cmd->num_params);
1636 	/* send the command along with data */
1637 	wmi_mtrace(WMI_PACKET_FILTER_CONFIG_CMDID, cmd->vdev_id, 0);
1638 	err = wmi_unified_cmd_send(wmi_handle, buf, len,
1639 				   WMI_PACKET_FILTER_CONFIG_CMDID);
1640 	if (err) {
1641 		wmi_err("Failed to send pkt_filter cmd");
1642 		wmi_buf_free(buf);
1643 		return QDF_STATUS_E_FAILURE;
1644 	}
1645 
1646 	return QDF_STATUS_SUCCESS;
1647 }
1648 
1649 void wmi_packet_filtering_attach_tlv(struct wmi_unified *wmi_handle)
1650 {
1651 	struct wmi_ops *ops = wmi_handle->ops;
1652 
1653 	ops->send_enable_disable_packet_filter_cmd =
1654 		send_enable_disable_packet_filter_cmd_tlv;
1655 	ops->send_config_packet_filter_cmd =
1656 		send_config_packet_filter_cmd_tlv;
1657 }
1658 #endif /* WLAN_FEATURE_PACKET_FILTERING */
1659 
1660 /**
1661  * send_wow_delete_pattern_cmd_tlv() - delete wow pattern in target
1662  * @wmi_handle: wmi handle
1663  * @ptrn_id: pattern id
1664  * @vdev_id: vdev id
1665  *
1666  * Return: QDF status
1667  */
1668 static QDF_STATUS send_wow_delete_pattern_cmd_tlv(wmi_unified_t wmi_handle,
1669 						  uint8_t ptrn_id,
1670 						  uint8_t vdev_id)
1671 {
1672 	WMI_WOW_DEL_PATTERN_CMD_fixed_param *cmd;
1673 	wmi_buf_t buf;
1674 	int32_t len;
1675 	int ret;
1676 
1677 	len = sizeof(WMI_WOW_DEL_PATTERN_CMD_fixed_param);
1678 
1679 	buf = wmi_buf_alloc(wmi_handle, len);
1680 	if (!buf) {
1681 		return QDF_STATUS_E_NOMEM;
1682 	}
1683 
1684 	cmd = (WMI_WOW_DEL_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1685 
1686 	WMITLV_SET_HDR(&cmd->tlv_header,
1687 		       WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param,
1688 		       WMITLV_GET_STRUCT_TLVLEN(
1689 				WMI_WOW_DEL_PATTERN_CMD_fixed_param));
1690 	cmd->vdev_id = vdev_id;
1691 	cmd->pattern_id = ptrn_id;
1692 	cmd->pattern_type = WOW_BITMAP_PATTERN;
1693 
1694 	wmi_mtrace(WMI_WOW_DEL_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
1695 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1696 				   WMI_WOW_DEL_WAKE_PATTERN_CMDID);
1697 	if (ret) {
1698 		wmi_err("Failed to delete wow ptrn from fw");
1699 		wmi_buf_free(buf);
1700 		return QDF_STATUS_E_FAILURE;
1701 	}
1702 
1703 	return QDF_STATUS_SUCCESS;
1704 }
1705 
1706 #ifdef WMI_HOST_WAKEUP_OVER_QMI
1707 static inline
1708 QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle,
1709 				    wmi_buf_t buf,
1710 				    uint32_t buflen, uint32_t cmd_id)
1711 {
1712 	wmi_debug("Send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID over QMI");
1713 	return wmi_unified_cmd_send_over_qmi(wmi_handle, buf,
1714 					     buflen, cmd_id);
1715 }
1716 #else
1717 static inline
1718 QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle,
1719 				    wmi_buf_t buf,
1720 				    uint32_t buflen, uint32_t cmd_id)
1721 {
1722 	return wmi_unified_cmd_send(wmi_handle, buf,
1723 				    buflen, cmd_id);
1724 }
1725 #endif
1726 
1727 /**
1728  * send_host_wakeup_ind_to_fw_cmd_tlv() - send wakeup ind to fw
1729  * @wmi_handle: wmi handle
1730  * @tx_pending_ind: flag of TX has pending frames
1731  *
1732  * Sends host wakeup indication to FW. On receiving this indication,
1733  * FW will come out of WOW.
1734  *
1735  * Return: QDF status
1736  */
1737 static QDF_STATUS send_host_wakeup_ind_to_fw_cmd_tlv(wmi_unified_t wmi_handle,
1738 						     bool tx_pending_ind)
1739 {
1740 	wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *cmd;
1741 	wmi_buf_t buf;
1742 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1743 	int32_t len;
1744 	int ret;
1745 
1746 	len = sizeof(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param);
1747 
1748 	buf = wmi_buf_alloc(wmi_handle, len);
1749 	if (!buf) {
1750 		return QDF_STATUS_E_NOMEM;
1751 	}
1752 
1753 	cmd = (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *)
1754 	      wmi_buf_data(buf);
1755 
1756 	if (tx_pending_ind) {
1757 		wmi_debug("TX pending before WoW wake, indicate FW");
1758 		cmd->flags |= WMI_WOW_RESUME_FLAG_TX_DATA;
1759 	}
1760 
1761 	WMITLV_SET_HDR(&cmd->tlv_header,
1762 		WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param,
1763 		WMITLV_GET_STRUCT_TLVLEN
1764 			(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param));
1765 
1766 	wmi_mtrace(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, NO_SESSION, 0);
1767 	ret = wmi_unified_cmd_send_chk(wmi_handle, buf, len,
1768 				       WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
1769 	if (ret) {
1770 		wmi_err("Failed to send host wakeup indication to fw");
1771 		wmi_buf_free(buf);
1772 		return QDF_STATUS_E_FAILURE;
1773 	}
1774 
1775 	return qdf_status;
1776 }
1777 
1778 /**
1779  * send_wow_timer_pattern_cmd_tlv() - set timer pattern tlv, so that firmware
1780  * will wake up host after specified time is elapsed
1781  * @wmi_handle: wmi handle
1782  * @vdev_id: vdev id
1783  * @cookie: value to identify reason why host set up wake call.
1784  * @time: time in ms
1785  *
1786  * Return: QDF status
1787  */
1788 static QDF_STATUS send_wow_timer_pattern_cmd_tlv(wmi_unified_t wmi_handle,
1789 				uint8_t vdev_id, uint32_t cookie, uint32_t time)
1790 {
1791 	WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
1792 	wmi_buf_t buf;
1793 	uint8_t *buf_ptr;
1794 	int32_t len;
1795 	int ret;
1796 
1797 	len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
1798 		WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_BITMAP_PATTERN_T) +
1799 		WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
1800 		WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
1801 		WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
1802 		WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t) +
1803 		WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
1804 
1805 	buf = wmi_buf_alloc(wmi_handle, len);
1806 	if (!buf) {
1807 		return QDF_STATUS_E_NOMEM;
1808 	}
1809 
1810 	cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1811 	buf_ptr = (uint8_t *) cmd;
1812 
1813 	WMITLV_SET_HDR(&cmd->tlv_header,
1814 		WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
1815 		WMITLV_GET_STRUCT_TLVLEN
1816 			(WMI_WOW_ADD_PATTERN_CMD_fixed_param));
1817 	cmd->vdev_id = vdev_id;
1818 	cmd->pattern_id = cookie,
1819 	cmd->pattern_type = WOW_TIMER_PATTERN;
1820 	buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
1821 
1822 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
1823 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1824 	buf_ptr += WMI_TLV_HDR_SIZE;
1825 
1826 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
1827 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1828 	buf_ptr += WMI_TLV_HDR_SIZE;
1829 
1830 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
1831 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1832 	buf_ptr += WMI_TLV_HDR_SIZE;
1833 
1834 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
1835 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1836 	buf_ptr += WMI_TLV_HDR_SIZE;
1837 
1838 	/* Fill TLV for pattern_info_timeout, and time value */
1839 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
1840 	buf_ptr += WMI_TLV_HDR_SIZE;
1841 	*((uint32_t *) buf_ptr) = time;
1842 	buf_ptr += sizeof(uint32_t);
1843 
1844 	/* Fill TLV for ra_ratelimit_interval. with dummy 0 value */
1845 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
1846 	buf_ptr += WMI_TLV_HDR_SIZE;
1847 	*((uint32_t *) buf_ptr) = 0;
1848 
1849 	wmi_debug("send wake timer pattern with time[%d] to fw vdev = %d",
1850 		 time, vdev_id);
1851 
1852 	wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
1853 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1854 				WMI_WOW_ADD_WAKE_PATTERN_CMDID);
1855 	if (ret) {
1856 		wmi_err("Failed to send wake timer pattern to fw");
1857 		wmi_buf_free(buf);
1858 		return QDF_STATUS_E_FAILURE;
1859 	}
1860 
1861 	return QDF_STATUS_SUCCESS;
1862 }
1863 
1864 #ifdef WLAN_FEATURE_EXTWOW_SUPPORT
1865 /**
1866  * send_enable_ext_wow_cmd_tlv() - enable ext wow in fw
1867  * @wmi_handle: wmi handle
1868  * @params: ext wow params
1869  *
1870  * Return:0 for success or error code
1871  */
1872 static QDF_STATUS send_enable_ext_wow_cmd_tlv(wmi_unified_t wmi_handle,
1873 					      struct ext_wow_params *params)
1874 {
1875 	wmi_extwow_enable_cmd_fixed_param *cmd;
1876 	wmi_buf_t buf;
1877 	int32_t len;
1878 	int ret;
1879 
1880 	len = sizeof(wmi_extwow_enable_cmd_fixed_param);
1881 	buf = wmi_buf_alloc(wmi_handle, len);
1882 	if (!buf) {
1883 		return QDF_STATUS_E_NOMEM;
1884 	}
1885 
1886 	cmd = (wmi_extwow_enable_cmd_fixed_param *) wmi_buf_data(buf);
1887 
1888 	WMITLV_SET_HDR(&cmd->tlv_header,
1889 		       WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param,
1890 		       WMITLV_GET_STRUCT_TLVLEN
1891 			       (wmi_extwow_enable_cmd_fixed_param));
1892 
1893 	cmd->vdev_id = params->vdev_id;
1894 	cmd->type = params->type;
1895 	cmd->wakeup_pin_num = params->wakeup_pin_num;
1896 
1897 	wmi_debug("vdev_id %d type %d Wakeup_pin_num %x",
1898 		 cmd->vdev_id, cmd->type, cmd->wakeup_pin_num);
1899 
1900 	wmi_mtrace(WMI_EXTWOW_ENABLE_CMDID, cmd->vdev_id, 0);
1901 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1902 				   WMI_EXTWOW_ENABLE_CMDID);
1903 	if (ret) {
1904 		wmi_err("Failed to set EXTWOW Enable");
1905 		wmi_buf_free(buf);
1906 		return QDF_STATUS_E_FAILURE;
1907 	}
1908 
1909 	return QDF_STATUS_SUCCESS;
1910 
1911 }
1912 
1913 /**
1914  * send_set_app_type2_params_in_fw_cmd_tlv() - set app type2 params in fw
1915  * @wmi_handle: wmi handle
1916  * @appType2Params: app type2 params
1917  *
1918  * Return: QDF status
1919  */
1920 static QDF_STATUS send_set_app_type2_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,
1921 			  struct app_type2_params *appType2Params)
1922 {
1923 	wmi_extwow_set_app_type2_params_cmd_fixed_param *cmd;
1924 	wmi_buf_t buf;
1925 	int32_t len;
1926 	int ret;
1927 
1928 	len = sizeof(wmi_extwow_set_app_type2_params_cmd_fixed_param);
1929 	buf = wmi_buf_alloc(wmi_handle, len);
1930 	if (!buf) {
1931 		return QDF_STATUS_E_NOMEM;
1932 	}
1933 
1934 	cmd = (wmi_extwow_set_app_type2_params_cmd_fixed_param *)
1935 	      wmi_buf_data(buf);
1936 
1937 	WMITLV_SET_HDR(&cmd->tlv_header,
1938 	       WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param,
1939 	       WMITLV_GET_STRUCT_TLVLEN
1940 			(wmi_extwow_set_app_type2_params_cmd_fixed_param));
1941 
1942 	cmd->vdev_id = appType2Params->vdev_id;
1943 
1944 	qdf_mem_copy(cmd->rc4_key, appType2Params->rc4_key, 16);
1945 	cmd->rc4_key_len = appType2Params->rc4_key_len;
1946 
1947 	cmd->ip_id = appType2Params->ip_id;
1948 	cmd->ip_device_ip = appType2Params->ip_device_ip;
1949 	cmd->ip_server_ip = appType2Params->ip_server_ip;
1950 
1951 	cmd->tcp_src_port = appType2Params->tcp_src_port;
1952 	cmd->tcp_dst_port = appType2Params->tcp_dst_port;
1953 	cmd->tcp_seq = appType2Params->tcp_seq;
1954 	cmd->tcp_ack_seq = appType2Params->tcp_ack_seq;
1955 
1956 	cmd->keepalive_init = appType2Params->keepalive_init;
1957 	cmd->keepalive_min = appType2Params->keepalive_min;
1958 	cmd->keepalive_max = appType2Params->keepalive_max;
1959 	cmd->keepalive_inc = appType2Params->keepalive_inc;
1960 
1961 	WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac.bytes,
1962 				   &cmd->gateway_mac);
1963 	cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
1964 	cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
1965 
1966 	wmi_debug("vdev_id %d gateway_mac "QDF_MAC_ADDR_FMT" "
1967 		 "rc4_key %.16s rc4_key_len %u "
1968 		 "ip_id %x ip_device_ip %x ip_server_ip %x "
1969 		 "tcp_src_port %u tcp_dst_port %u tcp_seq %u "
1970 		 "tcp_ack_seq %u keepalive_init %u keepalive_min %u "
1971 		 "keepalive_max %u keepalive_inc %u "
1972 		 "tcp_tx_timeout_val %u tcp_rx_timeout_val %u",
1973 		 cmd->vdev_id,
1974 		 QDF_MAC_ADDR_REF(appType2Params->gateway_mac.bytes),
1975 		 cmd->rc4_key, cmd->rc4_key_len,
1976 		 cmd->ip_id, cmd->ip_device_ip, cmd->ip_server_ip,
1977 		 cmd->tcp_src_port, cmd->tcp_dst_port, cmd->tcp_seq,
1978 		 cmd->tcp_ack_seq, cmd->keepalive_init, cmd->keepalive_min,
1979 		 cmd->keepalive_max, cmd->keepalive_inc,
1980 		 cmd->tcp_tx_timeout_val, cmd->tcp_rx_timeout_val);
1981 
1982 	wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID, cmd->vdev_id, 0);
1983 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1984 				   WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID);
1985 	if (ret) {
1986 		wmi_err("Failed to set APP TYPE2 PARAMS");
1987 		wmi_buf_free(buf);
1988 		return QDF_STATUS_E_FAILURE;
1989 	}
1990 
1991 	return QDF_STATUS_SUCCESS;
1992 
1993 }
1994 
1995 /**
1996  * send_app_type1_params_in_fw_cmd_tlv() - set app type1 params in fw
1997  * @wmi_handle: wmi handle
1998  * @app_type1_params: app type1 params
1999  *
2000  * Return: QDF status
2001  */
2002 static QDF_STATUS send_app_type1_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,
2003 				   struct app_type1_params *app_type1_params)
2004 {
2005 	wmi_extwow_set_app_type1_params_cmd_fixed_param *cmd;
2006 	wmi_buf_t buf;
2007 	int32_t len;
2008 	int ret;
2009 
2010 	len = sizeof(wmi_extwow_set_app_type1_params_cmd_fixed_param);
2011 	buf = wmi_buf_alloc(wmi_handle, len);
2012 	if (!buf) {
2013 		return QDF_STATUS_E_NOMEM;
2014 	}
2015 
2016 	cmd = (wmi_extwow_set_app_type1_params_cmd_fixed_param *)
2017 	      wmi_buf_data(buf);
2018 
2019 	WMITLV_SET_HDR(&cmd->tlv_header,
2020 	       WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param,
2021 	       WMITLV_GET_STRUCT_TLVLEN
2022 	       (wmi_extwow_set_app_type1_params_cmd_fixed_param));
2023 
2024 	cmd->vdev_id = app_type1_params->vdev_id;
2025 	WMI_CHAR_ARRAY_TO_MAC_ADDR(app_type1_params->wakee_mac_addr.bytes,
2026 				   &cmd->wakee_mac);
2027 	qdf_mem_copy(cmd->ident, app_type1_params->identification_id, 8);
2028 	cmd->ident_len = app_type1_params->id_length;
2029 	qdf_mem_copy(cmd->passwd, app_type1_params->password, 16);
2030 	cmd->passwd_len = app_type1_params->pass_length;
2031 
2032 	wmi_debug("vdev_id %d wakee_mac_addr "QDF_MAC_ADDR_FMT" "
2033 		 "identification_id %.8s id_length %u "
2034 		 "password %.16s pass_length %u",
2035 		 cmd->vdev_id,
2036 		 QDF_MAC_ADDR_REF(app_type1_params->wakee_mac_addr.bytes),
2037 		 cmd->ident, cmd->ident_len, cmd->passwd, cmd->passwd_len);
2038 
2039 	wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID, cmd->vdev_id, 0);
2040 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
2041 				   WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID);
2042 	if (ret) {
2043 		wmi_err("Failed to set APP TYPE1 PARAMS");
2044 		wmi_buf_free(buf);
2045 		return QDF_STATUS_E_FAILURE;
2046 	}
2047 
2048 	return QDF_STATUS_SUCCESS;
2049 }
2050 
2051 void wmi_extwow_attach_tlv(struct wmi_unified *wmi_handle)
2052 {
2053 	struct wmi_ops *ops = wmi_handle->ops;
2054 
2055 	ops->send_enable_ext_wow_cmd = send_enable_ext_wow_cmd_tlv;
2056 	ops->send_set_app_type2_params_in_fw_cmd =
2057 		send_set_app_type2_params_in_fw_cmd_tlv;
2058 	ops->send_app_type1_params_in_fw_cmd =
2059 		send_app_type1_params_in_fw_cmd_tlv;
2060 }
2061 #endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
2062 
2063 #ifdef WLAN_FEATURE_ICMP_OFFLOAD
2064 /**
2065  * send_icmp_ipv4_config_cmd_tlv() - send ICMP IPV4 offload command to fw
2066  * @wmi_handle: wmi handle
2067  * @pmo_icmp_req: ICMP offload parameters
2068  *
2069  * Return: QDF status
2070  */
2071 static QDF_STATUS
2072 send_icmp_ipv4_config_cmd_tlv(wmi_unified_t wmi_handle,
2073 			      struct pmo_icmp_offload *pmo_icmp_req)
2074 {
2075 	wmi_buf_t buf;
2076 	wmi_icmp_offload_fixed_param *cmd;
2077 	uint16_t len = sizeof(*cmd);
2078 	QDF_STATUS status;
2079 
2080 	buf = wmi_buf_alloc(wmi_handle, len);
2081 	if (!buf) {
2082 		wmi_err_rl("Failed to allocate wmi buffer");
2083 		status = QDF_STATUS_E_NOMEM;
2084 		return status;
2085 	}
2086 	cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf);
2087 	WMITLV_SET_HDR(&cmd->tlv_header,
2088 		       WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param,
2089 		       WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param));
2090 
2091 	cmd->vdev_id = pmo_icmp_req->vdev_id;
2092 	cmd->enable = pmo_icmp_req->enable;
2093 	cmd->valid_bitmask = 0;
2094 
2095 	WMI_SET_ICMP_OFFLOAD_IPV4_ENABLED_BIT(cmd->valid_bitmask);
2096 	qdf_mem_copy(&cmd->ipv4_addr, pmo_icmp_req->ipv4_addr,
2097 		     QDF_IPV4_ADDR_SIZE);
2098 	wmi_debug("ipv4:%pI4", &cmd->ipv4_addr);
2099 
2100 	wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
2101 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
2102 				      WMI_VDEV_ICMP_OFFLOAD_CMDID);
2103 
2104 	if (QDF_IS_STATUS_ERROR(status))
2105 		wmi_buf_free(buf);
2106 
2107 	return status;
2108 }
2109 
2110 /**
2111  * send_icmp_ipv6_config_cmd_tlv() - send ICMP IPV6 offload command to fw
2112  * @wmi_handle: wmi handle
2113  * @pmo_icmp_req: ICMP offload parameters
2114  *
2115  * Return: QDF status
2116  */
2117 static QDF_STATUS
2118 send_icmp_ipv6_config_cmd_tlv(wmi_unified_t wmi_handle,
2119 			      struct pmo_icmp_offload *pmo_icmp_req)
2120 {
2121 	wmi_buf_t buf;
2122 	uint8_t *buf_ptr;
2123 	uint16_t len;
2124 	int i;
2125 	WMI_IPV6_ADDR *ipv6_list;
2126 	wmi_icmp_offload_fixed_param *cmd;
2127 	QDF_STATUS status;
2128 
2129 	len = sizeof(wmi_icmp_offload_fixed_param) + WMI_TLV_HDR_SIZE +
2130 	      (pmo_icmp_req->ipv6_count) * sizeof(WMI_IPV6_ADDR);
2131 
2132 	buf = wmi_buf_alloc(wmi_handle, len);
2133 	if (!buf) {
2134 		wmi_err_rl("Failed to allocate wmi buffer");
2135 		status = QDF_STATUS_E_NOMEM;
2136 		return status;
2137 	}
2138 
2139 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
2140 	cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf);
2141 	WMITLV_SET_HDR(&cmd->tlv_header,
2142 		       WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param,
2143 		       WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param));
2144 
2145 	cmd->vdev_id = pmo_icmp_req->vdev_id;
2146 	cmd->enable = pmo_icmp_req->enable;
2147 	cmd->valid_bitmask = 0;
2148 
2149 	WMI_SET_ICMP_OFFLOAD_IPV6_ENABLED_BIT(cmd->valid_bitmask);
2150 	buf_ptr += sizeof(*cmd);
2151 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
2152 		       sizeof(WMI_IPV6_ADDR) * pmo_icmp_req->ipv6_count);
2153 	ipv6_list = (WMI_IPV6_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE);
2154 
2155 	for (i = 0; i < pmo_icmp_req->ipv6_count; i++) {
2156 		qdf_mem_copy(((*(ipv6_list + i)).address),
2157 			     &pmo_icmp_req->ipv6_addr[i],
2158 			     sizeof(WMI_IPV6_ADDR));
2159 		wmi_debug("ipv6_list[%d]:%pI6", i, (ipv6_list + i));
2160 	}
2161 
2162 	/* send the wmi command */
2163 	wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
2164 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
2165 				      WMI_VDEV_ICMP_OFFLOAD_CMDID);
2166 
2167 	if (QDF_IS_STATUS_ERROR(status))
2168 		wmi_buf_free(buf);
2169 
2170 	return status;
2171 }
2172 
2173 /**
2174  * send_icmp_offload_config_cmd_tlv() - send ICMP offload command to fw
2175  * @wmi_handle: wmi handle
2176  * @pmo_icmp_req: ICMP offload parameters
2177  *
2178  * Return: QDF status
2179  */
2180 static QDF_STATUS
2181 send_icmp_offload_config_cmd_tlv(wmi_unified_t wmi_handle,
2182 				 struct pmo_icmp_offload *pmo_icmp_req)
2183 {
2184 	QDF_STATUS status;
2185 
2186 	switch (pmo_icmp_req->trigger) {
2187 	case pmo_ipv4_change_notify:
2188 		status = send_icmp_ipv4_config_cmd_tlv(wmi_handle,
2189 						       pmo_icmp_req);
2190 		break;
2191 	case pmo_ipv6_change_notify:
2192 		status = send_icmp_ipv6_config_cmd_tlv(wmi_handle,
2193 						       pmo_icmp_req);
2194 		break;
2195 	default:
2196 		QDF_DEBUG_PANIC("Invalid ICMP trigger %d",
2197 				pmo_icmp_req->trigger);
2198 		status = QDF_STATUS_E_FAILURE;
2199 	}
2200 
2201 	return status;
2202 }
2203 
2204 static void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle)
2205 {
2206 	struct wmi_ops *ops = wmi_handle->ops;
2207 
2208 	ops->send_icmp_offload_config_cmd = send_icmp_offload_config_cmd_tlv;
2209 }
2210 #else
2211 static inline void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle)
2212 {}
2213 #endif /* WLAN_FEATURE_ICMP_OFFLOAD */
2214 
2215 void wmi_pmo_attach_tlv(wmi_unified_t wmi_handle)
2216 {
2217 	struct wmi_ops *ops = wmi_handle->ops;
2218 
2219 	ops->send_add_wow_wakeup_event_cmd =
2220 		send_add_wow_wakeup_event_cmd_tlv;
2221 	ops->send_wow_patterns_to_fw_cmd = send_wow_patterns_to_fw_cmd_tlv;
2222 	ops->send_enable_arp_ns_offload_cmd =
2223 		send_enable_arp_ns_offload_cmd_tlv;
2224 	ops->send_add_clear_mcbc_filter_cmd =
2225 		send_add_clear_mcbc_filter_cmd_tlv;
2226 	ops->send_multiple_add_clear_mcbc_filter_cmd =
2227 		send_multiple_add_clear_mcbc_filter_cmd_tlv;
2228 	ops->send_conf_hw_filter_cmd = send_conf_hw_filter_cmd_tlv;
2229 	ops->send_gtk_offload_cmd = send_gtk_offload_cmd_tlv;
2230 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
2231 	ops->send_igmp_offload_cmd = send_igmp_offload_cmd_tlv;
2232 #endif
2233 	ops->send_process_gtk_offload_getinfo_cmd =
2234 		send_process_gtk_offload_getinfo_cmd_tlv;
2235 	ops->send_enable_enhance_multicast_offload_cmd =
2236 		send_enable_enhance_multicast_offload_tlv;
2237 	ops->extract_gtk_rsp_event = extract_gtk_rsp_event_tlv;
2238 	ops->send_action_frame_patterns_cmd =
2239 		send_action_frame_patterns_cmd_tlv;
2240 	ops->send_wow_delete_pattern_cmd = send_wow_delete_pattern_cmd_tlv;
2241 	ops->send_host_wakeup_ind_to_fw_cmd =
2242 		send_host_wakeup_ind_to_fw_cmd_tlv;
2243 	ops->send_wow_timer_pattern_cmd = send_wow_timer_pattern_cmd_tlv;
2244 
2245 	wmi_d0wow_attach_tlv(wmi_handle);
2246 	wmi_ra_filtering_attach_tlv(wmi_handle);
2247 	wmi_lphb_attach_tlv(wmi_handle);
2248 	wmi_packet_filtering_attach_tlv(wmi_handle);
2249 	wmi_extwow_attach_tlv(wmi_handle);
2250 	wmi_icmp_offload_config_tlv(wmi_handle);
2251 }
2252