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