xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_pmo_tlv.c (revision 8cfe6b10058a04cafb17eed051f2ddf11bee8931)
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 	for (i = 0; i < filter_param->multicast_addr_cnt; i++) {
675 		WMI_CHAR_ARRAY_TO_MAC_ADDR(mac_addr_src_ptr, mac_addr_dst_ptr);
676 		mac_addr_src_ptr += ATH_MAC_LEN;
677 		mac_addr_dst_ptr++;
678 	}
679 
680 send_cmd:
681 	wmi_mtrace(WMI_SET_MULTIPLE_MCAST_FILTER_CMDID, cmd->vdev_id, 0);
682 	err = wmi_unified_cmd_send(wmi_handle, buf,
683 				   len,
684 				   WMI_SET_MULTIPLE_MCAST_FILTER_CMDID);
685 	if (err) {
686 		wmi_err("Failed to send set_param cmd");
687 		wmi_buf_free(buf);
688 		return QDF_STATUS_E_FAILURE;
689 	}
690 
691 	return QDF_STATUS_SUCCESS;
692 }
693 
694 static QDF_STATUS send_conf_hw_filter_cmd_tlv(wmi_unified_t wmi,
695 					      struct pmo_hw_filter_params *req)
696 {
697 	QDF_STATUS status;
698 	wmi_hw_data_filter_cmd_fixed_param *cmd;
699 	wmi_buf_t wmi_buf;
700 
701 	if (!req) {
702 		wmi_err("req is null");
703 		return QDF_STATUS_E_INVAL;
704 	}
705 
706 	wmi_buf = wmi_buf_alloc(wmi, sizeof(*cmd));
707 	if (!wmi_buf) {
708 		return QDF_STATUS_E_NOMEM;
709 	}
710 
711 	cmd = (wmi_hw_data_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
712 	WMITLV_SET_HDR(&cmd->tlv_header,
713 		  WMITLV_TAG_STRUC_wmi_hw_data_filter_cmd_fixed_param,
714 		  WMITLV_GET_STRUCT_TLVLEN(wmi_hw_data_filter_cmd_fixed_param));
715 	cmd->vdev_id = req->vdev_id;
716 	cmd->enable = req->enable;
717 	/* Set all modes in case of disable */
718 	if (!cmd->enable)
719 		cmd->hw_filter_bitmap = ((uint32_t)~0U);
720 	else
721 		cmd->hw_filter_bitmap = req->mode_bitmap;
722 
723 	wmi_debug("Send %s hw filter mode: 0x%X for vdev id %d",
724 		 req->enable ? "enable" : "disable", req->mode_bitmap,
725 		 req->vdev_id);
726 
727 	wmi_mtrace(WMI_HW_DATA_FILTER_CMDID, cmd->vdev_id, 0);
728 	status = wmi_unified_cmd_send(wmi, wmi_buf, sizeof(*cmd),
729 				      WMI_HW_DATA_FILTER_CMDID);
730 	if (QDF_IS_STATUS_ERROR(status)) {
731 		wmi_err("Failed to configure hw filter");
732 		wmi_buf_free(wmi_buf);
733 	}
734 
735 	return status;
736 }
737 
738 static void
739 fill_fils_tlv_params(WMI_GTK_OFFLOAD_CMD_fixed_param *cmd,
740 			  uint8_t vdev_id,
741 			  struct pmo_gtk_req *params)
742 {
743 	uint8_t *buf_ptr;
744 	wmi_gtk_offload_fils_tlv_param *ext_param;
745 
746 	buf_ptr = (uint8_t *) cmd + sizeof(*cmd);
747 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
748 		       sizeof(*ext_param));
749 	buf_ptr += WMI_TLV_HDR_SIZE;
750 
751 	ext_param = (wmi_gtk_offload_fils_tlv_param *)buf_ptr;
752 	WMITLV_SET_HDR(&ext_param->tlv_header,
753 		       WMITLV_TAG_STRUC_wmi_gtk_offload_extended_tlv_param,
754 		       WMITLV_GET_STRUCT_TLVLEN(
755 				wmi_gtk_offload_fils_tlv_param));
756 	ext_param->vdev_id = vdev_id;
757 	ext_param->flags = cmd->flags;
758 	ext_param->kek_len = params->kek_len;
759 	qdf_mem_copy(ext_param->KEK, params->kek, params->kek_len);
760 	qdf_mem_copy(ext_param->KCK, params->kck,
761 		     WMI_GTK_OFFLOAD_KCK_BYTES);
762 	qdf_mem_copy(ext_param->replay_counter, &params->replay_counter,
763 		     GTK_REPLAY_COUNTER_BYTES);
764 }
765 
766 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
767 /**
768  * send_igmp_offload_cmd_tlv() - send IGMP offload command to fw
769  * @wmi_handle: wmi handle
770  * @pmo_igmp_req: IGMP offload parameters
771  *
772  * Return: QDF status
773  */
774 static
775 QDF_STATUS send_igmp_offload_cmd_tlv(wmi_unified_t wmi_handle,
776 				     struct pmo_igmp_offload_req *pmo_igmp_req)
777 {
778 	wmi_buf_t buf;
779 	uint8_t *buf_ptr;
780 	int len;
781 	int i = 0;
782 	WMI_IPV4_ADDR *ipv4_list;
783 	wmi_igmp_offload_fixed_param *cmd;
784 	QDF_STATUS status = QDF_STATUS_SUCCESS;
785 
786 	len = sizeof(wmi_igmp_offload_fixed_param) + WMI_TLV_HDR_SIZE +
787 	     (pmo_igmp_req->num_grp_ip_address) * sizeof(WMI_IPV4_ADDR);
788 	/* alloc wmi buffer */
789 	buf = wmi_buf_alloc(wmi_handle, len);
790 	if (!buf) {
791 		status = QDF_STATUS_E_NOMEM;
792 		goto out;
793 	}
794 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
795 	cmd = (wmi_igmp_offload_fixed_param *)wmi_buf_data(buf);
796 
797 	WMITLV_SET_HDR(&cmd->tlv_header,
798 		       WMITLV_TAG_STRUC_wmi_igmp_offload_fixed_param,
799 		       WMITLV_GET_STRUCT_TLVLEN(wmi_igmp_offload_fixed_param));
800 
801 	cmd->vdev_id = pmo_igmp_req->vdev_id;
802 	cmd->enable = pmo_igmp_req->enable;
803 	cmd->version_support_bitmask =
804 				pmo_igmp_req->version_support;
805 
806 	buf_ptr += sizeof(*cmd);
807 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
808 		       sizeof(WMI_IPV4_ADDR) *
809 		       pmo_igmp_req->num_grp_ip_address);
810 
811 	ipv4_list = (WMI_IPV4_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE);
812 
813 	while (i < pmo_igmp_req->num_grp_ip_address) {
814 		qdf_mem_copy((void *)((*(ipv4_list + i)).address),
815 			     (void *)&(pmo_igmp_req->grp_ip_address[i]),
816 			     WMI_IPV4_ADDR_LEN);
817 		wmi_debug("piv4[%d]:%x", i, *(uint32_t *)(ipv4_list + i));
818 		i++;
819 	}
820 
821 	wmi_debug("VDEVID:%d, FLAG:x%x version support:%d",
822 		  cmd->vdev_id, cmd->enable,
823 		  cmd->version_support_bitmask);
824 
825 	/* send the wmi command */
826 	wmi_mtrace(WMI_VDEV_IGMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
827 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
828 				 WMI_VDEV_IGMP_OFFLOAD_CMDID)) {
829 		wmi_err("Failed to send WMI_VDEV_IGMP_OFFLOAD_CMDID");
830 		wmi_buf_free(buf);
831 		status = QDF_STATUS_E_FAILURE;
832 	}
833 out:
834 	return status;
835 }
836 #endif
837 
838 /**
839  * send_gtk_offload_cmd_tlv() - send GTK offload command to fw
840  * @wmi_handle: wmi handle
841  * @vdev_id: vdev id
842  * @params: GTK offload parameters
843  * @enable_offload: true to enable the offload
844  * @gtk_offload_opcode: GTK offload opcode
845  *
846  * Return: QDF status
847  */
848 static
849 QDF_STATUS send_gtk_offload_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_id,
850 				    struct pmo_gtk_req *params,
851 				    bool enable_offload,
852 				    uint32_t gtk_offload_opcode)
853 {
854 	int len;
855 	uint8_t *buf_ptr;
856 	wmi_buf_t buf;
857 	WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
858 	QDF_STATUS status = QDF_STATUS_SUCCESS;
859 
860 	len = sizeof(*cmd);
861 
862 	len += WMI_TLV_HDR_SIZE;
863 	if (params->is_fils_connection)
864 		len += sizeof(wmi_gtk_offload_fils_tlv_param);
865 
866 	if (params->kck_len > 16)
867 		len += WMI_TLV_HDR_SIZE +
868 		       roundup(params->kek_len, sizeof(uint32_t)) +
869 		       WMI_TLV_HDR_SIZE +
870 		       roundup(params->kck_len, sizeof(uint32_t));
871 
872 	/* alloc wmi buffer */
873 	buf = wmi_buf_alloc(wmi_handle, len);
874 	if (!buf) {
875 		status = QDF_STATUS_E_NOMEM;
876 		goto out;
877 	}
878 
879 	cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
880 	WMITLV_SET_HDR(&cmd->tlv_header,
881 		       WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
882 		       WMITLV_GET_STRUCT_TLVLEN
883 			       (WMI_GTK_OFFLOAD_CMD_fixed_param));
884 
885 	buf_ptr = wmi_buf_data(buf);
886 	cmd->vdev_id = vdev_id;
887 
888 	/* Request target to enable GTK offload */
889 	if (enable_offload == PMO_GTK_OFFLOAD_ENABLE) {
890 		cmd->flags = gtk_offload_opcode;
891 
892 		/* Copy the keys and replay counter */
893 		qdf_mem_copy(cmd->KCK, params->kck, sizeof(cmd->KCK));
894 		qdf_mem_copy(cmd->KEK, params->kek, sizeof(cmd->KEK));
895 		qdf_mem_copy(cmd->replay_counter, &params->replay_counter,
896 			     GTK_REPLAY_COUNTER_BYTES);
897 	} else {
898 		cmd->flags = gtk_offload_opcode;
899 	}
900 
901 	buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
902 
903 	if (params->is_fils_connection) {
904 		fill_fils_tlv_params(cmd, vdev_id, params);
905 		buf_ptr += sizeof(wmi_gtk_offload_fils_tlv_param);
906 	} else {
907 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
908 		buf_ptr += WMI_TLV_HDR_SIZE;
909 	}
910 
911 	if (params->kck_len > 16) {
912 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
913 			       roundup(params->kek_len, sizeof(uint32_t)));
914 		buf_ptr += WMI_TLV_HDR_SIZE;
915 
916 		qdf_mem_copy(buf_ptr, params->kek, params->kek_len);
917 		buf_ptr += roundup(params->kek_len, sizeof(uint32_t));
918 
919 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
920 			       roundup(params->kck_len, sizeof(uint32_t)));
921 		buf_ptr += WMI_TLV_HDR_SIZE;
922 
923 		qdf_mem_copy(buf_ptr, params->kck, params->kck_len);
924 		buf_ptr += roundup(params->kck_len, sizeof(uint32_t));
925 	}
926 
927 	wmi_debug("VDEVID: %d, GTK_FLAGS: x%x kek len %d",
928 		 vdev_id, cmd->flags, params->kek_len);
929 	/* send the wmi command */
930 	wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0);
931 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
932 				 WMI_GTK_OFFLOAD_CMDID)) {
933 		wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID");
934 		wmi_buf_free(buf);
935 		status = QDF_STATUS_E_FAILURE;
936 	}
937 
938 out:
939 	return status;
940 }
941 
942 /**
943  * send_process_gtk_offload_getinfo_cmd_tlv() - send GTK offload cmd to fw
944  * @wmi_handle: wmi handle
945  * @vdev_id: vdev id
946  * @offload_req_opcode: GTK offload request opcode
947  *
948  * Return: QDF status
949  */
950 static QDF_STATUS send_process_gtk_offload_getinfo_cmd_tlv(
951 			wmi_unified_t wmi_handle,
952 			uint8_t vdev_id,
953 			uint64_t offload_req_opcode)
954 {
955 	int len;
956 	wmi_buf_t buf;
957 	WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
958 	QDF_STATUS status = QDF_STATUS_SUCCESS;
959 
960 	len = sizeof(*cmd);
961 
962 	/* alloc wmi buffer */
963 	buf = wmi_buf_alloc(wmi_handle, len);
964 	if (!buf) {
965 		status = QDF_STATUS_E_NOMEM;
966 		goto out;
967 	}
968 
969 	cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
970 	WMITLV_SET_HDR(&cmd->tlv_header,
971 		       WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
972 		       WMITLV_GET_STRUCT_TLVLEN
973 			       (WMI_GTK_OFFLOAD_CMD_fixed_param));
974 
975 	/* Request for GTK offload status */
976 	cmd->flags = offload_req_opcode;
977 	cmd->vdev_id = vdev_id;
978 
979 	/* send the wmi command */
980 	wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0);
981 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
982 				 WMI_GTK_OFFLOAD_CMDID)) {
983 		wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID for req info");
984 		wmi_buf_free(buf);
985 		status = QDF_STATUS_E_FAILURE;
986 	}
987 
988 out:
989 	return status;
990 }
991 
992 /**
993  * send_enable_enhance_multicast_offload_tlv() - send enhance multicast offload
994  * @wmi_handle: wmi handle
995  * @vdev_id: vdev id
996  * @action: true for enable else false
997  *
998  * To enable enhance multicast offload to firmware
999  * when target goes to wow mode.
1000  *
1001  * Return: QDF Status
1002  */
1003 
1004 static
1005 QDF_STATUS send_enable_enhance_multicast_offload_tlv(
1006 		wmi_unified_t wmi_handle,
1007 		uint8_t vdev_id, bool action)
1008 {
1009 	QDF_STATUS status;
1010 	wmi_buf_t buf;
1011 	wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
1012 
1013 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
1014 	if (!buf) {
1015 		return QDF_STATUS_E_NOMEM;
1016 	}
1017 
1018 	cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
1019 							wmi_buf_data(buf);
1020 
1021 	WMITLV_SET_HDR(&cmd->tlv_header,
1022 		WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
1023 		WMITLV_GET_STRUCT_TLVLEN(
1024 			wmi_config_enhanced_mcast_filter_cmd_fixed_param));
1025 
1026 	cmd->vdev_id = vdev_id;
1027 	cmd->enable = ((action == 0) ? ENHANCED_MCAST_FILTER_DISABLED :
1028 			ENHANCED_MCAST_FILTER_ENABLED);
1029 	wmi_debug("config enhance multicast offload action %d for vdev %d",
1030 		 action, vdev_id);
1031 	wmi_mtrace(WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID, cmd->vdev_id, 0);
1032 	status = wmi_unified_cmd_send(wmi_handle, buf,
1033 			sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
1034 	if (status != QDF_STATUS_SUCCESS) {
1035 		wmi_buf_free(buf);
1036 		wmi_err("Failed to send ENHANCED_MCAST_FILTER_CMDID");
1037 	}
1038 
1039 	return status;
1040 }
1041 
1042 /**
1043  * extract_gtk_rsp_event_tlv() - extract gtk rsp params from event
1044  * @wmi_handle: wmi handle
1045  * @evt_buf: pointer to event buffer
1046  * @gtk_rsp_param: Pointer to extraction buffer
1047  * @len: length of the @evt_buf event buffer
1048  *
1049  * Return: QDF_STATUS_SUCCESS for success or error code
1050  */
1051 static QDF_STATUS extract_gtk_rsp_event_tlv(wmi_unified_t wmi_handle,
1052 	void *evt_buf, struct pmo_gtk_rsp_params *gtk_rsp_param, uint32_t len)
1053 {
1054 	WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *fixed_param;
1055 	WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
1056 
1057 	param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *)evt_buf;
1058 	if (!param_buf) {
1059 		wmi_err("gtk param_buf is NULL");
1060 		return QDF_STATUS_E_INVAL;
1061 	}
1062 
1063 	if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
1064 		wmi_err("Invalid length for GTK status");
1065 		return QDF_STATUS_E_INVAL;
1066 	}
1067 
1068 	fixed_param = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *)
1069 		param_buf->fixed_param;
1070 
1071 	if (fixed_param->vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) {
1072 		wmi_err_rl("Invalid vdev_id %u", fixed_param->vdev_id);
1073 		return QDF_STATUS_E_INVAL;
1074 	}
1075 
1076 	gtk_rsp_param->vdev_id = fixed_param->vdev_id;
1077 	gtk_rsp_param->status_flag = QDF_STATUS_SUCCESS;
1078 	gtk_rsp_param->refresh_cnt = fixed_param->refresh_cnt;
1079 	qdf_mem_copy(&gtk_rsp_param->replay_counter,
1080 		&fixed_param->replay_counter,
1081 		GTK_REPLAY_COUNTER_BYTES);
1082 
1083 	return QDF_STATUS_SUCCESS;
1084 
1085 }
1086 
1087 #ifdef FEATURE_WLAN_RA_FILTERING
1088 /**
1089  * send_wow_sta_ra_filter_cmd_tlv() - set RA filter pattern in fw
1090  * @wmi_handle: wmi handle
1091  * @vdev_id: vdev id
1092  * @default_pattern: default pattern
1093  * @rate_limit_interval: ra packets interval
1094  *
1095  * Return: QDF status
1096  */
1097 static QDF_STATUS send_wow_sta_ra_filter_cmd_tlv(wmi_unified_t wmi_handle,
1098 						 uint8_t vdev_id,
1099 						 uint8_t default_pattern,
1100 						 uint16_t rate_limit_interval)
1101 {
1102 
1103 	WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
1104 	wmi_buf_t buf;
1105 	uint8_t *buf_ptr;
1106 	int32_t len;
1107 	int ret;
1108 
1109 	len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
1110 	      WMI_TLV_HDR_SIZE +
1111 	      0 * sizeof(WOW_BITMAP_PATTERN_T) +
1112 	      WMI_TLV_HDR_SIZE +
1113 	      0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
1114 	      WMI_TLV_HDR_SIZE +
1115 	      0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
1116 	      WMI_TLV_HDR_SIZE +
1117 	      0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
1118 	      WMI_TLV_HDR_SIZE +
1119 	      0 * sizeof(uint32_t) + WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
1120 
1121 	buf = wmi_buf_alloc(wmi_handle, len);
1122 	if (!buf) {
1123 		return QDF_STATUS_E_NOMEM;
1124 	}
1125 
1126 	cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1127 	buf_ptr = (uint8_t *) cmd;
1128 
1129 	WMITLV_SET_HDR(&cmd->tlv_header,
1130 		       WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
1131 		       WMITLV_GET_STRUCT_TLVLEN
1132 			       (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
1133 	cmd->vdev_id = vdev_id;
1134 	cmd->pattern_id = default_pattern,
1135 	cmd->pattern_type = WOW_IPV6_RA_PATTERN;
1136 	buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
1137 
1138 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
1139 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1140 	buf_ptr += WMI_TLV_HDR_SIZE;
1141 
1142 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_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_IPV6_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_MAGIC_PATTERN_CMD 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 pattern_info_timeout but no data. */
1155 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
1156 	buf_ptr += WMI_TLV_HDR_SIZE;
1157 
1158 	/* Fill TLV for ra_ratelimit_interval. */
1159 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
1160 	buf_ptr += WMI_TLV_HDR_SIZE;
1161 
1162 	*((uint32_t *) buf_ptr) = rate_limit_interval;
1163 
1164 	wmi_debug("send RA rate limit [%d] to fw vdev = %d",
1165 		 rate_limit_interval, vdev_id);
1166 
1167 	wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
1168 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1169 				   WMI_WOW_ADD_WAKE_PATTERN_CMDID);
1170 	if (ret) {
1171 		wmi_err("Failed to send RA rate limit to fw");
1172 		wmi_buf_free(buf);
1173 		return QDF_STATUS_E_FAILURE;
1174 	}
1175 
1176 	return QDF_STATUS_SUCCESS;
1177 }
1178 
1179 void wmi_ra_filtering_attach_tlv(struct wmi_unified *wmi_handle)
1180 {
1181 	struct wmi_ops *ops = wmi_handle->ops;
1182 
1183 	ops->send_wow_sta_ra_filter_cmd = send_wow_sta_ra_filter_cmd_tlv;
1184 }
1185 #endif /* FEATURE_WLAN_RA_FILTERING */
1186 
1187 /**
1188  * send_action_frame_patterns_cmd_tlv() - send wmi cmd of action filter params
1189  * @wmi_handle: wmi handler
1190  * @action_params: pointer to action_params
1191  *
1192  * Return: 0 for success, otherwise appropriate error code
1193  */
1194 static QDF_STATUS send_action_frame_patterns_cmd_tlv(wmi_unified_t wmi_handle,
1195 		struct pmo_action_wakeup_set_params *action_params)
1196 {
1197 	WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *cmd;
1198 	wmi_buf_t buf;
1199 	int i;
1200 	int32_t err;
1201 	uint32_t len = 0, *cmd_args;
1202 	uint8_t *buf_ptr;
1203 
1204 	len = (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t))
1205 				+ WMI_TLV_HDR_SIZE + sizeof(*cmd);
1206 	buf = wmi_buf_alloc(wmi_handle, len);
1207 	if (!buf) {
1208 		return QDF_STATUS_E_NOMEM;
1209 	}
1210 	cmd = (WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *) wmi_buf_data(buf);
1211 	buf_ptr = (uint8_t *)cmd;
1212 	WMITLV_SET_HDR(&cmd->tlv_header,
1213 		WMITLV_TAG_STRUC_wmi_wow_set_action_wake_up_cmd_fixed_param,
1214 		WMITLV_GET_STRUCT_TLVLEN(
1215 				WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param));
1216 
1217 	cmd->vdev_id = action_params->vdev_id;
1218 	cmd->operation = action_params->operation;
1219 
1220 	for (i = 0; i < MAX_SUPPORTED_ACTION_CATEGORY_ELE_LIST; i++)
1221 		cmd->action_category_map[i] =
1222 				action_params->action_category_map[i];
1223 
1224 	buf_ptr += sizeof(WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param);
1225 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1226 		       (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t)));
1227 	buf_ptr += WMI_TLV_HDR_SIZE;
1228 	cmd_args = (uint32_t *) buf_ptr;
1229 	for (i = 0; i < PMO_SUPPORTED_ACTION_CATE; i++)
1230 		cmd_args[i] = action_params->action_per_category[i];
1231 
1232 	wmi_mtrace(WMI_WOW_SET_ACTION_WAKE_UP_CMDID, cmd->vdev_id, 0);
1233 	err = wmi_unified_cmd_send(wmi_handle, buf,
1234 				   len, WMI_WOW_SET_ACTION_WAKE_UP_CMDID);
1235 	if (err) {
1236 		wmi_err("Failed to send ap_ps_egap cmd");
1237 		wmi_buf_free(buf);
1238 		return QDF_STATUS_E_FAILURE;
1239 	}
1240 
1241 	return QDF_STATUS_SUCCESS;
1242 }
1243 
1244 #ifdef FEATURE_WLAN_LPHB
1245 /**
1246  * send_lphb_config_hbenable_cmd_tlv() - enable command of LPHB configuration
1247  * @wmi_handle: wmi handle
1248  * @params: LPHB configuration info
1249  *
1250  * Return: QDF status
1251  */
1252 static QDF_STATUS send_lphb_config_hbenable_cmd_tlv(wmi_unified_t wmi_handle,
1253 				wmi_hb_set_enable_cmd_fixed_param *params)
1254 {
1255 	QDF_STATUS status;
1256 	wmi_buf_t buf = NULL;
1257 	uint8_t *buf_ptr;
1258 	wmi_hb_set_enable_cmd_fixed_param *hb_enable_fp;
1259 	int len = sizeof(wmi_hb_set_enable_cmd_fixed_param);
1260 
1261 	buf = wmi_buf_alloc(wmi_handle, len);
1262 	if (!buf) {
1263 		return QDF_STATUS_E_NOMEM;
1264 	}
1265 
1266 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1267 	hb_enable_fp = (wmi_hb_set_enable_cmd_fixed_param *) buf_ptr;
1268 	WMITLV_SET_HDR(&hb_enable_fp->tlv_header,
1269 		       WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param,
1270 		       WMITLV_GET_STRUCT_TLVLEN
1271 			       (wmi_hb_set_enable_cmd_fixed_param));
1272 
1273 	/* fill in values */
1274 	hb_enable_fp->vdev_id = params->session;
1275 	hb_enable_fp->enable = params->enable;
1276 	hb_enable_fp->item = params->item;
1277 	hb_enable_fp->session = params->session;
1278 
1279 	wmi_mtrace(WMI_HB_SET_ENABLE_CMDID, NO_SESSION, 0);
1280 	status = wmi_unified_cmd_send(wmi_handle, buf,
1281 				      len, WMI_HB_SET_ENABLE_CMDID);
1282 	if (QDF_IS_STATUS_ERROR(status)) {
1283 		wmi_err("cmd_send WMI_HB_SET_ENABLE returned Error %d",
1284 			 status);
1285 		wmi_buf_free(buf);
1286 	}
1287 
1288 	return status;
1289 }
1290 
1291 /**
1292  * send_lphb_config_tcp_params_cmd_tlv() - set tcp params of LPHB configuration
1293  * @wmi_handle: wmi handle
1294  * @lphb_conf_req: lphb config request
1295  *
1296  * Return: QDF status
1297  */
1298 static QDF_STATUS send_lphb_config_tcp_params_cmd_tlv(wmi_unified_t wmi_handle,
1299 	    wmi_hb_set_tcp_params_cmd_fixed_param *lphb_conf_req)
1300 {
1301 	QDF_STATUS status;
1302 	wmi_buf_t buf = NULL;
1303 	uint8_t *buf_ptr;
1304 	wmi_hb_set_tcp_params_cmd_fixed_param *hb_tcp_params_fp;
1305 	int len = sizeof(wmi_hb_set_tcp_params_cmd_fixed_param);
1306 
1307 	buf = wmi_buf_alloc(wmi_handle, len);
1308 	if (!buf) {
1309 		return QDF_STATUS_E_NOMEM;
1310 	}
1311 
1312 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1313 	hb_tcp_params_fp = (wmi_hb_set_tcp_params_cmd_fixed_param *) buf_ptr;
1314 	WMITLV_SET_HDR(&hb_tcp_params_fp->tlv_header,
1315 		       WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param,
1316 		       WMITLV_GET_STRUCT_TLVLEN
1317 			       (wmi_hb_set_tcp_params_cmd_fixed_param));
1318 
1319 	/* fill in values */
1320 	hb_tcp_params_fp->vdev_id = lphb_conf_req->vdev_id;
1321 	hb_tcp_params_fp->srv_ip = lphb_conf_req->srv_ip;
1322 	hb_tcp_params_fp->dev_ip = lphb_conf_req->dev_ip;
1323 	hb_tcp_params_fp->seq = lphb_conf_req->seq;
1324 	hb_tcp_params_fp->src_port = lphb_conf_req->src_port;
1325 	hb_tcp_params_fp->dst_port = lphb_conf_req->dst_port;
1326 	hb_tcp_params_fp->interval = lphb_conf_req->interval;
1327 	hb_tcp_params_fp->timeout = lphb_conf_req->timeout;
1328 	hb_tcp_params_fp->session = lphb_conf_req->session;
1329 	qdf_mem_copy(&hb_tcp_params_fp->gateway_mac,
1330 		     &lphb_conf_req->gateway_mac,
1331 		     sizeof(hb_tcp_params_fp->gateway_mac));
1332 
1333 	wmi_mtrace(WMI_HB_SET_TCP_PARAMS_CMDID, NO_SESSION, 0);
1334 	status = wmi_unified_cmd_send(wmi_handle, buf,
1335 				      len, WMI_HB_SET_TCP_PARAMS_CMDID);
1336 	if (QDF_IS_STATUS_ERROR(status)) {
1337 		wmi_err("cmd_send WMI_HB_SET_TCP_PARAMS returned Error %d",
1338 			 status);
1339 		wmi_buf_free(buf);
1340 	}
1341 
1342 	return status;
1343 }
1344 
1345 /**
1346  * send_lphb_config_tcp_pkt_filter_cmd_tlv() - configure tcp packet filter cmd
1347  * @wmi_handle: wmi handle
1348  * @g_hb_tcp_filter_fp: tcp packet filter params
1349  *
1350  * Return: QDF status
1351  */
1352 static
1353 QDF_STATUS send_lphb_config_tcp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,
1354 		wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *g_hb_tcp_filter_fp)
1355 {
1356 	QDF_STATUS status;
1357 	wmi_buf_t buf = NULL;
1358 	uint8_t *buf_ptr;
1359 	wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *hb_tcp_filter_fp;
1360 	int len = sizeof(wmi_hb_set_tcp_pkt_filter_cmd_fixed_param);
1361 
1362 	buf = wmi_buf_alloc(wmi_handle, len);
1363 	if (!buf) {
1364 		return QDF_STATUS_E_NOMEM;
1365 	}
1366 
1367 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1368 	hb_tcp_filter_fp =
1369 		(wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *) buf_ptr;
1370 	WMITLV_SET_HDR(&hb_tcp_filter_fp->tlv_header,
1371 		WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param,
1372 		WMITLV_GET_STRUCT_TLVLEN
1373 		       (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param));
1374 
1375 	/* fill in values */
1376 	hb_tcp_filter_fp->vdev_id = g_hb_tcp_filter_fp->vdev_id;
1377 	hb_tcp_filter_fp->length = g_hb_tcp_filter_fp->length;
1378 	hb_tcp_filter_fp->offset = g_hb_tcp_filter_fp->offset;
1379 	hb_tcp_filter_fp->session = g_hb_tcp_filter_fp->session;
1380 	memcpy((void *)&hb_tcp_filter_fp->filter,
1381 	       (void *)&g_hb_tcp_filter_fp->filter,
1382 	       WMI_WLAN_HB_MAX_FILTER_SIZE);
1383 
1384 	wmi_mtrace(WMI_HB_SET_TCP_PKT_FILTER_CMDID, NO_SESSION, 0);
1385 	status = wmi_unified_cmd_send(wmi_handle, buf,
1386 				      len, WMI_HB_SET_TCP_PKT_FILTER_CMDID);
1387 	if (QDF_IS_STATUS_ERROR(status)) {
1388 		wmi_err("cmd_send WMI_HB_SET_TCP_PKT_FILTER returned Error %d",
1389 			 status);
1390 		wmi_buf_free(buf);
1391 	}
1392 
1393 	return status;
1394 }
1395 
1396 /**
1397  * send_lphb_config_udp_params_cmd_tlv() - configure udp param command of LPHB
1398  * @wmi_handle: wmi handle
1399  * @lphb_conf_req: lphb config request
1400  *
1401  * Return: QDF status
1402  */
1403 static QDF_STATUS send_lphb_config_udp_params_cmd_tlv(wmi_unified_t wmi_handle,
1404 		   wmi_hb_set_udp_params_cmd_fixed_param *lphb_conf_req)
1405 {
1406 	QDF_STATUS status;
1407 	wmi_buf_t buf = NULL;
1408 	uint8_t *buf_ptr;
1409 	wmi_hb_set_udp_params_cmd_fixed_param *hb_udp_params_fp;
1410 	int len = sizeof(wmi_hb_set_udp_params_cmd_fixed_param);
1411 
1412 	buf = wmi_buf_alloc(wmi_handle, len);
1413 	if (!buf) {
1414 		return QDF_STATUS_E_NOMEM;
1415 	}
1416 
1417 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1418 	hb_udp_params_fp = (wmi_hb_set_udp_params_cmd_fixed_param *) buf_ptr;
1419 	WMITLV_SET_HDR(&hb_udp_params_fp->tlv_header,
1420 		       WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param,
1421 		       WMITLV_GET_STRUCT_TLVLEN
1422 			       (wmi_hb_set_udp_params_cmd_fixed_param));
1423 
1424 	/* fill in values */
1425 	hb_udp_params_fp->vdev_id = lphb_conf_req->vdev_id;
1426 	hb_udp_params_fp->srv_ip = lphb_conf_req->srv_ip;
1427 	hb_udp_params_fp->dev_ip = lphb_conf_req->dev_ip;
1428 	hb_udp_params_fp->src_port = lphb_conf_req->src_port;
1429 	hb_udp_params_fp->dst_port = lphb_conf_req->dst_port;
1430 	hb_udp_params_fp->interval = lphb_conf_req->interval;
1431 	hb_udp_params_fp->timeout = lphb_conf_req->timeout;
1432 	hb_udp_params_fp->session = lphb_conf_req->session;
1433 	qdf_mem_copy(&hb_udp_params_fp->gateway_mac,
1434 		     &lphb_conf_req->gateway_mac,
1435 		     sizeof(lphb_conf_req->gateway_mac));
1436 
1437 	wmi_mtrace(WMI_HB_SET_UDP_PARAMS_CMDID, NO_SESSION, 0);
1438 	status = wmi_unified_cmd_send(wmi_handle, buf,
1439 				      len, WMI_HB_SET_UDP_PARAMS_CMDID);
1440 	if (QDF_IS_STATUS_ERROR(status)) {
1441 		wmi_err("cmd_send WMI_HB_SET_UDP_PARAMS returned Error %d",
1442 			 status);
1443 		wmi_buf_free(buf);
1444 	}
1445 
1446 	return status;
1447 }
1448 
1449 /**
1450  * send_lphb_config_udp_pkt_filter_cmd_tlv() - configure udp pkt filter command
1451  * @wmi_handle: wmi handle
1452  * @lphb_conf_req: lphb config request
1453  *
1454  * Return: QDF status
1455  */
1456 static
1457 QDF_STATUS send_lphb_config_udp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,
1458 		wmi_hb_set_udp_pkt_filter_cmd_fixed_param *lphb_conf_req)
1459 {
1460 	QDF_STATUS status;
1461 	wmi_buf_t buf = NULL;
1462 	uint8_t *buf_ptr;
1463 	wmi_hb_set_udp_pkt_filter_cmd_fixed_param *hb_udp_filter_fp;
1464 	int len = sizeof(wmi_hb_set_udp_pkt_filter_cmd_fixed_param);
1465 
1466 	buf = wmi_buf_alloc(wmi_handle, len);
1467 	if (!buf) {
1468 		return QDF_STATUS_E_NOMEM;
1469 	}
1470 
1471 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
1472 	hb_udp_filter_fp =
1473 		(wmi_hb_set_udp_pkt_filter_cmd_fixed_param *) buf_ptr;
1474 	WMITLV_SET_HDR(&hb_udp_filter_fp->tlv_header,
1475 		WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param,
1476 		WMITLV_GET_STRUCT_TLVLEN
1477 		       (wmi_hb_set_udp_pkt_filter_cmd_fixed_param));
1478 
1479 	/* fill in values */
1480 	hb_udp_filter_fp->vdev_id = lphb_conf_req->vdev_id;
1481 	hb_udp_filter_fp->length = lphb_conf_req->length;
1482 	hb_udp_filter_fp->offset = lphb_conf_req->offset;
1483 	hb_udp_filter_fp->session = lphb_conf_req->session;
1484 	memcpy((void *)&hb_udp_filter_fp->filter,
1485 	       (void *)&lphb_conf_req->filter,
1486 	       WMI_WLAN_HB_MAX_FILTER_SIZE);
1487 
1488 	wmi_mtrace(WMI_HB_SET_UDP_PKT_FILTER_CMDID, NO_SESSION, 0);
1489 	status = wmi_unified_cmd_send(wmi_handle, buf,
1490 				      len, WMI_HB_SET_UDP_PKT_FILTER_CMDID);
1491 	if (QDF_IS_STATUS_ERROR(status)) {
1492 		wmi_err("cmd_send WMI_HB_SET_UDP_PKT_FILTER returned Error %d",
1493 			 status);
1494 		wmi_buf_free(buf);
1495 	}
1496 
1497 	return status;
1498 }
1499 
1500 void wmi_lphb_attach_tlv(struct wmi_unified *wmi_handle)
1501 {
1502 	struct wmi_ops *ops = wmi_handle->ops;
1503 
1504 	ops->send_lphb_config_hbenable_cmd =
1505 		send_lphb_config_hbenable_cmd_tlv;
1506 	ops->send_lphb_config_tcp_params_cmd =
1507 		send_lphb_config_tcp_params_cmd_tlv;
1508 	ops->send_lphb_config_tcp_pkt_filter_cmd =
1509 		send_lphb_config_tcp_pkt_filter_cmd_tlv;
1510 	ops->send_lphb_config_udp_params_cmd =
1511 		send_lphb_config_udp_params_cmd_tlv;
1512 	ops->send_lphb_config_udp_pkt_filter_cmd =
1513 		send_lphb_config_udp_pkt_filter_cmd_tlv;
1514 }
1515 #endif /* FEATURE_WLAN_LPHB */
1516 
1517 #ifdef WLAN_FEATURE_PACKET_FILTERING
1518 /**
1519  * send_enable_disable_packet_filter_cmd_tlv() - enable/disable packet filter
1520  * @wmi_handle: wmi handle
1521  * @vdev_id: vdev id
1522  * @enable: Flag to enable/disable packet filter
1523  *
1524  * Return: QDF_STATUS_SUCCESS for success or error code
1525  */
1526 static QDF_STATUS send_enable_disable_packet_filter_cmd_tlv(
1527 		wmi_unified_t wmi_handle, uint8_t vdev_id, bool enable)
1528 {
1529 	int32_t len;
1530 	int ret = 0;
1531 	wmi_buf_t buf;
1532 	WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *cmd;
1533 
1534 	len = sizeof(WMI_PACKET_FILTER_ENABLE_CMD_fixed_param);
1535 
1536 	buf = wmi_buf_alloc(wmi_handle, len);
1537 	if (!buf) {
1538 		return QDF_STATUS_E_NOMEM;
1539 	}
1540 
1541 	cmd = (WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *) wmi_buf_data(buf);
1542 	WMITLV_SET_HDR(&cmd->tlv_header,
1543 		WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param,
1544 		WMITLV_GET_STRUCT_TLVLEN(
1545 			WMI_PACKET_FILTER_ENABLE_CMD_fixed_param));
1546 
1547 	cmd->vdev_id = vdev_id;
1548 	if (enable)
1549 		cmd->enable = PACKET_FILTER_SET_ENABLE;
1550 	else
1551 		cmd->enable = PACKET_FILTER_SET_DISABLE;
1552 
1553 	wmi_err("Packet filter enable %d for vdev_id %d", cmd->enable, vdev_id);
1554 
1555 	wmi_mtrace(WMI_PACKET_FILTER_ENABLE_CMDID, cmd->vdev_id, 0);
1556 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1557 				   WMI_PACKET_FILTER_ENABLE_CMDID);
1558 	if (ret) {
1559 		wmi_err("Failed to send packet filter wmi cmd to fw");
1560 		wmi_buf_free(buf);
1561 	}
1562 
1563 	return ret;
1564 }
1565 
1566 /**
1567  * send_config_packet_filter_cmd_tlv() - configure packet filter in target
1568  * @wmi_handle: wmi handle
1569  * @vdev_id: vdev id
1570  * @rcv_filter_param: Packet filter parameters
1571  * @filter_id: Filter id
1572  * @enable: Flag to add/delete packet filter configuration
1573  *
1574  * Return: QDF_STATUS_SUCCESS for success or error code
1575  */
1576 static QDF_STATUS send_config_packet_filter_cmd_tlv(wmi_unified_t wmi_handle,
1577 		uint8_t vdev_id, struct pmo_rcv_pkt_fltr_cfg *rcv_filter_param,
1578 		uint8_t filter_id, bool enable)
1579 {
1580 	int len, i;
1581 	int err = 0;
1582 	wmi_buf_t buf;
1583 	WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *cmd;
1584 
1585 	/* allocate the memory */
1586 	len = sizeof(*cmd);
1587 	buf = wmi_buf_alloc(wmi_handle, len);
1588 	if (!buf) {
1589 		return QDF_STATUS_E_NOMEM;
1590 	}
1591 
1592 	cmd = (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *)wmi_buf_data(buf);
1593 	WMITLV_SET_HDR(&cmd->tlv_header,
1594 		WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param,
1595 		WMITLV_GET_STRUCT_TLVLEN
1596 			       (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param));
1597 
1598 	cmd->vdev_id = vdev_id;
1599 	cmd->filter_id = filter_id;
1600 	if (enable)
1601 		cmd->filter_action = PACKET_FILTER_SET_ACTIVE;
1602 	else
1603 		cmd->filter_action = PACKET_FILTER_SET_INACTIVE;
1604 
1605 	if (enable) {
1606 		cmd->num_params = QDF_MIN(
1607 			WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER,
1608 			rcv_filter_param->num_params);
1609 		cmd->filter_type = rcv_filter_param->filter_type;
1610 		cmd->coalesce_time = rcv_filter_param->coalesce_time;
1611 
1612 		for (i = 0; i < cmd->num_params; i++) {
1613 			cmd->paramsData[i].proto_type =
1614 				rcv_filter_param->params_data[i].protocol_layer;
1615 			cmd->paramsData[i].cmp_type =
1616 				rcv_filter_param->params_data[i].compare_flag;
1617 			cmd->paramsData[i].data_length =
1618 				rcv_filter_param->params_data[i].data_length;
1619 			cmd->paramsData[i].data_offset =
1620 				rcv_filter_param->params_data[i].data_offset;
1621 			memcpy(&cmd->paramsData[i].compareData,
1622 				rcv_filter_param->params_data[i].compare_data,
1623 				sizeof(cmd->paramsData[i].compareData));
1624 			memcpy(&cmd->paramsData[i].dataMask,
1625 				rcv_filter_param->params_data[i].data_mask,
1626 				sizeof(cmd->paramsData[i].dataMask));
1627 		}
1628 	}
1629 
1630 	wmi_err("Packet filter action %d filter with id: %d, num_params=%d",
1631 		 cmd->filter_action, cmd->filter_id, cmd->num_params);
1632 	/* send the command along with data */
1633 	wmi_mtrace(WMI_PACKET_FILTER_CONFIG_CMDID, cmd->vdev_id, 0);
1634 	err = wmi_unified_cmd_send(wmi_handle, buf, len,
1635 				   WMI_PACKET_FILTER_CONFIG_CMDID);
1636 	if (err) {
1637 		wmi_err("Failed to send pkt_filter cmd");
1638 		wmi_buf_free(buf);
1639 		return QDF_STATUS_E_FAILURE;
1640 	}
1641 
1642 	return QDF_STATUS_SUCCESS;
1643 }
1644 
1645 void wmi_packet_filtering_attach_tlv(struct wmi_unified *wmi_handle)
1646 {
1647 	struct wmi_ops *ops = wmi_handle->ops;
1648 
1649 	ops->send_enable_disable_packet_filter_cmd =
1650 		send_enable_disable_packet_filter_cmd_tlv;
1651 	ops->send_config_packet_filter_cmd =
1652 		send_config_packet_filter_cmd_tlv;
1653 }
1654 #endif /* WLAN_FEATURE_PACKET_FILTERING */
1655 
1656 /**
1657  * send_wow_delete_pattern_cmd_tlv() - delete wow pattern in target
1658  * @wmi_handle: wmi handle
1659  * @ptrn_id: pattern id
1660  * @vdev_id: vdev id
1661  *
1662  * Return: QDF status
1663  */
1664 static QDF_STATUS send_wow_delete_pattern_cmd_tlv(wmi_unified_t wmi_handle,
1665 						  uint8_t ptrn_id,
1666 						  uint8_t vdev_id)
1667 {
1668 	WMI_WOW_DEL_PATTERN_CMD_fixed_param *cmd;
1669 	wmi_buf_t buf;
1670 	int32_t len;
1671 	int ret;
1672 
1673 	len = sizeof(WMI_WOW_DEL_PATTERN_CMD_fixed_param);
1674 
1675 	buf = wmi_buf_alloc(wmi_handle, len);
1676 	if (!buf) {
1677 		return QDF_STATUS_E_NOMEM;
1678 	}
1679 
1680 	cmd = (WMI_WOW_DEL_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1681 
1682 	WMITLV_SET_HDR(&cmd->tlv_header,
1683 		       WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param,
1684 		       WMITLV_GET_STRUCT_TLVLEN(
1685 				WMI_WOW_DEL_PATTERN_CMD_fixed_param));
1686 	cmd->vdev_id = vdev_id;
1687 	cmd->pattern_id = ptrn_id;
1688 	cmd->pattern_type = WOW_BITMAP_PATTERN;
1689 
1690 	wmi_mtrace(WMI_WOW_DEL_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
1691 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1692 				   WMI_WOW_DEL_WAKE_PATTERN_CMDID);
1693 	if (ret) {
1694 		wmi_err("Failed to delete wow ptrn from fw");
1695 		wmi_buf_free(buf);
1696 		return QDF_STATUS_E_FAILURE;
1697 	}
1698 
1699 	return QDF_STATUS_SUCCESS;
1700 }
1701 
1702 #ifdef WMI_HOST_WAKEUP_OVER_QMI
1703 static inline
1704 QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle,
1705 				    wmi_buf_t buf,
1706 				    uint32_t buflen, uint32_t cmd_id)
1707 {
1708 	wmi_debug("Send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID over QMI");
1709 	return wmi_unified_cmd_send_over_qmi(wmi_handle, buf,
1710 					     buflen, cmd_id);
1711 }
1712 #else
1713 static inline
1714 QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle,
1715 				    wmi_buf_t buf,
1716 				    uint32_t buflen, uint32_t cmd_id)
1717 {
1718 	return wmi_unified_cmd_send(wmi_handle, buf,
1719 				    buflen, cmd_id);
1720 }
1721 #endif
1722 
1723 /**
1724  * send_host_wakeup_ind_to_fw_cmd_tlv() - send wakeup ind to fw
1725  * @wmi_handle: wmi handle
1726  * @tx_pending_ind: flag of TX has pending frames
1727  *
1728  * Sends host wakeup indication to FW. On receiving this indication,
1729  * FW will come out of WOW.
1730  *
1731  * Return: QDF status
1732  */
1733 static QDF_STATUS send_host_wakeup_ind_to_fw_cmd_tlv(wmi_unified_t wmi_handle,
1734 						     bool tx_pending_ind)
1735 {
1736 	wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *cmd;
1737 	wmi_buf_t buf;
1738 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1739 	int32_t len;
1740 	int ret;
1741 
1742 	len = sizeof(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param);
1743 
1744 	buf = wmi_buf_alloc(wmi_handle, len);
1745 	if (!buf) {
1746 		return QDF_STATUS_E_NOMEM;
1747 	}
1748 
1749 	cmd = (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *)
1750 	      wmi_buf_data(buf);
1751 
1752 	if (tx_pending_ind) {
1753 		wmi_debug("TX pending before WoW wake, indicate FW");
1754 		cmd->flags |= WMI_WOW_RESUME_FLAG_TX_DATA;
1755 	}
1756 
1757 	WMITLV_SET_HDR(&cmd->tlv_header,
1758 		WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param,
1759 		WMITLV_GET_STRUCT_TLVLEN
1760 			(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param));
1761 
1762 	wmi_mtrace(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, NO_SESSION, 0);
1763 	ret = wmi_unified_cmd_send_chk(wmi_handle, buf, len,
1764 				       WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
1765 	if (ret) {
1766 		wmi_err("Failed to send host wakeup indication to fw");
1767 		wmi_buf_free(buf);
1768 		return QDF_STATUS_E_FAILURE;
1769 	}
1770 
1771 	return qdf_status;
1772 }
1773 
1774 /**
1775  * send_wow_timer_pattern_cmd_tlv() - set timer pattern tlv, so that firmware
1776  * will wake up host after specified time is elapsed
1777  * @wmi_handle: wmi handle
1778  * @vdev_id: vdev id
1779  * @cookie: value to identify reason why host set up wake call.
1780  * @time: time in ms
1781  *
1782  * Return: QDF status
1783  */
1784 static QDF_STATUS send_wow_timer_pattern_cmd_tlv(wmi_unified_t wmi_handle,
1785 				uint8_t vdev_id, uint32_t cookie, uint32_t time)
1786 {
1787 	WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
1788 	wmi_buf_t buf;
1789 	uint8_t *buf_ptr;
1790 	int32_t len;
1791 	int ret;
1792 
1793 	len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
1794 		WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_BITMAP_PATTERN_T) +
1795 		WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
1796 		WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
1797 		WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
1798 		WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t) +
1799 		WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
1800 
1801 	buf = wmi_buf_alloc(wmi_handle, len);
1802 	if (!buf) {
1803 		return QDF_STATUS_E_NOMEM;
1804 	}
1805 
1806 	cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1807 	buf_ptr = (uint8_t *) cmd;
1808 
1809 	WMITLV_SET_HDR(&cmd->tlv_header,
1810 		WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
1811 		WMITLV_GET_STRUCT_TLVLEN
1812 			(WMI_WOW_ADD_PATTERN_CMD_fixed_param));
1813 	cmd->vdev_id = vdev_id;
1814 	cmd->pattern_id = cookie,
1815 	cmd->pattern_type = WOW_TIMER_PATTERN;
1816 	buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
1817 
1818 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
1819 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1820 	buf_ptr += WMI_TLV_HDR_SIZE;
1821 
1822 	/* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_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_IPV6_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_MAGIC_PATTERN_CMD 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 pattern_info_timeout, and time value */
1835 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
1836 	buf_ptr += WMI_TLV_HDR_SIZE;
1837 	*((uint32_t *) buf_ptr) = time;
1838 	buf_ptr += sizeof(uint32_t);
1839 
1840 	/* Fill TLV for ra_ratelimit_interval. with dummy 0 value */
1841 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
1842 	buf_ptr += WMI_TLV_HDR_SIZE;
1843 	*((uint32_t *) buf_ptr) = 0;
1844 
1845 	wmi_debug("send wake timer pattern with time[%d] to fw vdev = %d",
1846 		 time, vdev_id);
1847 
1848 	wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
1849 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1850 				WMI_WOW_ADD_WAKE_PATTERN_CMDID);
1851 	if (ret) {
1852 		wmi_err("Failed to send wake timer pattern to fw");
1853 		wmi_buf_free(buf);
1854 		return QDF_STATUS_E_FAILURE;
1855 	}
1856 
1857 	return QDF_STATUS_SUCCESS;
1858 }
1859 
1860 #ifdef WLAN_FEATURE_EXTWOW_SUPPORT
1861 /**
1862  * send_enable_ext_wow_cmd_tlv() - enable ext wow in fw
1863  * @wmi_handle: wmi handle
1864  * @params: ext wow params
1865  *
1866  * Return:0 for success or error code
1867  */
1868 static QDF_STATUS send_enable_ext_wow_cmd_tlv(wmi_unified_t wmi_handle,
1869 					      struct ext_wow_params *params)
1870 {
1871 	wmi_extwow_enable_cmd_fixed_param *cmd;
1872 	wmi_buf_t buf;
1873 	int32_t len;
1874 	int ret;
1875 
1876 	len = sizeof(wmi_extwow_enable_cmd_fixed_param);
1877 	buf = wmi_buf_alloc(wmi_handle, len);
1878 	if (!buf) {
1879 		return QDF_STATUS_E_NOMEM;
1880 	}
1881 
1882 	cmd = (wmi_extwow_enable_cmd_fixed_param *) wmi_buf_data(buf);
1883 
1884 	WMITLV_SET_HDR(&cmd->tlv_header,
1885 		       WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param,
1886 		       WMITLV_GET_STRUCT_TLVLEN
1887 			       (wmi_extwow_enable_cmd_fixed_param));
1888 
1889 	cmd->vdev_id = params->vdev_id;
1890 	cmd->type = params->type;
1891 	cmd->wakeup_pin_num = params->wakeup_pin_num;
1892 
1893 	wmi_debug("vdev_id %d type %d Wakeup_pin_num %x",
1894 		 cmd->vdev_id, cmd->type, cmd->wakeup_pin_num);
1895 
1896 	wmi_mtrace(WMI_EXTWOW_ENABLE_CMDID, cmd->vdev_id, 0);
1897 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1898 				   WMI_EXTWOW_ENABLE_CMDID);
1899 	if (ret) {
1900 		wmi_err("Failed to set EXTWOW Enable");
1901 		wmi_buf_free(buf);
1902 		return QDF_STATUS_E_FAILURE;
1903 	}
1904 
1905 	return QDF_STATUS_SUCCESS;
1906 
1907 }
1908 
1909 /**
1910  * send_set_app_type2_params_in_fw_cmd_tlv() - set app type2 params in fw
1911  * @wmi_handle: wmi handle
1912  * @appType2Params: app type2 params
1913  *
1914  * Return: QDF status
1915  */
1916 static QDF_STATUS send_set_app_type2_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,
1917 			  struct app_type2_params *appType2Params)
1918 {
1919 	wmi_extwow_set_app_type2_params_cmd_fixed_param *cmd;
1920 	wmi_buf_t buf;
1921 	int32_t len;
1922 	int ret;
1923 
1924 	len = sizeof(wmi_extwow_set_app_type2_params_cmd_fixed_param);
1925 	buf = wmi_buf_alloc(wmi_handle, len);
1926 	if (!buf) {
1927 		return QDF_STATUS_E_NOMEM;
1928 	}
1929 
1930 	cmd = (wmi_extwow_set_app_type2_params_cmd_fixed_param *)
1931 	      wmi_buf_data(buf);
1932 
1933 	WMITLV_SET_HDR(&cmd->tlv_header,
1934 	       WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param,
1935 	       WMITLV_GET_STRUCT_TLVLEN
1936 			(wmi_extwow_set_app_type2_params_cmd_fixed_param));
1937 
1938 	cmd->vdev_id = appType2Params->vdev_id;
1939 
1940 	qdf_mem_copy(cmd->rc4_key, appType2Params->rc4_key, 16);
1941 	cmd->rc4_key_len = appType2Params->rc4_key_len;
1942 
1943 	cmd->ip_id = appType2Params->ip_id;
1944 	cmd->ip_device_ip = appType2Params->ip_device_ip;
1945 	cmd->ip_server_ip = appType2Params->ip_server_ip;
1946 
1947 	cmd->tcp_src_port = appType2Params->tcp_src_port;
1948 	cmd->tcp_dst_port = appType2Params->tcp_dst_port;
1949 	cmd->tcp_seq = appType2Params->tcp_seq;
1950 	cmd->tcp_ack_seq = appType2Params->tcp_ack_seq;
1951 
1952 	cmd->keepalive_init = appType2Params->keepalive_init;
1953 	cmd->keepalive_min = appType2Params->keepalive_min;
1954 	cmd->keepalive_max = appType2Params->keepalive_max;
1955 	cmd->keepalive_inc = appType2Params->keepalive_inc;
1956 
1957 	WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac.bytes,
1958 				   &cmd->gateway_mac);
1959 	cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
1960 	cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
1961 
1962 	wmi_debug("vdev_id %d gateway_mac "QDF_MAC_ADDR_FMT" "
1963 		 "rc4_key %.16s rc4_key_len %u "
1964 		 "ip_id %x ip_device_ip %x ip_server_ip %x "
1965 		 "tcp_src_port %u tcp_dst_port %u tcp_seq %u "
1966 		 "tcp_ack_seq %u keepalive_init %u keepalive_min %u "
1967 		 "keepalive_max %u keepalive_inc %u "
1968 		 "tcp_tx_timeout_val %u tcp_rx_timeout_val %u",
1969 		 cmd->vdev_id,
1970 		 QDF_MAC_ADDR_REF(appType2Params->gateway_mac.bytes),
1971 		 cmd->rc4_key, cmd->rc4_key_len,
1972 		 cmd->ip_id, cmd->ip_device_ip, cmd->ip_server_ip,
1973 		 cmd->tcp_src_port, cmd->tcp_dst_port, cmd->tcp_seq,
1974 		 cmd->tcp_ack_seq, cmd->keepalive_init, cmd->keepalive_min,
1975 		 cmd->keepalive_max, cmd->keepalive_inc,
1976 		 cmd->tcp_tx_timeout_val, cmd->tcp_rx_timeout_val);
1977 
1978 	wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID, cmd->vdev_id, 0);
1979 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1980 				   WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID);
1981 	if (ret) {
1982 		wmi_err("Failed to set APP TYPE2 PARAMS");
1983 		wmi_buf_free(buf);
1984 		return QDF_STATUS_E_FAILURE;
1985 	}
1986 
1987 	return QDF_STATUS_SUCCESS;
1988 
1989 }
1990 
1991 /**
1992  * send_app_type1_params_in_fw_cmd_tlv() - set app type1 params in fw
1993  * @wmi_handle: wmi handle
1994  * @app_type1_params: app type1 params
1995  *
1996  * Return: QDF status
1997  */
1998 static QDF_STATUS send_app_type1_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,
1999 				   struct app_type1_params *app_type1_params)
2000 {
2001 	wmi_extwow_set_app_type1_params_cmd_fixed_param *cmd;
2002 	wmi_buf_t buf;
2003 	int32_t len;
2004 	int ret;
2005 
2006 	len = sizeof(wmi_extwow_set_app_type1_params_cmd_fixed_param);
2007 	buf = wmi_buf_alloc(wmi_handle, len);
2008 	if (!buf) {
2009 		return QDF_STATUS_E_NOMEM;
2010 	}
2011 
2012 	cmd = (wmi_extwow_set_app_type1_params_cmd_fixed_param *)
2013 	      wmi_buf_data(buf);
2014 
2015 	WMITLV_SET_HDR(&cmd->tlv_header,
2016 	       WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param,
2017 	       WMITLV_GET_STRUCT_TLVLEN
2018 	       (wmi_extwow_set_app_type1_params_cmd_fixed_param));
2019 
2020 	cmd->vdev_id = app_type1_params->vdev_id;
2021 	WMI_CHAR_ARRAY_TO_MAC_ADDR(app_type1_params->wakee_mac_addr.bytes,
2022 				   &cmd->wakee_mac);
2023 	qdf_mem_copy(cmd->ident, app_type1_params->identification_id, 8);
2024 	cmd->ident_len = app_type1_params->id_length;
2025 	qdf_mem_copy(cmd->passwd, app_type1_params->password, 16);
2026 	cmd->passwd_len = app_type1_params->pass_length;
2027 
2028 	wmi_debug("vdev_id %d wakee_mac_addr "QDF_MAC_ADDR_FMT" "
2029 		 "identification_id %.8s id_length %u "
2030 		 "password %.16s pass_length %u",
2031 		 cmd->vdev_id,
2032 		 QDF_MAC_ADDR_REF(app_type1_params->wakee_mac_addr.bytes),
2033 		 cmd->ident, cmd->ident_len, cmd->passwd, cmd->passwd_len);
2034 
2035 	wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID, cmd->vdev_id, 0);
2036 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
2037 				   WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID);
2038 	if (ret) {
2039 		wmi_err("Failed to set APP TYPE1 PARAMS");
2040 		wmi_buf_free(buf);
2041 		return QDF_STATUS_E_FAILURE;
2042 	}
2043 
2044 	return QDF_STATUS_SUCCESS;
2045 }
2046 
2047 void wmi_extwow_attach_tlv(struct wmi_unified *wmi_handle)
2048 {
2049 	struct wmi_ops *ops = wmi_handle->ops;
2050 
2051 	ops->send_enable_ext_wow_cmd = send_enable_ext_wow_cmd_tlv;
2052 	ops->send_set_app_type2_params_in_fw_cmd =
2053 		send_set_app_type2_params_in_fw_cmd_tlv;
2054 	ops->send_app_type1_params_in_fw_cmd =
2055 		send_app_type1_params_in_fw_cmd_tlv;
2056 }
2057 #endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
2058 
2059 #ifdef WLAN_FEATURE_ICMP_OFFLOAD
2060 /**
2061  * send_icmp_ipv4_config_cmd_tlv() - send ICMP IPV4 offload command to fw
2062  * @wmi_handle: wmi handle
2063  * @pmo_icmp_req: ICMP offload parameters
2064  *
2065  * Return: QDF status
2066  */
2067 static QDF_STATUS
2068 send_icmp_ipv4_config_cmd_tlv(wmi_unified_t wmi_handle,
2069 			      struct pmo_icmp_offload *pmo_icmp_req)
2070 {
2071 	wmi_buf_t buf;
2072 	wmi_icmp_offload_fixed_param *cmd;
2073 	uint16_t len = sizeof(*cmd);
2074 	QDF_STATUS status;
2075 
2076 	buf = wmi_buf_alloc(wmi_handle, len);
2077 	if (!buf) {
2078 		wmi_err_rl("Failed to allocate wmi buffer");
2079 		status = QDF_STATUS_E_NOMEM;
2080 		return status;
2081 	}
2082 	cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf);
2083 	WMITLV_SET_HDR(&cmd->tlv_header,
2084 		       WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param,
2085 		       WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param));
2086 
2087 	cmd->vdev_id = pmo_icmp_req->vdev_id;
2088 	cmd->enable = pmo_icmp_req->enable;
2089 	cmd->valid_bitmask = 0;
2090 
2091 	WMI_SET_ICMP_OFFLOAD_IPV4_ENABLED_BIT(cmd->valid_bitmask);
2092 	qdf_mem_copy(&cmd->ipv4_addr, pmo_icmp_req->ipv4_addr,
2093 		     QDF_IPV4_ADDR_SIZE);
2094 	wmi_debug("ipv4:%pI4", &cmd->ipv4_addr);
2095 
2096 	wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
2097 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
2098 				      WMI_VDEV_ICMP_OFFLOAD_CMDID);
2099 
2100 	if (QDF_IS_STATUS_ERROR(status))
2101 		wmi_buf_free(buf);
2102 
2103 	return status;
2104 }
2105 
2106 /**
2107  * send_icmp_ipv6_config_cmd_tlv() - send ICMP IPV6 offload command to fw
2108  * @wmi_handle: wmi handle
2109  * @pmo_icmp_req: ICMP offload parameters
2110  *
2111  * Return: QDF status
2112  */
2113 static QDF_STATUS
2114 send_icmp_ipv6_config_cmd_tlv(wmi_unified_t wmi_handle,
2115 			      struct pmo_icmp_offload *pmo_icmp_req)
2116 {
2117 	wmi_buf_t buf;
2118 	uint8_t *buf_ptr;
2119 	uint16_t len;
2120 	int i;
2121 	WMI_IPV6_ADDR *ipv6_list;
2122 	wmi_icmp_offload_fixed_param *cmd;
2123 	QDF_STATUS status;
2124 
2125 	len = sizeof(wmi_icmp_offload_fixed_param) + WMI_TLV_HDR_SIZE +
2126 	      (pmo_icmp_req->ipv6_count) * sizeof(WMI_IPV6_ADDR);
2127 
2128 	buf = wmi_buf_alloc(wmi_handle, len);
2129 	if (!buf) {
2130 		wmi_err_rl("Failed to allocate wmi buffer");
2131 		status = QDF_STATUS_E_NOMEM;
2132 		return status;
2133 	}
2134 
2135 	buf_ptr = (uint8_t *)wmi_buf_data(buf);
2136 	cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf);
2137 	WMITLV_SET_HDR(&cmd->tlv_header,
2138 		       WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param,
2139 		       WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param));
2140 
2141 	cmd->vdev_id = pmo_icmp_req->vdev_id;
2142 	cmd->enable = pmo_icmp_req->enable;
2143 	cmd->valid_bitmask = 0;
2144 
2145 	WMI_SET_ICMP_OFFLOAD_IPV6_ENABLED_BIT(cmd->valid_bitmask);
2146 	buf_ptr += sizeof(*cmd);
2147 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
2148 		       sizeof(WMI_IPV6_ADDR) * pmo_icmp_req->ipv6_count);
2149 	ipv6_list = (WMI_IPV6_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE);
2150 
2151 	for (i = 0; i < pmo_icmp_req->ipv6_count; i++) {
2152 		qdf_mem_copy(((*(ipv6_list + i)).address),
2153 			     &pmo_icmp_req->ipv6_addr[i],
2154 			     sizeof(WMI_IPV6_ADDR));
2155 		wmi_debug("ipv6_list[%d]:%pI6", i, (ipv6_list + i));
2156 	}
2157 
2158 	/* send the wmi command */
2159 	wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
2160 	status = wmi_unified_cmd_send(wmi_handle, buf, len,
2161 				      WMI_VDEV_ICMP_OFFLOAD_CMDID);
2162 
2163 	if (QDF_IS_STATUS_ERROR(status))
2164 		wmi_buf_free(buf);
2165 
2166 	return status;
2167 }
2168 
2169 /**
2170  * send_icmp_offload_config_cmd_tlv() - send ICMP offload command to fw
2171  * @wmi_handle: wmi handle
2172  * @pmo_icmp_req: ICMP offload parameters
2173  *
2174  * Return: QDF status
2175  */
2176 static QDF_STATUS
2177 send_icmp_offload_config_cmd_tlv(wmi_unified_t wmi_handle,
2178 				 struct pmo_icmp_offload *pmo_icmp_req)
2179 {
2180 	QDF_STATUS status;
2181 
2182 	switch (pmo_icmp_req->trigger) {
2183 	case pmo_ipv4_change_notify:
2184 		status = send_icmp_ipv4_config_cmd_tlv(wmi_handle,
2185 						       pmo_icmp_req);
2186 		break;
2187 	case pmo_ipv6_change_notify:
2188 		status = send_icmp_ipv6_config_cmd_tlv(wmi_handle,
2189 						       pmo_icmp_req);
2190 		break;
2191 	default:
2192 		QDF_DEBUG_PANIC("Invalid ICMP trigger %d",
2193 				pmo_icmp_req->trigger);
2194 		status = QDF_STATUS_E_FAILURE;
2195 	}
2196 
2197 	return status;
2198 }
2199 
2200 static void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle)
2201 {
2202 	struct wmi_ops *ops = wmi_handle->ops;
2203 
2204 	ops->send_icmp_offload_config_cmd = send_icmp_offload_config_cmd_tlv;
2205 }
2206 #else
2207 static inline void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle)
2208 {}
2209 #endif /* WLAN_FEATURE_ICMP_OFFLOAD */
2210 
2211 void wmi_pmo_attach_tlv(wmi_unified_t wmi_handle)
2212 {
2213 	struct wmi_ops *ops = wmi_handle->ops;
2214 
2215 	ops->send_add_wow_wakeup_event_cmd =
2216 		send_add_wow_wakeup_event_cmd_tlv;
2217 	ops->send_wow_patterns_to_fw_cmd = send_wow_patterns_to_fw_cmd_tlv;
2218 	ops->send_enable_arp_ns_offload_cmd =
2219 		send_enable_arp_ns_offload_cmd_tlv;
2220 	ops->send_add_clear_mcbc_filter_cmd =
2221 		send_add_clear_mcbc_filter_cmd_tlv;
2222 	ops->send_multiple_add_clear_mcbc_filter_cmd =
2223 		send_multiple_add_clear_mcbc_filter_cmd_tlv;
2224 	ops->send_conf_hw_filter_cmd = send_conf_hw_filter_cmd_tlv;
2225 	ops->send_gtk_offload_cmd = send_gtk_offload_cmd_tlv;
2226 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
2227 	ops->send_igmp_offload_cmd = send_igmp_offload_cmd_tlv;
2228 #endif
2229 	ops->send_process_gtk_offload_getinfo_cmd =
2230 		send_process_gtk_offload_getinfo_cmd_tlv;
2231 	ops->send_enable_enhance_multicast_offload_cmd =
2232 		send_enable_enhance_multicast_offload_tlv;
2233 	ops->extract_gtk_rsp_event = extract_gtk_rsp_event_tlv;
2234 	ops->send_action_frame_patterns_cmd =
2235 		send_action_frame_patterns_cmd_tlv;
2236 	ops->send_wow_delete_pattern_cmd = send_wow_delete_pattern_cmd_tlv;
2237 	ops->send_host_wakeup_ind_to_fw_cmd =
2238 		send_host_wakeup_ind_to_fw_cmd_tlv;
2239 	ops->send_wow_timer_pattern_cmd = send_wow_timer_pattern_cmd_tlv;
2240 
2241 	wmi_d0wow_attach_tlv(wmi_handle);
2242 	wmi_ra_filtering_attach_tlv(wmi_handle);
2243 	wmi_lphb_attach_tlv(wmi_handle);
2244 	wmi_packet_filtering_attach_tlv(wmi_handle);
2245 	wmi_extwow_attach_tlv(wmi_handle);
2246 	wmi_icmp_offload_config_tlv(wmi_handle);
2247 }
2248