xref: /wlan-dirver/qcacld-3.0/core/wma/src/wma_features.c (revision bf57c2c31e6d81d5645b6ca42f1e2fde23df07f7)
1 /*
2  * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
3  *
4  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5  *
6  *
7  * Permission to use, copy, modify, and/or distribute this software for
8  * any purpose with or without fee is hereby granted, provided that the
9  * above copyright notice and this permission notice appear in all
10  * copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19  * PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 /*
23  * This file was originally distributed by Qualcomm Atheros, Inc.
24  * under proprietary terms before Copyright ownership was assigned
25  * to the Linux Foundation.
26  */
27 
28 /**
29  *  DOC:    wma_features.c
30  *  This file contains different features related functions like WoW,
31  *  Offloads, TDLS etc.
32  */
33 
34 /* Header files */
35 
36 #include "cds_ieee80211_common.h"	/* ieee80211_frame */
37 #include "wma.h"
38 #include "wma_api.h"
39 #include "cds_api.h"
40 #include "wmi_unified_api.h"
41 #include "wlan_qct_sys.h"
42 #include "wni_api.h"
43 #include "ani_global.h"
44 #include "wmi_unified.h"
45 #include "wni_cfg.h"
46 #include "cfg_api.h"
47 #include <cdp_txrx_tx_delay.h>
48 #include <cdp_txrx_peer_ops.h>
49 
50 #include "qdf_nbuf.h"
51 #include "qdf_types.h"
52 #include "qdf_mem.h"
53 #include "qdf_util.h"
54 
55 #include "wma_types.h"
56 #include "lim_api.h"
57 #include "lim_session_utils.h"
58 
59 #include "cds_utils.h"
60 
61 #if !defined(REMOVE_PKT_LOG)
62 #include "pktlog_ac.h"
63 #endif /* REMOVE_PKT_LOG */
64 
65 #include "dbglog_host.h"
66 #include "csr_api.h"
67 #include "ol_fw.h"
68 
69 #include "wma_internal.h"
70 #include "wma_nan_datapath.h"
71 #include <cdp_txrx_handle.h>
72 #include "wlan_pmo_ucfg_api.h"
73 #include <target_if_scan.h>
74 #include "wlan_reg_services_api.h"
75 #include "wlan_roam_debug.h"
76 
77 #ifndef ARRAY_LENGTH
78 #define ARRAY_LENGTH(a)         (sizeof(a) / sizeof((a)[0]))
79 #endif
80 
81 /**
82  * WMA_SET_VDEV_IE_SOURCE_HOST - Flag to identify the source of VDEV SET IE
83  * command. The value is 0x0 for the VDEV SET IE WMI commands from mobile
84  * MCL platform.
85  */
86 #define WMA_SET_VDEV_IE_SOURCE_HOST 0x0
87 
88 
89 #ifdef FEATURE_WLAN_DIAG_SUPPORT
90 /**
91  * qdf_wma_wow_wakeup_stats_event()- send wow wakeup stats
92  * @tp_wma_handle wma: WOW wakeup packet counter
93  *
94  * This function sends wow wakeup stats diag event
95  *
96  * Return: void.
97  */
98 static inline void qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma)
99 {
100 	QDF_STATUS status;
101 	struct sir_wake_lock_stats stats;
102 
103 	WLAN_HOST_DIAG_EVENT_DEF(WowStats,
104 	struct host_event_wlan_powersave_wow_stats);
105 
106 	status = wma_get_wakelock_stats(&stats);
107 	if (QDF_IS_STATUS_ERROR(status))
108 		return;
109 	qdf_mem_zero(&WowStats, sizeof(WowStats));
110 
111 	WowStats.wow_bcast_wake_up_count =
112 		stats.wow_bcast_wake_up_count;
113 	WowStats.wow_ipv4_mcast_wake_up_count =
114 		stats.wow_ipv4_mcast_wake_up_count;
115 	WowStats.wow_ipv6_mcast_wake_up_count =
116 		stats.wow_ipv6_mcast_wake_up_count;
117 	WowStats.wow_ipv6_mcast_ra_stats =
118 		stats.wow_ipv6_mcast_ra_stats;
119 	WowStats.wow_ipv6_mcast_ns_stats =
120 		stats.wow_ipv6_mcast_ns_stats;
121 	WowStats.wow_ipv6_mcast_na_stats =
122 		stats.wow_ipv6_mcast_na_stats;
123 	WowStats.wow_pno_match_wake_up_count =
124 		stats.wow_pno_match_wake_up_count;
125 	WowStats.wow_pno_complete_wake_up_count =
126 		stats.wow_pno_complete_wake_up_count;
127 	WowStats.wow_gscan_wake_up_count =
128 		stats.wow_gscan_wake_up_count;
129 	WowStats.wow_low_rssi_wake_up_count =
130 		stats.wow_low_rssi_wake_up_count;
131 	WowStats.wow_rssi_breach_wake_up_count =
132 		stats.wow_rssi_breach_wake_up_count;
133 	WowStats.wow_icmpv4_count =
134 		stats.wow_icmpv4_count;
135 	WowStats.wow_icmpv6_count =
136 		stats.wow_icmpv6_count;
137 	WowStats.wow_oem_response_wake_up_count =
138 		stats.wow_oem_response_wake_up_count;
139 
140 	WLAN_HOST_DIAG_EVENT_REPORT(&WowStats, EVENT_WLAN_POWERSAVE_WOW_STATS);
141 }
142 #else
143 static inline void qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma)
144 {
145 	return;
146 }
147 #endif
148 
149 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
150 /**
151  * wma_post_auto_shutdown_msg() - to post auto shutdown event to sme
152  *
153  * Return: 0 for success or error code
154  */
155 static int wma_wake_reason_auto_shutdown(void)
156 {
157 	tSirAutoShutdownEvtParams *auto_sh_evt;
158 	QDF_STATUS qdf_status;
159 	struct scheduler_msg sme_msg = { 0 };
160 
161 	auto_sh_evt = (tSirAutoShutdownEvtParams *)
162 		      qdf_mem_malloc(sizeof(tSirAutoShutdownEvtParams));
163 	if (!auto_sh_evt) {
164 		WMA_LOGE(FL("No Mem"));
165 		return -ENOMEM;
166 	}
167 
168 	auto_sh_evt->shutdown_reason =
169 		WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY;
170 	sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND;
171 	sme_msg.bodyptr = auto_sh_evt;
172 	sme_msg.bodyval = 0;
173 
174 	qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
175 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
176 		WMA_LOGE("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME");
177 		qdf_mem_free(auto_sh_evt);
178 		return -EINVAL;
179 	}
180 
181 	return 0;
182 }
183 #else
184 static inline int wma_wake_reason_auto_shutdown(void)
185 {
186 	return 0;
187 }
188 #endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
189 
190 #ifdef FEATURE_WLAN_SCAN_PNO
191 static int wma_wake_reason_nlod(t_wma_handle *wma, uint8_t vdev_id)
192 {
193 	wmi_nlo_event nlo_event = { .vdev_id = vdev_id };
194 	WMI_NLO_MATCH_EVENTID_param_tlvs param = { .fixed_param = &nlo_event };
195 
196 	return target_if_nlo_match_event_handler(wma, (uint8_t *)&param,
197 						 sizeof(param));
198 }
199 #else
200 static inline int wma_wake_reason_nlod(uint8_t vdev_id)
201 {
202 	return 0;
203 }
204 #endif /* FEATURE_WLAN_SCAN_PNO */
205 
206 /**
207  * wma_send_snr_request() - send request to fw to get RSSI stats
208  * @wma_handle: wma handle
209  * @pGetRssiReq: get RSSI request
210  *
211  * Return: QDF status
212  */
213 QDF_STATUS wma_send_snr_request(tp_wma_handle wma_handle,
214 				void *pGetRssiReq)
215 {
216 	tAniGetRssiReq *pRssiBkUp = NULL;
217 
218 	/* command is in progess */
219 	if (NULL != wma_handle->pGetRssiReq)
220 		return QDF_STATUS_SUCCESS;
221 
222 	/* create a copy of csrRssiCallback to send rssi value
223 	 * after wmi event
224 	 */
225 	if (pGetRssiReq) {
226 		pRssiBkUp = qdf_mem_malloc(sizeof(tAniGetRssiReq));
227 		if (!pRssiBkUp) {
228 			WMA_LOGE("Failed to alloc memory for tAniGetRssiReq");
229 			wma_handle->pGetRssiReq = NULL;
230 			return QDF_STATUS_E_NOMEM;
231 		}
232 		pRssiBkUp->sessionId =
233 			((tAniGetRssiReq *) pGetRssiReq)->sessionId;
234 		pRssiBkUp->rssiCallback =
235 			((tAniGetRssiReq *) pGetRssiReq)->rssiCallback;
236 		pRssiBkUp->pDevContext =
237 			((tAniGetRssiReq *) pGetRssiReq)->pDevContext;
238 		wma_handle->pGetRssiReq = (void *)pRssiBkUp;
239 	}
240 
241 	if (wmi_unified_snr_request_cmd(wma_handle->wmi_handle)) {
242 		WMA_LOGE("Failed to send host stats request to fw");
243 		qdf_mem_free(pRssiBkUp);
244 		wma_handle->pGetRssiReq = NULL;
245 		return QDF_STATUS_E_FAILURE;
246 	}
247 	return QDF_STATUS_SUCCESS;
248 }
249 
250 /**
251  * wma_get_snr() - get RSSI from fw
252  * @psnr_req: request params
253  *
254  * Return: QDF status
255  */
256 QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req)
257 {
258 	tAniGetSnrReq *psnr_req_bkp;
259 	tp_wma_handle wma_handle = NULL;
260 	struct wma_txrx_node *intr;
261 
262 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
263 
264 	if (NULL == wma_handle) {
265 		WMA_LOGE("%s : Failed to get wma_handle", __func__);
266 		return QDF_STATUS_E_FAULT;
267 	}
268 
269 	intr = &wma_handle->interfaces[psnr_req->sessionId];
270 	/* command is in progess */
271 	if (NULL != intr->psnr_req) {
272 		WMA_LOGE("%s : previous snr request is pending", __func__);
273 		return QDF_STATUS_SUCCESS;
274 	}
275 
276 	psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq));
277 	if (!psnr_req_bkp) {
278 		WMA_LOGE("Failed to allocate memory for tAniGetSnrReq");
279 		return QDF_STATUS_E_NOMEM;
280 	}
281 
282 	qdf_mem_set(psnr_req_bkp, sizeof(tAniGetSnrReq), 0);
283 	psnr_req_bkp->staId = psnr_req->staId;
284 	psnr_req_bkp->pDevContext = psnr_req->pDevContext;
285 	psnr_req_bkp->snrCallback = psnr_req->snrCallback;
286 	intr->psnr_req = (void *)psnr_req_bkp;
287 
288 	if (wmi_unified_snr_cmd(wma_handle->wmi_handle,
289 				 psnr_req->sessionId)) {
290 		WMA_LOGE("Failed to send host stats request to fw");
291 		qdf_mem_free(psnr_req_bkp);
292 		intr->psnr_req = NULL;
293 		return QDF_STATUS_E_FAILURE;
294 	}
295 
296 	return QDF_STATUS_SUCCESS;
297 }
298 
299 /**
300  * wma_process_link_status_req() - process link status request from UMAC
301  * @wma: wma handle
302  * @pGetLinkStatus: get link params
303  *
304  * Return: none
305  */
306 void wma_process_link_status_req(tp_wma_handle wma,
307 				 tAniGetLinkStatus *pGetLinkStatus)
308 {
309 	struct link_status_params cmd = {0};
310 	struct wma_txrx_node *iface =
311 		&wma->interfaces[pGetLinkStatus->sessionId];
312 
313 	if (iface->plink_status_req) {
314 		WMA_LOGE("%s:previous link status request is pending,deleting the new request",
315 			__func__);
316 		qdf_mem_free(pGetLinkStatus);
317 		return;
318 	}
319 
320 	iface->plink_status_req = pGetLinkStatus;
321 	cmd.session_id = pGetLinkStatus->sessionId;
322 	if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) {
323 		WMA_LOGE("Failed to send WMI link  status request to fw");
324 		iface->plink_status_req = NULL;
325 		goto end;
326 	}
327 
328 	return;
329 
330 end:
331 	wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
332 }
333 
334 #ifdef WLAN_FEATURE_TSF
335 /**
336  * wma_vdev_tsf_handler() - handle tsf event indicated by FW
337  * @handle: wma context
338  * @data: event buffer
339  * @data len: length of event buffer
340  *
341  * Return: 0 on success
342  */
343 int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
344 {
345 	struct scheduler_msg tsf_msg = {0};
346 	WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
347 	wmi_vdev_tsf_report_event_fixed_param *tsf_event;
348 	struct stsf *ptsf;
349 
350 	if (data == NULL) {
351 		WMA_LOGE("%s: invalid pointer", __func__);
352 		return -EINVAL;
353 	}
354 	ptsf = qdf_mem_malloc(sizeof(*ptsf));
355 	if (NULL == ptsf) {
356 		WMA_LOGE("%s: failed to allocate tsf data structure", __func__);
357 		return -ENOMEM;
358 	}
359 
360 	param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
361 	tsf_event = param_buf->fixed_param;
362 
363 	ptsf->vdev_id = tsf_event->vdev_id;
364 	ptsf->tsf_low = tsf_event->tsf_low;
365 	ptsf->tsf_high = tsf_event->tsf_high;
366 	ptsf->soc_timer_low = tsf_event->qtimer_low;
367 	ptsf->soc_timer_high = tsf_event->qtimer_high;
368 
369 	WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__);
370 	WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__,
371 	ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
372 
373 	tsf_msg.type = eWNI_SME_TSF_EVENT;
374 	tsf_msg.bodyptr = ptsf;
375 	tsf_msg.bodyval = 0;
376 
377 	if (QDF_STATUS_SUCCESS !=
378 		scheduler_post_msg(QDF_MODULE_ID_SME, &tsf_msg)) {
379 
380 		WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__);
381 		qdf_mem_free(ptsf);
382 		return -EINVAL;
383 	}
384 	return 0;
385 }
386 
387 #ifdef QCA_WIFI_3_0
388 #define TSF_FW_ACTION_CMD TSF_TSTAMP_QTIMER_CAPTURE_REQ
389 #else
390 #define TSF_FW_ACTION_CMD TSF_TSTAMP_CAPTURE_REQ
391 #endif
392 /**
393  * wma_capture_tsf() - send wmi to fw to capture tsf
394  * @wma_handle: wma handler
395  * @vdev_id: vdev id
396  *
397  * Return: wmi send state
398  */
399 QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
400 {
401 	QDF_STATUS status = QDF_STATUS_SUCCESS;
402 	wmi_buf_t buf;
403 	wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
404 	int ret;
405 	int len = sizeof(*cmd);
406 
407 	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
408 	if (!buf) {
409 		WMA_LOGP("%s: failed to allocate memory for cap tsf cmd",
410 			 __func__);
411 		return QDF_STATUS_E_NOMEM;
412 	}
413 
414 	cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
415 	cmd->vdev_id = vdev_id;
416 	cmd->tsf_action = TSF_FW_ACTION_CMD;
417 	WMA_LOGD("%s :vdev_id %u, tsf_cmd: %d", __func__, cmd->vdev_id,
418 						cmd->tsf_action);
419 
420 	WMITLV_SET_HDR(&cmd->tlv_header,
421 	WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
422 	WMITLV_GET_STRUCT_TLVLEN(
423 	wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
424 
425 	ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
426 				   WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
427 	if (ret != EOK) {
428 		WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
429 		status = QDF_STATUS_E_FAILURE;
430 		goto error;
431 	}
432 
433 	return QDF_STATUS_SUCCESS;
434 
435 error:
436 	if (buf)
437 		wmi_buf_free(buf);
438 	return status;
439 }
440 
441 /**
442  * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
443  * @wma_handle: wma handler
444  * @vdev_id: vdev id
445  *
446  * Return: wmi send state
447  */
448 QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
449 {
450 	QDF_STATUS status = QDF_STATUS_SUCCESS;
451 	wmi_buf_t buf;
452 	wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
453 	int ret;
454 	int len = sizeof(*cmd);
455 	uint8_t *buf_ptr;
456 
457 	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
458 	if (!buf) {
459 		WMA_LOGP("%s: failed to allocate memory for reset tsf gpio",
460 			 __func__);
461 		return QDF_STATUS_E_NOMEM;
462 	}
463 
464 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
465 	cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
466 	cmd->vdev_id = vdev_id;
467 	cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
468 
469 	WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", __func__,
470 		 cmd->vdev_id);
471 
472 	WMITLV_SET_HDR(&cmd->tlv_header,
473 		WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
474 		WMITLV_GET_STRUCT_TLVLEN(
475 				wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
476 
477 	ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
478 				   WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
479 
480 	if (ret != EOK) {
481 		WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
482 		status = QDF_STATUS_E_FAILURE;
483 		goto error;
484 	}
485 	return QDF_STATUS_SUCCESS;
486 
487 error:
488 	if (buf)
489 		wmi_buf_free(buf);
490 	return status;
491 }
492 
493 /**
494  * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin
495  * @handle: wma handler
496  * @pin: GPIO pin id
497  *
498  * Return: QDF_STATUS
499  */
500 QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin)
501 {
502 	tp_wma_handle wma = (tp_wma_handle)handle;
503 	struct pdev_params pdev_param = {0};
504 	int32_t ret;
505 
506 	if (!wma || !wma->wmi_handle) {
507 		WMA_LOGE("%s: WMA is closed, can not set gpio", __func__);
508 		return QDF_STATUS_E_INVAL;
509 	}
510 
511 	WMA_LOGD("%s: set tsf gpio pin: %d", __func__, pin);
512 
513 	pdev_param.param_id = WMI_PDEV_PARAM_WNTS_CONFIG;
514 	pdev_param.param_value = pin;
515 	ret = wmi_unified_pdev_param_send(wma->wmi_handle,
516 					 &pdev_param,
517 					 WMA_WILDCARD_PDEV_ID);
518 	if (ret) {
519 		WMA_LOGE("%s: Failed to set tsf gpio pin (%d)", __func__, ret);
520 		return QDF_STATUS_E_FAILURE;
521 	}
522 	return QDF_STATUS_SUCCESS;
523 }
524 #endif
525 
526 /**
527  * wma_set_wisa_params(): Set WISA features related params in FW
528  * @wma_handle: WMA handle
529  * @wisa: Pointer to WISA param struct
530  *
531  * Return: CDF status
532  */
533 QDF_STATUS wma_set_wisa_params(tp_wma_handle wma_handle,
534 				struct sir_wisa_params *wisa)
535 {
536 	QDF_STATUS status = QDF_STATUS_SUCCESS;
537 	wmi_buf_t buf;
538 	wmi_vdev_wisa_cmd_fixed_param *cmd;
539 	int ret, len = sizeof(*cmd);
540 
541 	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
542 	if (!buf) {
543 		WMA_LOGP("%s: failed to allocate memory for WISA params",
544 			 __func__);
545 		return QDF_STATUS_E_NOMEM;
546 	}
547 
548 	cmd = (wmi_vdev_wisa_cmd_fixed_param *) wmi_buf_data(buf);
549 	cmd->wisa_mode = wisa->mode;
550 	cmd->vdev_id = wisa->vdev_id;
551 
552 	WMITLV_SET_HDR(&cmd->tlv_header,
553 		WMITLV_TAG_STRUC_wmi_vdev_wisa_cmd_fixed_param,
554 		WMITLV_GET_STRUCT_TLVLEN(
555 				wmi_vdev_wisa_cmd_fixed_param));
556 
557 	ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
558 				   WMI_VDEV_WISA_CMDID);
559 	if (ret != EOK) {
560 		WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
561 		status = QDF_STATUS_E_FAILURE;
562 		goto error;
563 	}
564 	return QDF_STATUS_SUCCESS;
565 
566 error:
567 	wmi_buf_free(buf);
568 	return status;
569 }
570 
571 /**
572  * wma_process_dhcp_ind() - process dhcp indication from SME
573  * @wma_handle: wma handle
574  * @ta_dhcp_ind: DHCP indication
575  *
576  * Return: QDF Status
577  */
578 QDF_STATUS wma_process_dhcp_ind(tp_wma_handle wma_handle,
579 				tAniDHCPInd *ta_dhcp_ind)
580 {
581 	uint8_t vdev_id;
582 	int status = 0;
583 	wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
584 
585 	if (!ta_dhcp_ind) {
586 		WMA_LOGE("%s : DHCP indication is NULL", __func__);
587 		return QDF_STATUS_E_FAILURE;
588 	}
589 
590 	if (!wma_find_vdev_by_addr(wma_handle,
591 				   ta_dhcp_ind->adapterMacAddr.bytes,
592 				   &vdev_id)) {
593 		WMA_LOGE("%s: Failed to find vdev id for DHCP indication",
594 			 __func__);
595 		return QDF_STATUS_E_FAILURE;
596 	}
597 
598 	WMA_LOGD("%s: WMA --> WMI_PEER_SET_PARAM triggered by DHCP, msgType=%s, device_mode=%d, macAddr=" MAC_ADDRESS_STR,
599 		__func__, ta_dhcp_ind->msgType == WMA_DHCP_START_IND ?
600 		"WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND",
601 		ta_dhcp_ind->device_mode,
602 		MAC_ADDR_ARRAY(ta_dhcp_ind->peerMacAddr.bytes));
603 
604 	/* fill in values */
605 	peer_set_param_fp.vdev_id = vdev_id;
606 	peer_set_param_fp.param_id = WMI_PEER_CRIT_PROTO_HINT_ENABLED;
607 	if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType)
608 		peer_set_param_fp.param_value = 1;
609 	else
610 		peer_set_param_fp.param_value = 0;
611 	WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes,
612 				   &peer_set_param_fp.peer_macaddr);
613 
614 	status = wmi_unified_process_dhcp_ind(wma_handle->wmi_handle,
615 						&peer_set_param_fp);
616 	if (status != EOK)
617 		return QDF_STATUS_E_FAILURE;
618 
619 	return QDF_STATUS_SUCCESS;
620 }
621 
622 /**
623  * wma_chan_phy__mode() - get WLAN_PHY_MODE for channel
624  * @chan: channel number
625  * @chan_width: maximum channel width possible
626  * @dot11_mode: maximum phy_mode possible
627  *
628  * Return: return WLAN_PHY_MODE
629  */
630 WLAN_PHY_MODE wma_chan_phy_mode(u8 chan, enum phy_ch_width chan_width,
631 				u8 dot11_mode)
632 {
633 	WLAN_PHY_MODE phymode = MODE_UNKNOWN;
634 	uint16_t bw_val = wlan_reg_get_bw_value(chan_width);
635 
636 	if (WLAN_REG_IS_24GHZ_CH(chan)) {
637 		if (((CH_WIDTH_5MHZ == chan_width) ||
638 		     (CH_WIDTH_10MHZ == chan_width)) &&
639 		    ((WNI_CFG_DOT11_MODE_11B == dot11_mode) ||
640 		     (WNI_CFG_DOT11_MODE_11G == dot11_mode) ||
641 		     (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
642 		     (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
643 		     (WNI_CFG_DOT11_MODE_11AC == dot11_mode) ||
644 		     (WNI_CFG_DOT11_MODE_11AX == dot11_mode)))
645 			phymode = MODE_11G;
646 		else {
647 			switch (dot11_mode) {
648 			case WNI_CFG_DOT11_MODE_11B:
649 				if ((bw_val == 20) || (bw_val == 40))
650 					phymode = MODE_11B;
651 				break;
652 			case WNI_CFG_DOT11_MODE_11G:
653 				if ((bw_val == 20) || (bw_val == 40))
654 					phymode = MODE_11G;
655 				break;
656 			case WNI_CFG_DOT11_MODE_11G_ONLY:
657 				if ((bw_val == 20) || (bw_val == 40))
658 					phymode = MODE_11GONLY;
659 				break;
660 			case WNI_CFG_DOT11_MODE_11N:
661 			case WNI_CFG_DOT11_MODE_11N_ONLY:
662 				if (bw_val == 20)
663 					phymode = MODE_11NG_HT20;
664 				else if (bw_val == 40)
665 					phymode = MODE_11NG_HT40;
666 				break;
667 			case WNI_CFG_DOT11_MODE_ALL:
668 			case WNI_CFG_DOT11_MODE_11AC:
669 			case WNI_CFG_DOT11_MODE_11AC_ONLY:
670 				if (bw_val == 20)
671 					phymode = MODE_11AC_VHT20_2G;
672 				else if (bw_val == 40)
673 					phymode = MODE_11AC_VHT40_2G;
674 				break;
675 			case WNI_CFG_DOT11_MODE_11AX:
676 			case WNI_CFG_DOT11_MODE_11AX_ONLY:
677 				if (20 == bw_val)
678 					phymode = MODE_11AX_HE20_2G;
679 				else if (40 == bw_val)
680 					phymode = MODE_11AX_HE40_2G;
681 				break;
682 			default:
683 				break;
684 			}
685 		}
686 	} else if (WLAN_REG_IS_11P_CH(chan))
687 		phymode = MODE_11A;
688 	else {
689 		if (((CH_WIDTH_5MHZ == chan_width) ||
690 		     (CH_WIDTH_10MHZ == chan_width)) &&
691 		    ((WNI_CFG_DOT11_MODE_11A == dot11_mode) ||
692 		     (WNI_CFG_DOT11_MODE_11N == dot11_mode) ||
693 		     (WNI_CFG_DOT11_MODE_ALL == dot11_mode) ||
694 		     (WNI_CFG_DOT11_MODE_11AC == dot11_mode) ||
695 		     (WNI_CFG_DOT11_MODE_11AX == dot11_mode)))
696 			phymode = MODE_11A;
697 		else {
698 			switch (dot11_mode) {
699 			case WNI_CFG_DOT11_MODE_11A:
700 				if (0 < bw_val)
701 					phymode = MODE_11A;
702 				break;
703 			case WNI_CFG_DOT11_MODE_11N:
704 			case WNI_CFG_DOT11_MODE_11N_ONLY:
705 				if (bw_val == 20)
706 					phymode = MODE_11NA_HT20;
707 				else if (40 <= bw_val)
708 					phymode = MODE_11NA_HT40;
709 				break;
710 			case WNI_CFG_DOT11_MODE_ALL:
711 			case WNI_CFG_DOT11_MODE_11AC:
712 			case WNI_CFG_DOT11_MODE_11AC_ONLY:
713 				if (bw_val == 20)
714 					phymode = MODE_11AC_VHT20;
715 				else if (bw_val == 40)
716 					phymode = MODE_11AC_VHT40;
717 				else if (bw_val == 80)
718 					phymode = MODE_11AC_VHT80;
719 				else if (chan_width == CH_WIDTH_160MHZ)
720 					phymode = MODE_11AC_VHT160;
721 				else if (chan_width == CH_WIDTH_80P80MHZ)
722 					phymode = MODE_11AC_VHT80_80;
723 				break;
724 			case WNI_CFG_DOT11_MODE_11AX:
725 			case WNI_CFG_DOT11_MODE_11AX_ONLY:
726 				if (20 == bw_val)
727 					phymode = MODE_11AX_HE20;
728 				else if (40 == bw_val)
729 					phymode = MODE_11AX_HE40;
730 				else if (80 == bw_val)
731 					phymode = MODE_11AX_HE80;
732 				else if (CH_WIDTH_160MHZ == chan_width)
733 					phymode = MODE_11AX_HE160;
734 				else if (CH_WIDTH_80P80MHZ == chan_width)
735 					phymode = MODE_11AX_HE80_80;
736 				break;
737 			default:
738 				break;
739 			}
740 		}
741 	}
742 
743 	WMA_LOGD("%s: phymode %d channel %d ch_width %d dot11_mode %d",
744 		 __func__, phymode, chan, chan_width, dot11_mode);
745 
746 	QDF_ASSERT(MODE_UNKNOWN != phymode);
747 	return phymode;
748 }
749 
750 /**
751  * wma_get_link_speed() -send command to get linkspeed
752  * @handle: wma handle
753  * @pLinkSpeed: link speed info
754  *
755  * Return: QDF status
756  */
757 QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, tSirLinkSpeedInfo *pLinkSpeed)
758 {
759 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
760 	wmi_mac_addr peer_macaddr;
761 
762 	if (!wma_handle || !wma_handle->wmi_handle) {
763 		WMA_LOGE("%s: WMA is closed, can not issue get link speed cmd",
764 			 __func__);
765 		return QDF_STATUS_E_INVAL;
766 	}
767 	if (!wmi_service_enabled(wma_handle->wmi_handle,
768 				    wmi_service_estimate_linkspeed)) {
769 		WMA_LOGE("%s: Linkspeed feature bit not enabled Sending value 0 as link speed.",
770 			__func__);
771 		wma_send_link_speed(0);
772 		return QDF_STATUS_E_FAILURE;
773 	}
774 	/* Copy the peer macaddress to the wma buffer */
775 	WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes,
776 				   &peer_macaddr);
777 	WMA_LOGD("%s: pLinkSpeed->peerMacAddr: %pM, peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x",
778 		 __func__, pLinkSpeed->peer_macaddr.bytes,
779 		 peer_macaddr.mac_addr31to0,
780 		 peer_macaddr.mac_addr47to32);
781 	if (wmi_unified_get_link_speed_cmd(wma_handle->wmi_handle,
782 					peer_macaddr)) {
783 		return QDF_STATUS_E_FAILURE;
784 	}
785 
786 	return QDF_STATUS_SUCCESS;
787 }
788 
789 QDF_STATUS wma_get_peer_info(WMA_HANDLE handle,
790 				struct sir_peer_info_req *peer_info_req)
791 {
792 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
793 	wmi_request_stats_cmd_fixed_param *cmd;
794 	wmi_buf_t  wmi_buf;
795 	uint32_t  len;
796 	uint8_t *buf_ptr;
797 
798 	if (!wma_handle || !wma_handle->wmi_handle) {
799 		WMA_LOGE("%s: WMA is closed, can not issue get rssi",
800 			__func__);
801 		return QDF_STATUS_E_INVAL;
802 	}
803 
804 	len  = sizeof(wmi_request_stats_cmd_fixed_param);
805 	wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
806 	if (!wmi_buf) {
807 		WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
808 		return QDF_STATUS_E_NOMEM;
809 	}
810 	buf_ptr = (uint8_t *)wmi_buf_data(wmi_buf);
811 
812 	cmd = (wmi_request_stats_cmd_fixed_param *)buf_ptr;
813 	WMITLV_SET_HDR(&cmd->tlv_header,
814 		WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param,
815 		WMITLV_GET_STRUCT_TLVLEN(wmi_request_stats_cmd_fixed_param));
816 
817 	cmd->stats_id = WMI_REQUEST_PEER_STAT;
818 	cmd->vdev_id = peer_info_req->sessionid;
819 	WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_info_req->peer_macaddr.bytes,
820 				   &cmd->peer_macaddr);
821 	wma_handle->get_sta_peer_info = true;
822 
823 	if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
824 				WMI_REQUEST_STATS_CMDID)) {
825 		WMA_LOGE("Failed to send host stats request to fw");
826 		wmi_buf_free(wmi_buf);
827 		return QDF_STATUS_E_FAILURE;
828 	}
829 
830 	qdf_mem_copy(&(wma_handle->peer_macaddr),
831 					&(peer_info_req->peer_macaddr),
832 					QDF_MAC_ADDR_SIZE);
833 	return QDF_STATUS_SUCCESS;
834 }
835 
836 QDF_STATUS wma_get_peer_info_ext(WMA_HANDLE handle,
837 				struct sir_peer_info_ext_req *peer_info_req)
838 {
839 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
840 	wmi_request_peer_stats_info_cmd_fixed_param *cmd;
841 	wmi_buf_t  wmi_buf;
842 	uint32_t  len;
843 	uint8_t *buf_ptr;
844 
845 	if (!wma_handle || !wma_handle->wmi_handle) {
846 		WMA_LOGE("%s: WMA is closed, can not issue get rssi",
847 			__func__);
848 		return QDF_STATUS_E_INVAL;
849 	}
850 
851 	WMA_LOGI("%s send WMI_REQUEST_PEER_STATS_INFO_CMDID", __func__);
852 
853 	len  = sizeof(wmi_request_peer_stats_info_cmd_fixed_param);
854 	wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
855 	if (!wmi_buf) {
856 		WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
857 		return QDF_STATUS_E_NOMEM;
858 	}
859 	buf_ptr = (uint8_t *)wmi_buf_data(wmi_buf);
860 
861 	cmd = (wmi_request_peer_stats_info_cmd_fixed_param *)buf_ptr;
862 	WMITLV_SET_HDR(&cmd->tlv_header,
863 		WMITLV_TAG_STRUC_wmi_request_peer_stats_info_cmd_fixed_param,
864 		WMITLV_GET_STRUCT_TLVLEN(
865 			wmi_request_peer_stats_info_cmd_fixed_param));
866 	cmd->vdev_id = peer_info_req->sessionid;
867 	cmd->request_type = WMI_REQUEST_ONE_PEER_STATS_INFO;
868 	wma_handle->get_one_peer_info = true;
869 	WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_info_req->peer_macaddr.bytes,
870 			&cmd->peer_macaddr);
871 	cmd->reset_after_request = peer_info_req->reset_after_request;
872 
873 	if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
874 				WMI_REQUEST_PEER_STATS_INFO_CMDID)) {
875 		WMA_LOGE("Failed to send peer stats request to fw");
876 		wmi_buf_free(wmi_buf);
877 		return QDF_STATUS_E_FAILURE;
878 	}
879 
880 	WMA_LOGI("%s vdev_id %d, mac %pM, req_type %x, reset %x",
881 			__func__,
882 			cmd->vdev_id,
883 			peer_info_req->peer_macaddr.bytes,
884 			cmd->request_type,
885 			cmd->reset_after_request);
886 
887 	qdf_mem_copy(&(wma_handle->peer_macaddr),
888 					&(peer_info_req->peer_macaddr),
889 					QDF_MAC_ADDR_SIZE);
890 
891 	return QDF_STATUS_SUCCESS;
892 }
893 
894 /**
895  * wma_add_beacon_filter() - Issue WMI command to set beacon filter
896  * @wma: wma handler
897  * @filter_params: beacon_filter_param to set
898  *
899  * Return: Return QDF_STATUS
900  */
901 QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle,
902 				struct beacon_filter_param *filter_params)
903 {
904 	int i;
905 	wmi_buf_t wmi_buf;
906 	u_int8_t *buf;
907 	A_UINT32 *ie_map;
908 	int ret;
909 	struct wma_txrx_node *iface;
910 	tp_wma_handle wma = (tp_wma_handle) handle;
911 
912 	wmi_add_bcn_filter_cmd_fixed_param *cmd;
913 	int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param);
914 
915 	len += WMI_TLV_HDR_SIZE;
916 	len += BCN_FLT_MAX_ELEMS_IE_LIST*sizeof(A_UINT32);
917 
918 	if (!wma || !wma->wmi_handle) {
919 		WMA_LOGE("%s: WMA is closed, can not issue set beacon filter",
920 			__func__);
921 		return QDF_STATUS_E_INVAL;
922 	}
923 
924 	iface = &wma->interfaces[filter_params->vdev_id];
925 	qdf_mem_copy(&iface->beacon_filter, filter_params,
926 			sizeof(struct beacon_filter_param));
927 	iface->beacon_filter_enabled = true;
928 
929 	wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
930 	if (!wmi_buf) {
931 		WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
932 		return QDF_STATUS_E_NOMEM;
933 	}
934 
935 	buf = (u_int8_t *) wmi_buf_data(wmi_buf);
936 
937 	cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
938 	cmd->vdev_id = filter_params->vdev_id;
939 
940 	WMITLV_SET_HDR(&cmd->tlv_header,
941 			WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param,
942 			WMITLV_GET_STRUCT_TLVLEN(
943 				wmi_add_bcn_filter_cmd_fixed_param));
944 
945 	buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param);
946 
947 	WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32,
948 			(BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)));
949 
950 	ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE);
951 	for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) {
952 		ie_map[i] = filter_params->ie_map[i];
953 		WMA_LOGD("beacon filter ie map = %u", ie_map[i]);
954 	}
955 
956 	ret = wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
957 			WMI_ADD_BCN_FILTER_CMDID);
958 	if (ret) {
959 		WMA_LOGE("Failed to send wmi add beacon filter = %d",
960 				ret);
961 		wmi_buf_free(wmi_buf);
962 		return QDF_STATUS_E_FAILURE;
963 	}
964 
965 	return QDF_STATUS_SUCCESS;
966 }
967 
968 /**
969 * wma_remove_beacon_filter() - Issue WMI command to remove beacon filter
970 * @wma: wma handler
971 * @filter_params: beacon_filter_params
972 *
973 * Return: Return QDF_STATUS
974 */
975 QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle,
976 				struct beacon_filter_param *filter_params)
977 {
978 	wmi_buf_t buf;
979 	tp_wma_handle wma = (tp_wma_handle) handle;
980 	wmi_rmv_bcn_filter_cmd_fixed_param *cmd;
981 	int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param);
982 	int ret;
983 
984 	if (!wma || !wma->wmi_handle) {
985 		WMA_LOGE("%s: WMA is closed, cannot issue remove beacon filter",
986 			__func__);
987 		return QDF_STATUS_E_INVAL;
988 	}
989 
990 	buf = wmi_buf_alloc(wma->wmi_handle, len);
991 	if (!buf) {
992 		WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
993 		return QDF_STATUS_E_NOMEM;
994 	}
995 	cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf);
996 	cmd->vdev_id = filter_params->vdev_id;
997 
998 	WMITLV_SET_HDR(&cmd->tlv_header,
999 			WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param,
1000 			WMITLV_GET_STRUCT_TLVLEN(
1001 				wmi_rmv_bcn_filter_cmd_fixed_param));
1002 
1003 	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1004 			WMI_RMV_BCN_FILTER_CMDID);
1005 	if (ret) {
1006 		WMA_LOGE("Failed to send wmi remove beacon filter = %d",
1007 				ret);
1008 		wmi_buf_free(buf);
1009 		return QDF_STATUS_E_FAILURE;
1010 	}
1011 
1012 	return QDF_STATUS_SUCCESS;
1013 }
1014 
1015 /**
1016  * wma_send_adapt_dwelltime_params() - send adaptive dwelltime configuration
1017  * params to firmware
1018  * @wma_handle:	 wma handler
1019  * @dwelltime_params: pointer to dwelltime_params
1020  *
1021  * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure
1022  */
1023 QDF_STATUS wma_send_adapt_dwelltime_params(WMA_HANDLE handle,
1024 			struct adaptive_dwelltime_params *dwelltime_params)
1025 {
1026 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
1027 	struct wmi_adaptive_dwelltime_params wmi_param = {0};
1028 	int32_t err;
1029 
1030 	wmi_param.is_enabled = dwelltime_params->is_enabled;
1031 	wmi_param.dwelltime_mode = dwelltime_params->dwelltime_mode;
1032 	wmi_param.lpf_weight = dwelltime_params->lpf_weight;
1033 	wmi_param.passive_mon_intval = dwelltime_params->passive_mon_intval;
1034 	wmi_param.wifi_act_threshold = dwelltime_params->wifi_act_threshold;
1035 	err = wmi_unified_send_adapt_dwelltime_params_cmd(wma_handle->
1036 					wmi_handle, &wmi_param);
1037 	if (err)
1038 		return QDF_STATUS_E_FAILURE;
1039 
1040 	return QDF_STATUS_SUCCESS;
1041 }
1042 
1043 QDF_STATUS wma_send_dbs_scan_selection_params(WMA_HANDLE handle,
1044 			struct wmi_dbs_scan_sel_params *dbs_scan_params)
1045 {
1046 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
1047 	int32_t err;
1048 
1049 	err = wmi_unified_send_dbs_scan_sel_params_cmd(wma_handle->
1050 					wmi_handle, dbs_scan_params);
1051 	if (err)
1052 		return QDF_STATUS_E_FAILURE;
1053 
1054 	return QDF_STATUS_SUCCESS;
1055 }
1056 
1057 /**
1058  * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW
1059  * @wma: wma handle
1060  * @cmd: Profiling command index
1061  * @value1: parameter1 value
1062  * @value2: parameter2 value
1063  *
1064  * Return: 0 for success else error code
1065  */
1066 QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
1067 			uint32_t cmd, uint32_t value1, uint32_t value2)
1068 {
1069 	int ret;
1070 
1071 	ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd,
1072 			value1, value2);
1073 	if (ret) {
1074 		WMA_LOGE("enable cmd Failed for id %d value %d",
1075 				value1, value2);
1076 		return ret;
1077 	}
1078 
1079 	return QDF_STATUS_SUCCESS;
1080 }
1081 
1082 /**
1083  * wma_wow_set_wake_time() - set timer pattern tlv, so that firmware will wake
1084  * up host after specified time is elapsed
1085  * @wma_handle: wma handle
1086  * @vdev_id: vdev id
1087  * @cookie: value to identify reason why host set up wake call.
1088  * @time: time in ms
1089  *
1090  * Return: QDF status
1091  */
1092 static QDF_STATUS wma_wow_set_wake_time(WMA_HANDLE wma_handle, uint8_t vdev_id,
1093 					uint32_t cookie, uint32_t time)
1094 {
1095 	int ret;
1096 	tp_wma_handle wma = (tp_wma_handle)wma_handle;
1097 
1098 	WMA_LOGD(FL("send timer patter with time: %d and vdev = %d to fw"),
1099 		    time, vdev_id);
1100 	ret = wmi_unified_wow_timer_pattern_cmd(wma->wmi_handle, vdev_id,
1101 						cookie, time);
1102 	if (ret) {
1103 		WMA_LOGE(FL("Failed to send timer patter to fw"));
1104 		return QDF_STATUS_E_FAILURE;
1105 	}
1106 
1107 	return QDF_STATUS_SUCCESS;
1108 }
1109 
1110 /**
1111  * wma_check_and_set_wake_timer(): checks all interfaces and if any interface
1112  * has install_key pending, sets timer pattern in fw to wake up host after
1113  * specified time has elapsed.
1114  * @wma: wma handle
1115  * @time: time after which host wants to be awaken.
1116  *
1117  * Return: None
1118  */
1119 void wma_check_and_set_wake_timer(uint32_t time)
1120 {
1121 	int i;
1122 	struct wma_txrx_node *iface;
1123 	bool is_set_key_in_progress = false;
1124 	t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
1125 
1126 	if (!wma) {
1127 		WMA_LOGE("%s: WMA is closed",
1128 			__func__);
1129 		return;
1130 	}
1131 
1132 	if (!wmi_service_enabled(wma->wmi_handle,
1133 		wmi_service_wow_wakeup_by_timer_pattern)) {
1134 		WMA_LOGD("TIME_PATTERN is not enabled");
1135 		return;
1136 	}
1137 
1138 	for (i = 0; i < wma->max_bssid; i++) {
1139 		iface = &wma->interfaces[i];
1140 		if (iface->is_vdev_valid && iface->is_waiting_for_key) {
1141 			/*
1142 			 * right now cookie is dont care, since FW disregards
1143 			 * that.
1144 			 */
1145 			is_set_key_in_progress = true;
1146 			wma_wow_set_wake_time((WMA_HANDLE)wma, i, 0, time);
1147 			break;
1148 		}
1149 	}
1150 
1151 	if (!is_set_key_in_progress)
1152 		WMA_LOGD("set key not in progress for any vdev");
1153 }
1154 
1155 /**
1156  * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
1157  * @wma: wma handle
1158  * @vdev_id: vdev id
1159  *
1160  * Return: 0 for success or error code
1161  */
1162 int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id)
1163 {
1164 
1165 	if (wmi_unified_nat_keepalive_en_cmd(wma->wmi_handle, vdev_id))
1166 		return QDF_STATUS_E_FAILURE;
1167 
1168 	return QDF_STATUS_SUCCESS;
1169 }
1170 
1171 /**
1172  * wma_unified_csa_offload_enable() - sen CSA offload enable command
1173  * @wma: wma handle
1174  * @vdev_id: vdev id
1175  *
1176  * Return: 0 for success or error code
1177  */
1178 int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
1179 {
1180 	if (wmi_unified_csa_offload_enable(wma->wmi_handle,
1181 				 vdev_id)) {
1182 		WMA_LOGP("%s: Failed to send CSA offload enable command",
1183 			 __func__);
1184 		return -EIO;
1185 	}
1186 
1187 	return 0;
1188 }
1189 
1190 #ifdef WLAN_FEATURE_NAN
1191 /**
1192  * wma_nan_rsp_event_handler() - Function is used to handle nan response
1193  * @handle: wma handle
1194  * @event_buf: event buffer
1195  * @len: length of buffer
1196  *
1197  * Return: 0 for success or error code
1198  */
1199 int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1200 			      uint32_t len)
1201 {
1202 	WMI_NAN_EVENTID_param_tlvs *param_buf;
1203 	tSirNanEvent *nan_rsp_event;
1204 	wmi_nan_event_hdr *nan_rsp_event_hdr;
1205 	QDF_STATUS status;
1206 	struct scheduler_msg message = {0};
1207 	uint8_t *buf_ptr;
1208 	uint32_t alloc_len;
1209 
1210 	/*
1211 	 * This is how received event_buf looks like
1212 	 *
1213 	 * <-------------------- event_buf ----------------------------------->
1214 	 *
1215 	 * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
1216 	 *
1217 	 * +-----------+---------+-----------------------+--------------------+
1218 	 * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
1219 	 * +-----------+---------+-----------------------+--------------------+
1220 	 */
1221 
1222 	WMA_LOGD("%s: Posting NaN response event to SME", __func__);
1223 	param_buf = (WMI_NAN_EVENTID_param_tlvs *) event_buf;
1224 	if (!param_buf) {
1225 		WMA_LOGE("%s: Invalid nan response event buf", __func__);
1226 		return -EINVAL;
1227 	}
1228 	nan_rsp_event_hdr = param_buf->fixed_param;
1229 	buf_ptr = (uint8_t *) nan_rsp_event_hdr;
1230 	alloc_len = sizeof(tSirNanEvent);
1231 	alloc_len += nan_rsp_event_hdr->data_len;
1232 	if (nan_rsp_event_hdr->data_len > ((WMI_SVC_MSG_MAX_SIZE -
1233 	    sizeof(*nan_rsp_event_hdr)) / sizeof(uint8_t)) ||
1234 	    nan_rsp_event_hdr->data_len > param_buf->num_data) {
1235 		WMA_LOGE("excess data length:%d, num_data:%d",
1236 			nan_rsp_event_hdr->data_len, param_buf->num_data);
1237 		return -EINVAL;
1238 	}
1239 	nan_rsp_event = (tSirNanEvent *) qdf_mem_malloc(alloc_len);
1240 	if (NULL == nan_rsp_event) {
1241 		WMA_LOGE("%s: Memory allocation failure", __func__);
1242 		return -ENOMEM;
1243 	}
1244 
1245 	nan_rsp_event->event_data_len = nan_rsp_event_hdr->data_len;
1246 	qdf_mem_copy(nan_rsp_event->event_data, buf_ptr +
1247 		     sizeof(wmi_nan_event_hdr) + WMI_TLV_HDR_SIZE,
1248 		     nan_rsp_event->event_data_len);
1249 	message.type = eWNI_SME_NAN_EVENT;
1250 	message.bodyptr = (void *)nan_rsp_event;
1251 	message.bodyval = 0;
1252 
1253 	status = scheduler_post_msg(QDF_MODULE_ID_SME, &message);
1254 	if (status != QDF_STATUS_SUCCESS) {
1255 		WMA_LOGE("%s: Failed to post NaN response event to SME",
1256 			 __func__);
1257 		qdf_mem_free(nan_rsp_event);
1258 		return -EFAULT;
1259 	}
1260 	WMA_LOGD("%s: NaN response event Posted to SME", __func__);
1261 	return 0;
1262 }
1263 #else
1264 static int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf,
1265 				     uint32_t len)
1266 {
1267 	return 0;
1268 }
1269 #endif /* WLAN_FEATURE_NAN */
1270 
1271 /**
1272  * wma_csa_offload_handler() - CSA event handler
1273  * @handle: wma handle
1274  * @event: event buffer
1275  * @len: buffer length
1276  *
1277  * This event is sent by firmware when it receives CSA IE.
1278  *
1279  * Return: 0 for success or error code
1280  */
1281 int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
1282 {
1283 	tp_wma_handle wma = (tp_wma_handle) handle;
1284 	WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf;
1285 	wmi_csa_event_fixed_param *csa_event;
1286 	uint8_t bssid[IEEE80211_ADDR_LEN];
1287 	uint8_t vdev_id = 0;
1288 	uint8_t cur_chan = 0;
1289 	struct ieee80211_channelswitch_ie *csa_ie;
1290 	struct csa_offload_params *csa_offload_event;
1291 	struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
1292 	struct ieee80211_ie_wide_bw_switch *wb_ie;
1293 	struct wma_txrx_node *intr = wma->interfaces;
1294 
1295 	param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
1296 
1297 	WMA_LOGD("%s: Enter", __func__);
1298 	if (!param_buf) {
1299 		WMA_LOGE("Invalid csa event buffer");
1300 		return -EINVAL;
1301 	}
1302 	csa_event = param_buf->fixed_param;
1303 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
1304 
1305 	if (wma_find_vdev_by_bssid(wma, bssid, &vdev_id) == NULL) {
1306 		WMA_LOGE("Invalid bssid received %s:%d", __func__, __LINE__);
1307 		return -EINVAL;
1308 	}
1309 
1310 	csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event));
1311 	if (!csa_offload_event) {
1312 		WMA_LOGE("QDF MEM Alloc Failed for csa_offload_event");
1313 		return -EINVAL;
1314 	}
1315 
1316 	qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event));
1317 	qdf_mem_copy(csa_offload_event->bssId, &bssid, IEEE80211_ADDR_LEN);
1318 
1319 	if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
1320 		csa_ie = (struct ieee80211_channelswitch_ie *)
1321 						(&csa_event->csa_ie[0]);
1322 		csa_offload_event->channel = csa_ie->newchannel;
1323 		csa_offload_event->switch_mode = csa_ie->switchmode;
1324 	} else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
1325 		xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
1326 						(&csa_event->xcsa_ie[0]);
1327 		csa_offload_event->channel = xcsa_ie->newchannel;
1328 		csa_offload_event->switch_mode = xcsa_ie->switchmode;
1329 		csa_offload_event->new_op_class = xcsa_ie->newClass;
1330 	} else {
1331 		WMA_LOGE("CSA Event error: No CSA IE present");
1332 		qdf_mem_free(csa_offload_event);
1333 		return -EINVAL;
1334 	}
1335 
1336 	if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
1337 		wb_ie = (struct ieee80211_ie_wide_bw_switch *)
1338 						(&csa_event->wb_ie[0]);
1339 		csa_offload_event->new_ch_width = wb_ie->new_ch_width;
1340 		csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1;
1341 		csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2;
1342 	}
1343 
1344 	csa_offload_event->ies_present_flag = csa_event->ies_present_flag;
1345 
1346 	WMA_LOGD("CSA: New Channel = %d BSSID:%pM",
1347 		 csa_offload_event->channel, csa_offload_event->bssId);
1348 
1349 	cur_chan = cds_freq_to_chan(intr[vdev_id].mhz);
1350 	/*
1351 	 * basic sanity check: requested channel should not be 0
1352 	 * and equal to home channel
1353 	 */
1354 	if (0 == csa_offload_event->channel) {
1355 		WMA_LOGE("CSA Event with channel %d. Ignore !!",
1356 			 csa_offload_event->channel);
1357 		qdf_mem_free(csa_offload_event);
1358 		return -EINVAL;
1359 	}
1360 	wma->interfaces[vdev_id].is_channel_switch = true;
1361 	wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0);
1362 	return 0;
1363 }
1364 
1365 #ifdef FEATURE_OEM_DATA_SUPPORT
1366 /**
1367  * wma_oem_data_response_handler() - OEM data response event handler
1368  * @handle: wma handle
1369  * @datap: data ptr
1370  * @len: data length
1371  *
1372  * Return: 0 for success or error code
1373  */
1374 int wma_oem_data_response_handler(void *handle,
1375 				  uint8_t *datap, uint32_t len)
1376 {
1377 	WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf;
1378 	uint8_t *data;
1379 	uint32_t datalen;
1380 	struct oem_data_rsp *oem_rsp;
1381 	tpAniSirGlobal pmac = cds_get_context(QDF_MODULE_ID_PE);
1382 
1383 	if (!pmac) {
1384 		WMA_LOGE(FL("Invalid pmac"));
1385 		return -EINVAL;
1386 	}
1387 
1388 	if (!pmac->sme.oem_data_rsp_callback) {
1389 		WMA_LOGE(FL("Callback not registered"));
1390 		return -EINVAL;
1391 	}
1392 
1393 	param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap;
1394 	if (!param_buf) {
1395 		WMA_LOGE(FL("Received NULL buf ptr from FW"));
1396 		return -ENOMEM;
1397 	}
1398 
1399 	data = param_buf->data;
1400 	datalen = param_buf->num_data;
1401 
1402 	if (!data) {
1403 		WMA_LOGE(FL("Received NULL data from FW"));
1404 		return -EINVAL;
1405 	}
1406 
1407 	if (datalen > OEM_DATA_RSP_SIZE) {
1408 		WMA_LOGE(FL("Received data len %d exceeds max value %d"),
1409 			 datalen, OEM_DATA_RSP_SIZE);
1410 		return -EINVAL;
1411 	}
1412 
1413 	oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp));
1414 	if (!oem_rsp) {
1415 		WMA_LOGE(FL("Failed to alloc oem_data_rsp"));
1416 		return -ENOMEM;
1417 	}
1418 	oem_rsp->rsp_len = datalen;
1419 	if (oem_rsp->rsp_len) {
1420 		oem_rsp->data = qdf_mem_malloc(oem_rsp->rsp_len);
1421 		if (!oem_rsp->data) {
1422 			WMA_LOGE(FL("malloc failed for data"));
1423 			qdf_mem_free(oem_rsp);
1424 			return -ENOMEM;
1425 		}
1426 	} else {
1427 		WMA_LOGE(FL("Invalid rsp length: %d"),
1428 			 oem_rsp->rsp_len);
1429 		qdf_mem_free(oem_rsp);
1430 		return -EINVAL;
1431 	}
1432 
1433 	qdf_mem_copy(oem_rsp->data, data, datalen);
1434 
1435 	WMA_LOGD("Sending OEM_DATA_RSP(len: %d) to upper layer", datalen);
1436 
1437 	pmac->sme.oem_data_rsp_callback(oem_rsp);
1438 
1439 	if (oem_rsp->data)
1440 		qdf_mem_free(oem_rsp->data);
1441 	qdf_mem_free(oem_rsp);
1442 
1443 	return 0;
1444 }
1445 
1446 /**
1447  * wma_start_oem_data_req() - start OEM data request to target
1448  * @wma_handle: wma handle
1449  * @oem_data_req: start request params
1450  *
1451  * Return: QDF_STATUS
1452  */
1453 QDF_STATUS wma_start_oem_data_req(tp_wma_handle wma_handle,
1454 			    struct oem_data_req *oem_data_req)
1455 {
1456 	int ret = 0;
1457 
1458 	WMA_LOGD(FL("Send OEM Data Request to target"));
1459 
1460 	if (!oem_data_req || !oem_data_req->data) {
1461 		WMA_LOGE(FL("oem_data_req is null"));
1462 		return QDF_STATUS_E_INVAL;
1463 	}
1464 
1465 	if (!wma_handle || !wma_handle->wmi_handle) {
1466 		WMA_LOGE(FL("WMA - closed, can not send Oem data request cmd"));
1467 		qdf_mem_free(oem_data_req->data);
1468 		return QDF_STATUS_E_INVAL;
1469 	}
1470 
1471 	ret = wmi_unified_start_oem_data_cmd(wma_handle->wmi_handle,
1472 				   oem_data_req->data_len,
1473 				   oem_data_req->data);
1474 
1475 	if (!QDF_IS_STATUS_SUCCESS(ret))
1476 		WMA_LOGE(FL("wmi cmd send failed"));
1477 
1478 	return ret;
1479 }
1480 #endif /* FEATURE_OEM_DATA_SUPPORT */
1481 
1482 #if !defined(REMOVE_PKT_LOG)
1483 /**
1484  * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target
1485  * @handle: wma handle
1486  * @params: pktlog params
1487  *
1488  * Return: QDF status
1489  */
1490 QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,
1491 				   struct ath_pktlog_wmi_params *params)
1492 {
1493 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
1494 	int ret;
1495 
1496 	ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle,
1497 			params->pktlog_event,
1498 			params->cmd_id, params->user_triggered);
1499 	if (ret)
1500 		return QDF_STATUS_E_FAILURE;
1501 
1502 	return QDF_STATUS_SUCCESS;
1503 }
1504 #endif /* REMOVE_PKT_LOG */
1505 
1506 /**
1507  * wma_wow_wake_reason_str() -  Converts wow wakeup reason code to text format
1508  * @wake_reason - WOW wake reason
1509  *
1510  * Return: reason code in string format
1511  */
1512 static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason)
1513 {
1514 	switch (wake_reason) {
1515 	case WOW_REASON_UNSPECIFIED:
1516 		return "UNSPECIFIED";
1517 	case WOW_REASON_NLOD:
1518 		return "NLOD";
1519 	case WOW_REASON_AP_ASSOC_LOST:
1520 		return "AP_ASSOC_LOST";
1521 	case WOW_REASON_LOW_RSSI:
1522 		return "LOW_RSSI";
1523 	case WOW_REASON_DEAUTH_RECVD:
1524 		return "DEAUTH_RECVD";
1525 	case WOW_REASON_DISASSOC_RECVD:
1526 		return "DISASSOC_RECVD";
1527 	case WOW_REASON_GTK_HS_ERR:
1528 		return "GTK_HS_ERR";
1529 	case WOW_REASON_EAP_REQ:
1530 		return "EAP_REQ";
1531 	case WOW_REASON_FOURWAY_HS_RECV:
1532 		return "FOURWAY_HS_RECV";
1533 	case WOW_REASON_TIMER_INTR_RECV:
1534 		return "TIMER_INTR_RECV";
1535 	case WOW_REASON_PATTERN_MATCH_FOUND:
1536 		return "PATTERN_MATCH_FOUND";
1537 	case WOW_REASON_RECV_MAGIC_PATTERN:
1538 		return "RECV_MAGIC_PATTERN";
1539 	case WOW_REASON_P2P_DISC:
1540 		return "P2P_DISC";
1541 	case WOW_REASON_WLAN_HB:
1542 		return "WLAN_HB";
1543 	case WOW_REASON_CSA_EVENT:
1544 		return "CSA_EVENT";
1545 	case WOW_REASON_PROBE_REQ_WPS_IE_RECV:
1546 		return "PROBE_REQ_WPS_IE_RECV";
1547 	case WOW_REASON_AUTH_REQ_RECV:
1548 		return "AUTH_REQ_RECV";
1549 	case WOW_REASON_ASSOC_REQ_RECV:
1550 		return "ASSOC_REQ_RECV";
1551 	case WOW_REASON_HTT_EVENT:
1552 		return "HTT_EVENT";
1553 	case WOW_REASON_RA_MATCH:
1554 		return "RA_MATCH";
1555 	case WOW_REASON_HOST_AUTO_SHUTDOWN:
1556 		return "HOST_AUTO_SHUTDOWN";
1557 	case WOW_REASON_IOAC_MAGIC_EVENT:
1558 		return "IOAC_MAGIC_EVENT";
1559 	case WOW_REASON_IOAC_SHORT_EVENT:
1560 		return "IOAC_SHORT_EVENT";
1561 	case WOW_REASON_IOAC_EXTEND_EVENT:
1562 		return "IOAC_EXTEND_EVENT";
1563 	case WOW_REASON_IOAC_TIMER_EVENT:
1564 		return "IOAC_TIMER_EVENT";
1565 	case WOW_REASON_ROAM_HO:
1566 		return "ROAM_HO";
1567 	case WOW_REASON_DFS_PHYERR_RADADR_EVENT:
1568 		return "DFS_PHYERR_RADADR_EVENT";
1569 	case WOW_REASON_BEACON_RECV:
1570 		return "BEACON_RECV";
1571 	case WOW_REASON_CLIENT_KICKOUT_EVENT:
1572 		return "CLIENT_KICKOUT_EVENT";
1573 	case WOW_REASON_NAN_EVENT:
1574 		return "NAN_EVENT";
1575 	case WOW_REASON_EXTSCAN:
1576 		return "EXTSCAN";
1577 	case WOW_REASON_RSSI_BREACH_EVENT:
1578 		return "RSSI_BREACH_EVENT";
1579 	case WOW_REASON_IOAC_REV_KA_FAIL_EVENT:
1580 		return "IOAC_REV_KA_FAIL_EVENT";
1581 	case WOW_REASON_IOAC_SOCK_EVENT:
1582 		return "IOAC_SOCK_EVENT";
1583 	case WOW_REASON_NLO_SCAN_COMPLETE:
1584 		return "NLO_SCAN_COMPLETE";
1585 	case WOW_REASON_PACKET_FILTER_MATCH:
1586 		return "PACKET_FILTER_MATCH";
1587 	case WOW_REASON_ASSOC_RES_RECV:
1588 		return "ASSOC_RES_RECV";
1589 	case WOW_REASON_REASSOC_REQ_RECV:
1590 		return "REASSOC_REQ_RECV";
1591 	case WOW_REASON_REASSOC_RES_RECV:
1592 		return "REASSOC_RES_RECV";
1593 	case WOW_REASON_ACTION_FRAME_RECV:
1594 		return "ACTION_FRAME_RECV";
1595 	case WOW_REASON_BPF_ALLOW:
1596 		return "BPF_ALLOW";
1597 	case WOW_REASON_NAN_DATA:
1598 		return "NAN_DATA";
1599 	case WOW_REASON_OEM_RESPONSE_EVENT:
1600 		return "OEM_RESPONSE_EVENT";
1601 	case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
1602 		return "TDLS_CONN_TRACKER_EVENT";
1603 	case WOW_REASON_CRITICAL_LOG:
1604 		return "CRITICAL_LOG";
1605 	case WOW_REASON_P2P_LISTEN_OFFLOAD:
1606 		return "P2P_LISTEN_OFFLOAD";
1607 	case WOW_REASON_NAN_EVENT_WAKE_HOST:
1608 		return "NAN_EVENT_WAKE_HOST";
1609 	case WOW_REASON_DEBUG_TEST:
1610 		return "DEBUG_TEST";
1611 	case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
1612 		return "CHIP_POWER_FAILURE_DETECT";
1613 	case WOW_REASON_11D_SCAN:
1614 		return "11D_SCAN";
1615 	case WOW_REASON_SAP_OBSS_DETECTION:
1616 		return "SAP_OBSS_DETECTION";
1617 	case WOW_REASON_BSS_COLOR_COLLISION_DETECT:
1618 		return "BSS_COLOR_COLLISION_DETECT";
1619 	default:
1620 		return "unknown";
1621 	}
1622 }
1623 
1624 /**
1625  * wma_wow_stats_display() - display wow wake up stats
1626  * @stats: per vdev stats counters
1627  *
1628  * Return: none
1629  */
1630 static void wma_wow_stats_display(struct sir_vdev_wow_stats *stats)
1631 {
1632 	WMA_LOGA("uc %d bc %d v4_mc %d v6_mc %d ra %d ns %d na %d pno_match %d pno_complete %d gscan %d low_rssi %d rssi_breach %d icmp %d icmpv6 %d oem %d",
1633 		stats->ucast,
1634 		stats->bcast,
1635 		stats->ipv4_mcast,
1636 		stats->ipv6_mcast,
1637 		stats->ipv6_mcast_ra,
1638 		stats->ipv6_mcast_ns,
1639 		stats->ipv6_mcast_na,
1640 		stats->pno_match,
1641 		stats->pno_complete,
1642 		stats->gscan,
1643 		stats->low_rssi,
1644 		stats->rssi_breach,
1645 		stats->icmpv4,
1646 		stats->icmpv6,
1647 		stats->oem_response);
1648 }
1649 
1650 static void wma_print_wow_stats(t_wma_handle *wma,
1651 				WOW_EVENT_INFO_fixed_param *wake_info)
1652 {
1653 	struct sir_vdev_wow_stats *stats;
1654 
1655 	switch (wake_info->wake_reason) {
1656 	case WOW_REASON_BPF_ALLOW:
1657 	case WOW_REASON_PATTERN_MATCH_FOUND:
1658 	case WOW_REASON_RA_MATCH:
1659 	case WOW_REASON_NLOD:
1660 	case WOW_REASON_NLO_SCAN_COMPLETE:
1661 	case WOW_REASON_LOW_RSSI:
1662 	case WOW_REASON_EXTSCAN:
1663 	case WOW_REASON_RSSI_BREACH_EVENT:
1664 	case WOW_REASON_OEM_RESPONSE_EVENT:
1665 	case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
1666 	case WOW_REASON_11D_SCAN:
1667 		break;
1668 	default:
1669 		return;
1670 	}
1671 
1672 	stats = &wma->interfaces[wake_info->vdev_id].wow_stats;
1673 	wma_wow_stats_display(stats);
1674 }
1675 
1676 /**
1677  * wma_inc_wow_stats() - maintain wow pattern match wake up stats
1678  * @wma: wma handle, containing the stats counters
1679  * @wake_info: the wake event information
1680  *
1681  * Return: none
1682  */
1683 static void wma_inc_wow_stats(t_wma_handle *wma,
1684 			      WOW_EVENT_INFO_fixed_param *wake_info)
1685 {
1686 	struct sir_vdev_wow_stats *stats;
1687 
1688 	if (wake_info->wake_reason == WOW_REASON_UNSPECIFIED) {
1689 		wma->wow_unspecified_wake_count++;
1690 		return;
1691 	}
1692 
1693 	stats = &wma->interfaces[wake_info->vdev_id].wow_stats;
1694 	switch (wake_info->wake_reason) {
1695 	case WOW_REASON_RA_MATCH:
1696 		stats->ipv6_mcast++;
1697 		stats->ipv6_mcast_ra++;
1698 		stats->icmpv6++;
1699 		break;
1700 	case WOW_REASON_NLOD:
1701 		stats->pno_match++;
1702 		break;
1703 	case WOW_REASON_NLO_SCAN_COMPLETE:
1704 		stats->pno_complete++;
1705 		break;
1706 	case WOW_REASON_LOW_RSSI:
1707 		stats->low_rssi++;
1708 		break;
1709 	case WOW_REASON_EXTSCAN:
1710 		stats->gscan++;
1711 		break;
1712 	case WOW_REASON_RSSI_BREACH_EVENT:
1713 		stats->rssi_breach++;
1714 		break;
1715 	case WOW_REASON_OEM_RESPONSE_EVENT:
1716 		stats->oem_response++;
1717 	case WOW_REASON_11D_SCAN:
1718 		stats->scan_11d++;
1719 		break;
1720 	case WOW_REASON_CHIP_POWER_FAILURE_DETECT:
1721 		stats->pwr_save_fail_detected++;
1722 		break;
1723 	}
1724 }
1725 
1726 #ifdef FEATURE_WLAN_EXTSCAN
1727 /**
1728  * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id
1729  * @tag: WMI TLV tag
1730  *
1731  * Return:
1732  *	0 if TLV tag is invalid
1733  *	else return corresponding WMI event id
1734  */
1735 static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
1736 {
1737 	uint32_t event_id;
1738 
1739 	switch (tag) {
1740 	case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param:
1741 		event_id = WMI_EXTSCAN_START_STOP_EVENTID;
1742 		break;
1743 
1744 	case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param:
1745 		event_id = WMI_EXTSCAN_OPERATION_EVENTID;
1746 		break;
1747 
1748 	case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param:
1749 		event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID;
1750 		break;
1751 
1752 	case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param:
1753 		event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID;
1754 		break;
1755 
1756 	case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param:
1757 		event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID;
1758 		break;
1759 
1760 	case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param:
1761 		event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID;
1762 		break;
1763 
1764 	case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param:
1765 		event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID;
1766 		break;
1767 
1768 	default:
1769 		event_id = 0;
1770 		WMA_LOGE("%s: Unknown tag: %d", __func__, tag);
1771 		break;
1772 	}
1773 
1774 	WMA_LOGI("%s: For tag %d WMI event 0x%x", __func__, tag, event_id);
1775 	return event_id;
1776 }
1777 #else
1778 static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag)
1779 {
1780 	return 0;
1781 }
1782 #endif
1783 
1784 /**
1785  * wow_get_wmi_eventid() - map reason or tlv tag to corresponding event id
1786  * @tag: WMI TLV tag
1787  * @reason: WOW reason
1788  *
1789  * WOW reason type is primarily used to find the ID. If there could be
1790  * multiple events that can be sent as a WOW event with same reason
1791  * then tlv tag is used to identify the corresponding event.
1792  *
1793  * Return:
1794  *      0 if TLV tag/reason is invalid
1795  *      else return corresponding WMI event id
1796  */
1797 static int wow_get_wmi_eventid(int32_t reason, uint32_t tag)
1798 {
1799 	int event_id;
1800 
1801 	switch (reason) {
1802 	case WOW_REASON_AP_ASSOC_LOST:
1803 		event_id = WMI_ROAM_EVENTID;
1804 		break;
1805 	case WOW_REASON_NLO_SCAN_COMPLETE:
1806 		event_id = WMI_NLO_SCAN_COMPLETE_EVENTID;
1807 		break;
1808 	case WOW_REASON_CSA_EVENT:
1809 		event_id = WMI_CSA_HANDLING_EVENTID;
1810 		break;
1811 	case WOW_REASON_LOW_RSSI:
1812 		event_id = WMI_ROAM_EVENTID;
1813 		break;
1814 	case WOW_REASON_CLIENT_KICKOUT_EVENT:
1815 		event_id = WMI_PEER_STA_KICKOUT_EVENTID;
1816 		break;
1817 	case WOW_REASON_EXTSCAN:
1818 		event_id = wma_extscan_get_eventid_from_tlvtag(tag);
1819 		break;
1820 	case WOW_REASON_RSSI_BREACH_EVENT:
1821 		event_id = WMI_RSSI_BREACH_EVENTID;
1822 		break;
1823 	case WOW_REASON_NAN_EVENT:
1824 		event_id = WMI_NAN_EVENTID;
1825 		break;
1826 	case WOW_REASON_NAN_DATA:
1827 		event_id = wma_ndp_get_eventid_from_tlvtag(tag);
1828 		break;
1829 	case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
1830 		event_id = WOW_TDLS_CONN_TRACKER_EVENT;
1831 		break;
1832 	case WOW_REASON_ROAM_HO:
1833 		event_id = WMI_ROAM_EVENTID;
1834 		break;
1835 	case WOW_REASON_11D_SCAN:
1836 		event_id = WMI_11D_NEW_COUNTRY_EVENTID;
1837 		break;
1838 	default:
1839 		WMA_LOGD(FL("No Event Id for WOW reason %s(%d)"),
1840 			 wma_wow_wake_reason_str(reason), reason);
1841 		event_id = 0;
1842 		break;
1843 	}
1844 	wlan_roam_debug_log(WMA_INVALID_VDEV_ID, DEBUG_WOW_REASON,
1845 			    DEBUG_INVALID_PEER_ID, NULL, NULL,
1846 			    reason, event_id);
1847 
1848 	return event_id;
1849 }
1850 
1851 /**
1852  * is_piggybacked_event() - Returns true if the given wake reason indicates
1853  *	there will be piggybacked TLV event data
1854  * @reason: WOW reason
1855  *
1856  * There are three types of WoW event payloads: none, piggybacked event, and
1857  * network packet. This function returns true for wake reasons that fall into
1858  * the piggybacked event case.
1859  *
1860  * Return: true for piggybacked event data
1861  */
1862 static bool is_piggybacked_event(int32_t reason)
1863 {
1864 	switch (reason) {
1865 	case WOW_REASON_AP_ASSOC_LOST:
1866 	case WOW_REASON_NLO_SCAN_COMPLETE:
1867 	case WOW_REASON_CSA_EVENT:
1868 	case WOW_REASON_LOW_RSSI:
1869 	case WOW_REASON_CLIENT_KICKOUT_EVENT:
1870 	case WOW_REASON_EXTSCAN:
1871 	case WOW_REASON_RSSI_BREACH_EVENT:
1872 	case WOW_REASON_NAN_EVENT:
1873 	case WOW_REASON_NAN_DATA:
1874 	case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
1875 	case WOW_REASON_ROAM_HO:
1876 		return true;
1877 	default:
1878 		return false;
1879 	}
1880 }
1881 
1882 /**
1883  * wma_pkt_proto_subtype_to_string() - to convert proto subtype
1884  *         of data packet to string.
1885  * @proto_subtype: proto subtype for data packet
1886  *
1887  * This function returns the string for the proto subtype of
1888  * data packet.
1889  *
1890  * Return: string for proto subtype for data packet
1891  */
1892 static const char *
1893 wma_pkt_proto_subtype_to_string(enum qdf_proto_subtype proto_subtype)
1894 {
1895 	switch (proto_subtype) {
1896 	case QDF_PROTO_EAPOL_M1:
1897 		return "EAPOL M1";
1898 	case QDF_PROTO_EAPOL_M2:
1899 		return "EAPOL M2";
1900 	case QDF_PROTO_EAPOL_M3:
1901 		return "EAPOL M3";
1902 	case QDF_PROTO_EAPOL_M4:
1903 		return "EAPOL M4";
1904 	case QDF_PROTO_DHCP_DISCOVER:
1905 		return "DHCP DISCOVER";
1906 	case QDF_PROTO_DHCP_REQUEST:
1907 		return "DHCP REQUEST";
1908 	case QDF_PROTO_DHCP_OFFER:
1909 		return "DHCP OFFER";
1910 	case QDF_PROTO_DHCP_ACK:
1911 		return "DHCP ACK";
1912 	case QDF_PROTO_DHCP_NACK:
1913 		return "DHCP NACK";
1914 	case QDF_PROTO_DHCP_RELEASE:
1915 		return "DHCP RELEASE";
1916 	case QDF_PROTO_DHCP_INFORM:
1917 		return "DHCP INFORM";
1918 	case QDF_PROTO_DHCP_DECLINE:
1919 		return "DHCP DECLINE";
1920 	case QDF_PROTO_ARP_REQ:
1921 		return "ARP REQUEST";
1922 	case QDF_PROTO_ARP_RES:
1923 		return "ARP RESPONSE";
1924 	case QDF_PROTO_ICMP_REQ:
1925 		return "ICMP REQUEST";
1926 	case QDF_PROTO_ICMP_RES:
1927 		return "ICMP RESPONSE";
1928 	case QDF_PROTO_ICMPV6_REQ:
1929 		return "ICMPV6 REQUEST";
1930 	case QDF_PROTO_ICMPV6_RES:
1931 		return "ICMPV6 RESPONSE";
1932 	case QDF_PROTO_ICMPV6_RS:
1933 		return "ICMPV6 RS";
1934 	case QDF_PROTO_ICMPV6_RA:
1935 		return "ICMPV6 RA";
1936 	case QDF_PROTO_ICMPV6_NS:
1937 		return "ICMPV6 NS";
1938 	case QDF_PROTO_ICMPV6_NA:
1939 		return "ICMPV6 NA";
1940 	case QDF_PROTO_IPV4_UDP:
1941 		return "IPV4 UDP Packet";
1942 	case QDF_PROTO_IPV4_TCP:
1943 		return "IPV4 TCP Packet";
1944 	case QDF_PROTO_IPV6_UDP:
1945 		return "IPV6 UDP Packet";
1946 	case QDF_PROTO_IPV6_TCP:
1947 		return "IPV6 TCP Packet";
1948 	default:
1949 		return NULL;
1950 	}
1951 }
1952 
1953 /**
1954  * wma_wow_get_pkt_proto_subtype() - get the proto subtype of the packet.
1955  * @data: Pointer to the packet data buffer
1956  * @len: length of the packet data buffer
1957  *
1958  * Return: proto subtype of the packet.
1959  */
1960 static enum qdf_proto_subtype
1961 wma_wow_get_pkt_proto_subtype(uint8_t *data, uint32_t len)
1962 {
1963 	uint16_t eth_type;
1964 	uint8_t proto_type;
1965 
1966 	if (len < QDF_NBUF_TRAC_ETH_TYPE_OFFSET + 2) {
1967 		WMA_LOGE("Malformed ethernet packet: length %u < %d",
1968 			 len, QDF_NBUF_TRAC_ETH_TYPE_OFFSET + 2);
1969 		return QDF_PROTO_INVALID;
1970 	}
1971 
1972 	eth_type = *(uint16_t *)(data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET);
1973 	eth_type = qdf_cpu_to_be16(eth_type);
1974 
1975 	WMA_LOGD("Ether Type: 0x%04x", eth_type);
1976 	switch (eth_type) {
1977 	case QDF_NBUF_TRAC_EAPOL_ETH_TYPE:
1978 		if (len < WMA_EAPOL_SUBTYPE_GET_MIN_LEN)
1979 			return QDF_PROTO_INVALID;
1980 
1981 		WMA_LOGD("EAPOL Packet");
1982 		return qdf_nbuf_data_get_eapol_subtype(data);
1983 
1984 	case QDF_NBUF_TRAC_ARP_ETH_TYPE:
1985 		if (len < WMA_ARP_SUBTYPE_GET_MIN_LEN)
1986 			return QDF_PROTO_INVALID;
1987 
1988 		WMA_LOGD("ARP Packet");
1989 		return qdf_nbuf_data_get_arp_subtype(data);
1990 
1991 	case QDF_NBUF_TRAC_IPV4_ETH_TYPE:
1992 		if (len < WMA_IPV4_PROTO_GET_MIN_LEN)
1993 			return QDF_PROTO_INVALID;
1994 
1995 		WMA_LOGD("IPV4 Packet");
1996 
1997 		proto_type = qdf_nbuf_data_get_ipv4_proto(data);
1998 		WMA_LOGD("IPV4_proto_type: %u", proto_type);
1999 
2000 		switch (proto_type) {
2001 		case QDF_NBUF_TRAC_ICMP_TYPE:
2002 			if (len < WMA_ICMP_SUBTYPE_GET_MIN_LEN)
2003 				return QDF_PROTO_INVALID;
2004 
2005 			WMA_LOGD("ICMP Packet");
2006 			return qdf_nbuf_data_get_icmp_subtype(data);
2007 
2008 		case QDF_NBUF_TRAC_UDP_TYPE:
2009 			if (len < WMA_IS_DHCP_GET_MIN_LEN)
2010 				return QDF_PROTO_IPV4_UDP;
2011 
2012 			if (!qdf_nbuf_data_is_ipv4_dhcp_pkt(data))
2013 				return QDF_PROTO_INVALID;
2014 
2015 			if (len < WMA_DHCP_SUBTYPE_GET_MIN_LEN)
2016 				return QDF_PROTO_INVALID;
2017 
2018 			WMA_LOGD("DHCP Packet");
2019 			return qdf_nbuf_data_get_dhcp_subtype(data);
2020 
2021 		case QDF_NBUF_TRAC_TCP_TYPE:
2022 			return QDF_PROTO_IPV4_TCP;
2023 
2024 		default:
2025 			return QDF_PROTO_INVALID;
2026 		}
2027 
2028 	case QDF_NBUF_TRAC_IPV6_ETH_TYPE:
2029 		if (len < WMA_IPV6_PROTO_GET_MIN_LEN)
2030 			return QDF_PROTO_INVALID;
2031 
2032 		WMA_LOGD("IPV6 Packet");
2033 
2034 		proto_type = qdf_nbuf_data_get_ipv6_proto(data);
2035 		WMA_LOGD("IPV6_proto_type: %u", proto_type);
2036 
2037 		switch (proto_type) {
2038 		case QDF_NBUF_TRAC_ICMPV6_TYPE:
2039 			if (len < WMA_ICMPV6_SUBTYPE_GET_MIN_LEN)
2040 				return QDF_PROTO_INVALID;
2041 
2042 			WMA_LOGD("ICMPV6 Packet");
2043 			return qdf_nbuf_data_get_icmpv6_subtype(data);
2044 
2045 		case QDF_NBUF_TRAC_UDP_TYPE:
2046 			return QDF_PROTO_IPV6_UDP;
2047 
2048 		case QDF_NBUF_TRAC_TCP_TYPE:
2049 			return QDF_PROTO_IPV6_TCP;
2050 
2051 		default:
2052 			return QDF_PROTO_INVALID;
2053 		}
2054 
2055 	default:
2056 		return QDF_PROTO_INVALID;
2057 	}
2058 }
2059 
2060 static void wma_log_pkt_eapol(uint8_t *data, uint32_t length)
2061 {
2062 	uint16_t pkt_len, key_len;
2063 
2064 	if (length < WMA_EAPOL_INFO_GET_MIN_LEN)
2065 		return;
2066 
2067 	pkt_len = *(uint16_t *)(data + EAPOL_PKT_LEN_OFFSET);
2068 	key_len = *(uint16_t *)(data + EAPOL_KEY_LEN_OFFSET);
2069 	WMA_LOGD("Pkt_len: %u, Key_len: %u",
2070 		 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(key_len));
2071 }
2072 
2073 static void wma_log_pkt_dhcp(uint8_t *data, uint32_t length)
2074 {
2075 	uint16_t pkt_len;
2076 	uint32_t trans_id;
2077 
2078 	if (length < WMA_DHCP_INFO_GET_MIN_LEN)
2079 		return;
2080 
2081 	pkt_len = *(uint16_t *)(data + DHCP_PKT_LEN_OFFSET);
2082 	trans_id = *(uint32_t *)(data + DHCP_TRANSACTION_ID_OFFSET);
2083 	WMA_LOGD("Pkt_len: %u, Transaction_id: %u",
2084 		 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(trans_id));
2085 }
2086 
2087 static void wma_log_pkt_icmpv4(uint8_t *data, uint32_t length)
2088 {
2089 	uint16_t pkt_len, seq_num;
2090 
2091 	if (length < WMA_IPV4_PKT_INFO_GET_MIN_LEN)
2092 		return;
2093 
2094 	pkt_len = *(uint16_t *)(data + IPV4_PKT_LEN_OFFSET);
2095 	seq_num = *(uint16_t *)(data + ICMP_SEQ_NUM_OFFSET);
2096 	WMA_LOGD("Pkt_len: %u, Seq_num: %u",
2097 		 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(seq_num));
2098 }
2099 
2100 static void wma_log_pkt_icmpv6(uint8_t *data, uint32_t length)
2101 {
2102 	uint16_t pkt_len, seq_num;
2103 
2104 	if (length < WMA_IPV6_PKT_INFO_GET_MIN_LEN)
2105 		return;
2106 
2107 	pkt_len = *(uint16_t *)(data + IPV6_PKT_LEN_OFFSET);
2108 	seq_num = *(uint16_t *)(data + ICMPV6_SEQ_NUM_OFFSET);
2109 	WMA_LOGD("Pkt_len: %u, Seq_num: %u",
2110 		 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(seq_num));
2111 }
2112 
2113 static void wma_log_pkt_ipv4(uint8_t *data, uint32_t length)
2114 {
2115 	uint16_t pkt_len, src_port, dst_port;
2116 	char *ip_addr;
2117 
2118 	if (length < WMA_IPV4_PKT_INFO_GET_MIN_LEN)
2119 		return;
2120 
2121 	pkt_len = *(uint16_t *)(data + IPV4_PKT_LEN_OFFSET);
2122 	ip_addr = (char *)(data + IPV4_SRC_ADDR_OFFSET);
2123 	WMA_LOGD("src addr %d:%d:%d:%d", ip_addr[0], ip_addr[1],
2124 		 ip_addr[2], ip_addr[3]);
2125 	ip_addr = (char *)(data + IPV4_DST_ADDR_OFFSET);
2126 	WMA_LOGD("dst addr %d:%d:%d:%d", ip_addr[0], ip_addr[1],
2127 		 ip_addr[2], ip_addr[3]);
2128 	src_port = *(uint16_t *)(data + IPV4_SRC_PORT_OFFSET);
2129 	dst_port = *(uint16_t *)(data + IPV4_DST_PORT_OFFSET);
2130 	WMA_LOGD("Pkt_len: %u, src_port: %u, dst_port: %u",
2131 		 qdf_cpu_to_be16(pkt_len),
2132 		 qdf_cpu_to_be16(src_port),
2133 		 qdf_cpu_to_be16(dst_port));
2134 }
2135 
2136 static void wma_log_pkt_ipv6(uint8_t *data, uint32_t length)
2137 {
2138 	uint16_t pkt_len, src_port, dst_port;
2139 	char *ip_addr;
2140 
2141 	if (length < WMA_IPV6_PKT_INFO_GET_MIN_LEN)
2142 		return;
2143 
2144 	pkt_len = *(uint16_t *)(data + IPV6_PKT_LEN_OFFSET);
2145 	ip_addr = (char *)(data + IPV6_SRC_ADDR_OFFSET);
2146 	WMA_LOGD("src addr "IPV6_ADDR_STR, ip_addr[0],
2147 		 ip_addr[1], ip_addr[2], ip_addr[3], ip_addr[4],
2148 		 ip_addr[5], ip_addr[6], ip_addr[7], ip_addr[8],
2149 		 ip_addr[9], ip_addr[10], ip_addr[11],
2150 		 ip_addr[12], ip_addr[13], ip_addr[14],
2151 		 ip_addr[15]);
2152 	ip_addr = (char *)(data + IPV6_DST_ADDR_OFFSET);
2153 	WMA_LOGD("dst addr "IPV6_ADDR_STR, ip_addr[0],
2154 		 ip_addr[1], ip_addr[2], ip_addr[3], ip_addr[4],
2155 		 ip_addr[5], ip_addr[6], ip_addr[7], ip_addr[8],
2156 		 ip_addr[9], ip_addr[10], ip_addr[11],
2157 		 ip_addr[12], ip_addr[13], ip_addr[14],
2158 		 ip_addr[15]);
2159 	src_port = *(uint16_t *)(data + IPV6_SRC_PORT_OFFSET);
2160 	dst_port = *(uint16_t *)(data + IPV6_DST_PORT_OFFSET);
2161 	WMA_LOGD("Pkt_len: %u, src_port: %u, dst_port: %u",
2162 		 qdf_cpu_to_be16(pkt_len),
2163 		 qdf_cpu_to_be16(src_port),
2164 		 qdf_cpu_to_be16(dst_port));
2165 }
2166 
2167 static void wma_log_pkt_tcpv4(uint8_t *data, uint32_t length)
2168 {
2169 	uint32_t seq_num;
2170 
2171 	if (length < WMA_IPV4_PKT_INFO_GET_MIN_LEN)
2172 		return;
2173 
2174 	seq_num = *(uint32_t *)(data + IPV4_TCP_SEQ_NUM_OFFSET);
2175 	WMA_LOGD("TCP_seq_num: %u", qdf_cpu_to_be16(seq_num));
2176 }
2177 
2178 static void wma_log_pkt_tcpv6(uint8_t *data, uint32_t length)
2179 {
2180 	uint32_t seq_num;
2181 
2182 	if (length < WMA_IPV6_PKT_INFO_GET_MIN_LEN)
2183 		return;
2184 
2185 	seq_num = *(uint32_t *)(data + IPV6_TCP_SEQ_NUM_OFFSET);
2186 	WMA_LOGD("TCP_seq_num: %u", qdf_cpu_to_be16(seq_num));
2187 }
2188 
2189 /**
2190  * wma_wow_parse_data_pkt() - API to parse data buffer for data
2191  *    packet that resulted in WOW wakeup.
2192  * @stats: per-vdev stats for tracking packet types
2193  * @data: Pointer to data buffer
2194  * @length: data buffer length
2195  *
2196  * This function parses the data buffer received (first few bytes of
2197  * skb->data) to get informaton like src mac addr, dst mac addr, packet
2198  * len, seq_num, etc. It also increments stats for different packet types.
2199  *
2200  * Return: void
2201  */
2202 static void wma_wow_parse_data_pkt(struct sir_vdev_wow_stats *stats,
2203 				   uint8_t *data,
2204 				   uint32_t length)
2205 {
2206 	enum qdf_proto_subtype proto_subtype;
2207 	const char *proto_subtype_name;
2208 	uint8_t *dest_mac;
2209 	uint8_t *src_mac;
2210 
2211 	WMA_LOGD("packet length: %u", length);
2212 	if (length < QDF_NBUF_TRAC_IPV4_OFFSET)
2213 		return;
2214 
2215 	src_mac = data + QDF_NBUF_SRC_MAC_OFFSET;
2216 	dest_mac = data + QDF_NBUF_DEST_MAC_OFFSET;
2217 	WMA_LOGD("Src_mac: " MAC_ADDRESS_STR ", Dst_mac: " MAC_ADDRESS_STR,
2218 		 MAC_ADDR_ARRAY(src_mac), MAC_ADDR_ARRAY(dest_mac));
2219 
2220 	switch (*dest_mac) {
2221 	case WMA_BCAST_MAC_ADDR:
2222 		stats->bcast++;
2223 		break;
2224 	case WMA_MCAST_IPV4_MAC_ADDR:
2225 		stats->ipv4_mcast++;
2226 		break;
2227 	case WMA_MCAST_IPV6_MAC_ADDR:
2228 		stats->ipv6_mcast++;
2229 		break;
2230 	default:
2231 		stats->ucast++;
2232 		break;
2233 	}
2234 
2235 	proto_subtype = wma_wow_get_pkt_proto_subtype(data, length);
2236 	proto_subtype_name = wma_pkt_proto_subtype_to_string(proto_subtype);
2237 	if (proto_subtype_name)
2238 		WMA_LOGD("WOW Wakeup: %s rcvd", proto_subtype_name);
2239 
2240 	switch (proto_subtype) {
2241 	case QDF_PROTO_EAPOL_M1:
2242 	case QDF_PROTO_EAPOL_M2:
2243 	case QDF_PROTO_EAPOL_M3:
2244 	case QDF_PROTO_EAPOL_M4:
2245 		wma_log_pkt_eapol(data, length);
2246 		break;
2247 
2248 	case QDF_PROTO_DHCP_DISCOVER:
2249 	case QDF_PROTO_DHCP_REQUEST:
2250 	case QDF_PROTO_DHCP_OFFER:
2251 	case QDF_PROTO_DHCP_ACK:
2252 	case QDF_PROTO_DHCP_NACK:
2253 	case QDF_PROTO_DHCP_RELEASE:
2254 	case QDF_PROTO_DHCP_INFORM:
2255 	case QDF_PROTO_DHCP_DECLINE:
2256 		wma_log_pkt_dhcp(data, length);
2257 		break;
2258 
2259 	case QDF_PROTO_ICMP_REQ:
2260 	case QDF_PROTO_ICMP_RES:
2261 		stats->icmpv4++;
2262 		wma_log_pkt_icmpv4(data, length);
2263 		break;
2264 
2265 	case QDF_PROTO_ICMPV6_REQ:
2266 	case QDF_PROTO_ICMPV6_RES:
2267 	case QDF_PROTO_ICMPV6_RS:
2268 		stats->icmpv6++;
2269 		wma_log_pkt_icmpv6(data, length);
2270 		break;
2271 	case QDF_PROTO_ICMPV6_RA:
2272 		stats->icmpv6++;
2273 		stats->ipv6_mcast_ra++;
2274 		wma_log_pkt_icmpv6(data, length);
2275 		break;
2276 	case QDF_PROTO_ICMPV6_NS:
2277 		stats->icmpv6++;
2278 		stats->ipv6_mcast_ns++;
2279 		wma_log_pkt_icmpv6(data, length);
2280 		break;
2281 	case QDF_PROTO_ICMPV6_NA:
2282 		stats->icmpv6++;
2283 		stats->ipv6_mcast_na++;
2284 		wma_log_pkt_icmpv6(data, length);
2285 		break;
2286 
2287 	case QDF_PROTO_IPV4_UDP:
2288 		wma_log_pkt_ipv4(data, length);
2289 		break;
2290 	case QDF_PROTO_IPV4_TCP:
2291 		wma_log_pkt_ipv4(data, length);
2292 		wma_log_pkt_tcpv4(data, length);
2293 		break;
2294 
2295 	case QDF_PROTO_IPV6_UDP:
2296 		wma_log_pkt_ipv6(data, length);
2297 		break;
2298 	case QDF_PROTO_IPV6_TCP:
2299 		wma_log_pkt_ipv6(data, length);
2300 		wma_log_pkt_tcpv6(data, length);
2301 		break;
2302 	default:
2303 		break;
2304 	}
2305 }
2306 
2307 /**
2308  * wma_wow_dump_mgmt_buffer() - API to parse data buffer for mgmt.
2309  *    packet that resulted in WOW wakeup.
2310  * @wow_packet_buffer: Pointer to data buffer
2311  * @buf_len: length of data buffer
2312  *
2313  * This function parses the data buffer received (802.11 header)
2314  * to get informaton like src mac addr, dst mac addr, seq_num,
2315  * frag_num, etc.
2316  *
2317  * Return: void
2318  */
2319 static void wma_wow_dump_mgmt_buffer(uint8_t *wow_packet_buffer,
2320 				     uint32_t buf_len)
2321 {
2322 	struct ieee80211_frame_addr4 *wh;
2323 
2324 	WMA_LOGD("wow_buf_pkt_len: %u", buf_len);
2325 	wh = (struct ieee80211_frame_addr4 *)
2326 		(wow_packet_buffer);
2327 	if (buf_len >= sizeof(struct ieee80211_frame)) {
2328 		uint8_t to_from_ds, frag_num;
2329 		uint32_t seq_num;
2330 
2331 		WMA_LOGE("RA: " MAC_ADDRESS_STR " TA: " MAC_ADDRESS_STR,
2332 			MAC_ADDR_ARRAY(wh->i_addr1),
2333 			MAC_ADDR_ARRAY(wh->i_addr2));
2334 
2335 		WMA_LOGE("TO_DS: %u, FROM_DS: %u",
2336 			wh->i_fc[1] & IEEE80211_FC1_DIR_TODS,
2337 			wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS);
2338 
2339 		to_from_ds = wh->i_fc[1] & IEEE80211_FC1_DIR_DSTODS;
2340 
2341 		switch (to_from_ds) {
2342 		case IEEE80211_NO_DS:
2343 			WMA_LOGE("BSSID: " MAC_ADDRESS_STR,
2344 				MAC_ADDR_ARRAY(wh->i_addr3));
2345 			break;
2346 		case IEEE80211_TO_DS:
2347 			WMA_LOGE("DA: " MAC_ADDRESS_STR,
2348 				MAC_ADDR_ARRAY(wh->i_addr3));
2349 			break;
2350 		case IEEE80211_FROM_DS:
2351 			WMA_LOGE("SA: " MAC_ADDRESS_STR,
2352 				MAC_ADDR_ARRAY(wh->i_addr3));
2353 			break;
2354 		case IEEE80211_DS_TO_DS:
2355 			if (buf_len >= sizeof(struct ieee80211_frame_addr4))
2356 				WMA_LOGE("DA: " MAC_ADDRESS_STR " SA: "
2357 					MAC_ADDRESS_STR,
2358 					MAC_ADDR_ARRAY(wh->i_addr3),
2359 					MAC_ADDR_ARRAY(wh->i_addr4));
2360 			break;
2361 		}
2362 
2363 		seq_num = (((*(uint16_t *)wh->i_seq) &
2364 				IEEE80211_SEQ_SEQ_MASK) >>
2365 				IEEE80211_SEQ_SEQ_SHIFT);
2366 		frag_num = (((*(uint16_t *)wh->i_seq) &
2367 				IEEE80211_SEQ_FRAG_MASK) >>
2368 				IEEE80211_SEQ_FRAG_SHIFT);
2369 
2370 		WMA_LOGE("SEQ_NUM: %u, FRAG_NUM: %u",
2371 				seq_num, frag_num);
2372 	} else {
2373 		WMA_LOGE("Insufficient buffer length for mgmt. packet");
2374 	}
2375 }
2376 
2377 /**
2378  * wma_acquire_wakelock() - conditionally aquires a wakelock base on wake reason
2379  * @wma: the wma handle with the wakelocks to aquire
2380  * @wake_reason: wow wakeup reason
2381  *
2382  * Return: None
2383  */
2384 static void wma_acquire_wow_wakelock(t_wma_handle *wma, int wake_reason)
2385 {
2386 	qdf_wake_lock_t *wl;
2387 	uint32_t ms;
2388 
2389 	switch (wake_reason) {
2390 	case WOW_REASON_AUTH_REQ_RECV:
2391 		wl = &wma->wow_auth_req_wl;
2392 		ms = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT;
2393 		break;
2394 	case WOW_REASON_ASSOC_REQ_RECV:
2395 		wl = &wma->wow_assoc_req_wl;
2396 		ms = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION;
2397 		break;
2398 	case WOW_REASON_DEAUTH_RECVD:
2399 		wl = &wma->wow_deauth_rec_wl;
2400 		ms = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION;
2401 		break;
2402 	case WOW_REASON_DISASSOC_RECVD:
2403 		wl = &wma->wow_disassoc_rec_wl;
2404 		ms = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION;
2405 		break;
2406 	case WOW_REASON_AP_ASSOC_LOST:
2407 		wl = &wma->wow_ap_assoc_lost_wl;
2408 		ms = WMA_BMISS_EVENT_WAKE_LOCK_DURATION;
2409 		break;
2410 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
2411 	case WOW_REASON_HOST_AUTO_SHUTDOWN:
2412 		wl = &wma->wow_auto_shutdown_wl;
2413 		ms = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION;
2414 		break;
2415 #endif
2416 	case WOW_REASON_ROAM_HO:
2417 		wl = &wma->roam_ho_wl;
2418 		ms = WMA_ROAM_HO_WAKE_LOCK_DURATION;
2419 		break;
2420 	default:
2421 		return;
2422 	}
2423 
2424 	WMA_LOGA("Holding %d msec wake_lock", ms);
2425 	cds_host_diag_log_work(wl, ms, WIFI_POWER_EVENT_WAKELOCK_WOW);
2426 	qdf_wake_lock_timeout_acquire(wl, ms);
2427 }
2428 
2429 /**
2430  * wma_wake_reason_ap_assoc_lost() - WOW_REASON_AP_ASSOC_LOST handler
2431  * @wma: Pointer to wma handle
2432  * @event: pointer to piggybacked WMI_ROAM_EVENTID_param_tlvs buffer
2433  * @len: length of the event buffer
2434  *
2435  * Return: Errno
2436  */
2437 static int
2438 wma_wake_reason_ap_assoc_lost(t_wma_handle *wma, void *event, uint32_t len)
2439 {
2440 	WMI_ROAM_EVENTID_param_tlvs *event_param;
2441 	wmi_roam_event_fixed_param *roam_event;
2442 
2443 	event_param = event;
2444 	if (!event_param) {
2445 		WMA_LOGE("AP Assoc Lost event data is null");
2446 		return -EINVAL;
2447 	}
2448 
2449 	roam_event = event_param->fixed_param;
2450 	WMA_LOGA(FL("Beacon miss indication on vdev %d"), roam_event->vdev_id);
2451 
2452 	wma_beacon_miss_handler(wma, roam_event->vdev_id, roam_event->rssi);
2453 
2454 	return 0;
2455 }
2456 
2457 static const char *wma_vdev_type_str(uint32_t vdev_type)
2458 {
2459 	switch (vdev_type) {
2460 	case WMI_VDEV_TYPE_AP:
2461 		return "AP";
2462 	case WMI_VDEV_TYPE_STA:
2463 		return "STA";
2464 	case WMI_VDEV_TYPE_IBSS:
2465 		return "IBSS";
2466 	case WMI_VDEV_TYPE_MONITOR:
2467 		return "MONITOR";
2468 	case WMI_VDEV_TYPE_NAN:
2469 		return "NAN";
2470 	case WMI_VDEV_TYPE_OCB:
2471 		return "OCB";
2472 	case WMI_VDEV_TYPE_NDI:
2473 		return "NDI";
2474 	default:
2475 		return "unknown";
2476 	}
2477 }
2478 
2479 static int wma_wake_event_packet(
2480 	t_wma_handle *wma,
2481 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param,
2482 	uint32_t length)
2483 {
2484 	WOW_EVENT_INFO_fixed_param *wake_info;
2485 	struct wma_txrx_node *vdev;
2486 	uint8_t *packet;
2487 	uint32_t packet_len;
2488 
2489 	if (event_param->num_wow_packet_buffer <= 4) {
2490 		WMA_LOGE("Invalid wow packet buffer from firmware %u",
2491 			 event_param->num_wow_packet_buffer);
2492 		return -EINVAL;
2493 	}
2494 	/* first 4 bytes are the length, followed by the buffer */
2495 	packet_len = *(uint32_t *)event_param->wow_packet_buffer;
2496 	packet = event_param->wow_packet_buffer + 4;
2497 
2498 	if (!packet_len) {
2499 		WMA_LOGE("Wake event packet is empty");
2500 		return 0;
2501 	}
2502 
2503 	if (packet_len > (event_param->num_wow_packet_buffer - 4)) {
2504 		WMA_LOGE("Invalid packet_len from firmware, packet_len: %u, num_wow_packet_buffer: %u",
2505 			 packet_len,
2506 			 event_param->num_wow_packet_buffer);
2507 		return -EINVAL;
2508 	}
2509 
2510 	wake_info = event_param->fixed_param;
2511 
2512 	switch (wake_info->wake_reason) {
2513 	case WOW_REASON_AUTH_REQ_RECV:
2514 	case WOW_REASON_ASSOC_REQ_RECV:
2515 	case WOW_REASON_DEAUTH_RECVD:
2516 	case WOW_REASON_DISASSOC_RECVD:
2517 	case WOW_REASON_ASSOC_RES_RECV:
2518 	case WOW_REASON_REASSOC_REQ_RECV:
2519 	case WOW_REASON_REASSOC_RES_RECV:
2520 	case WOW_REASON_BEACON_RECV:
2521 	case WOW_REASON_ACTION_FRAME_RECV:
2522 		/* management frame case */
2523 		wma_wow_dump_mgmt_buffer(packet, packet_len);
2524 		break;
2525 
2526 	case WOW_REASON_BPF_ALLOW:
2527 	case WOW_REASON_PATTERN_MATCH_FOUND:
2528 	case WOW_REASON_RA_MATCH:
2529 	case WOW_REASON_RECV_MAGIC_PATTERN:
2530 		WMA_LOGD("Wake event packet:");
2531 		qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
2532 				   packet, packet_len);
2533 
2534 		vdev = &wma->interfaces[wake_info->vdev_id];
2535 		wma_wow_parse_data_pkt(&vdev->wow_stats, packet, packet_len);
2536 		break;
2537 
2538 	default:
2539 		WMA_LOGE("Wake reason %s(%u) is not a packet event",
2540 			 wma_wow_wake_reason_str(wake_info->wake_reason),
2541 			 wake_info->wake_reason);
2542 		return -EINVAL;
2543 	}
2544 
2545 	return 0;
2546 }
2547 
2548 static int wma_wake_event_no_payload(
2549 	t_wma_handle *wma,
2550 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param,
2551 	uint32_t length)
2552 {
2553 	WOW_EVENT_INFO_fixed_param *wake_info = event_param->fixed_param;
2554 
2555 	switch (wake_info->wake_reason) {
2556 	case WOW_REASON_HOST_AUTO_SHUTDOWN:
2557 		return wma_wake_reason_auto_shutdown();
2558 
2559 	case WOW_REASON_NLOD:
2560 		return wma_wake_reason_nlod(wma, wake_info->vdev_id);
2561 
2562 	default:
2563 		return 0;
2564 	}
2565 }
2566 
2567 static int wma_wake_event_piggybacked(
2568 	t_wma_handle *wma,
2569 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param,
2570 	uint32_t length)
2571 {
2572 	int errno = 0;
2573 	void *pb_event;
2574 	uint32_t pb_event_len;
2575 	uint32_t wake_reason;
2576 	uint32_t event_id;
2577 
2578 	/*
2579 	 * There are "normal" cases where a wake reason that usually contains a
2580 	 * piggybacked event is empty. In these cases we just want to wake up,
2581 	 * and no action is needed. Bail out now if that is the case.
2582 	 */
2583 	if (!event_param->wow_packet_buffer ||
2584 	    event_param->num_wow_packet_buffer <= 4) {
2585 		WMA_LOGE("Invalid wow packet buffer from firmware %u",
2586 			 event_param->num_wow_packet_buffer);
2587 		return 0;
2588 	}
2589 
2590 	wake_reason = event_param->fixed_param->wake_reason;
2591 
2592 	/* parse piggybacked event from param buffer */
2593 	{
2594 		int ret_code;
2595 		uint8_t *pb_event_buf;
2596 		uint32_t tag;
2597 
2598 		/* first 4 bytes are the length, followed by the buffer */
2599 		pb_event_len = *(uint32_t *)event_param->wow_packet_buffer;
2600 		if (pb_event_len > (event_param->num_wow_packet_buffer - 4)) {
2601 			WMA_LOGE("Invalid pb_event_len from firmware, pb_event_len: %u, num_wow_packet_buffer: %u",
2602 				 pb_event_len,
2603 				 event_param->num_wow_packet_buffer);
2604 			return -EINVAL;
2605 		}
2606 		pb_event_buf = event_param->wow_packet_buffer + 4;
2607 
2608 		WMA_LOGD("piggybacked event buffer:");
2609 		qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
2610 				   pb_event_buf, pb_event_len);
2611 
2612 		tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(pb_event_buf));
2613 		event_id = wow_get_wmi_eventid(wake_reason, tag);
2614 		if (!event_id) {
2615 			WMA_LOGE(FL("Unable to find Event Id"));
2616 			return -EINVAL;
2617 		}
2618 
2619 		ret_code = wmitlv_check_and_pad_event_tlvs(wma, pb_event_buf,
2620 							   pb_event_len,
2621 							   event_id, &pb_event);
2622 		if (ret_code) {
2623 			WMA_LOGE(FL("Bad TLVs; len:%d, event_id:%d, status:%d"),
2624 				 pb_event_len, event_id, ret_code);
2625 			return -EINVAL;
2626 		}
2627 	}
2628 
2629 	switch (wake_reason) {
2630 	case WOW_REASON_AP_ASSOC_LOST:
2631 		errno = wma_wake_reason_ap_assoc_lost(wma, pb_event,
2632 						      pb_event_len);
2633 		break;
2634 
2635 #ifdef FEATURE_WLAN_SCAN_PNO
2636 	case WOW_REASON_NLO_SCAN_COMPLETE:
2637 		errno = target_if_nlo_complete_handler(wma, pb_event,
2638 						       pb_event_len);
2639 		break;
2640 #endif /* FEATURE_WLAN_SCAN_PNO */
2641 
2642 	case WOW_REASON_CSA_EVENT:
2643 		errno = wma_csa_offload_handler(wma, pb_event, pb_event_len);
2644 		break;
2645 
2646 	/*
2647 	 * WOW_REASON_LOW_RSSI is used for following roaming events -
2648 	 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS,
2649 	 * WMI_ROAM_REASON_SUITABLE_AP will be handled by
2650 	 * wma_roam_event_callback().
2651 	 * WOW_REASON_ROAM_HO is associated with
2652 	 * WMI_ROAM_REASON_HO_FAILED event and it will be handled by
2653 	 * wma_roam_event_callback().
2654 	 */
2655 	case WOW_REASON_LOW_RSSI:
2656 	case WOW_REASON_ROAM_HO:
2657 		wlan_roam_debug_log(event_param->fixed_param->vdev_id,
2658 				    DEBUG_WOW_ROAM_EVENT,
2659 				    DEBUG_INVALID_PEER_ID,
2660 				    NULL, NULL, wake_reason,
2661 				    pb_event_len);
2662 		if (pb_event_len > 0) {
2663 			errno = wma_roam_event_callback(wma, pb_event,
2664 							pb_event_len);
2665 		} else {
2666 			/*
2667 			 * No wow_packet_buffer means a better AP beacon
2668 			 * will follow in a later event.
2669 			 */
2670 			WMA_LOGD("Host woken up because of better AP beacon");
2671 		}
2672 		break;
2673 
2674 	case WOW_REASON_CLIENT_KICKOUT_EVENT:
2675 		errno = wma_peer_sta_kickout_event_handler(wma, pb_event,
2676 							   pb_event_len);
2677 		break;
2678 
2679 #ifdef FEATURE_WLAN_EXTSCAN
2680 	case WOW_REASON_EXTSCAN:
2681 		errno = wma_extscan_wow_event_callback(wma, pb_event,
2682 						       pb_event_len);
2683 		break;
2684 #endif
2685 
2686 	case WOW_REASON_RSSI_BREACH_EVENT:
2687 		errno = wma_rssi_breached_event_handler(wma, pb_event,
2688 							pb_event_len);
2689 		break;
2690 
2691 	case WOW_REASON_NAN_EVENT:
2692 		errno = wma_nan_rsp_event_handler(wma, pb_event, pb_event_len);
2693 		break;
2694 
2695 	case WOW_REASON_NAN_DATA:
2696 		errno = wma_ndp_wow_event_callback(wma, pb_event, pb_event_len,
2697 						   event_id);
2698 		break;
2699 
2700 #ifdef FEATURE_WLAN_TDLS
2701 	case WOW_REASON_TDLS_CONN_TRACKER_EVENT:
2702 		errno = wma_tdls_event_handler(wma, pb_event, pb_event_len);
2703 		break;
2704 #endif
2705 
2706 	case WOW_REASON_TIMER_INTR_RECV:
2707 		/*
2708 		 * Right now firmware is not returning any cookie host has
2709 		 * programmed. So do not check for cookie.
2710 		 */
2711 		WMA_LOGE("WOW_REASON_TIMER_INTR_RECV received, indicating key exchange did not finish. Initiate disconnect");
2712 		errno = wma_peer_sta_kickout_event_handler(wma, pb_event,
2713 							   pb_event_len);
2714 		break;
2715 
2716 	default:
2717 		WMA_LOGE("Wake reason %s(%u) is not a piggybacked event",
2718 			 wma_wow_wake_reason_str(wake_reason), wake_reason);
2719 		errno = -EINVAL;
2720 		break;
2721 	}
2722 
2723 	wmitlv_free_allocated_event_tlvs(event_id, &pb_event);
2724 
2725 	return errno;
2726 }
2727 
2728 static void wma_wake_event_log_reason(t_wma_handle *wma,
2729 				      WOW_EVENT_INFO_fixed_param *wake_info)
2730 {
2731 	struct wma_txrx_node *vdev;
2732 
2733 	/* "Unspecified" means APPS triggered wake, else firmware triggered */
2734 	if (wake_info->wake_reason != WOW_REASON_UNSPECIFIED) {
2735 		vdev = &wma->interfaces[wake_info->vdev_id];
2736 		WMA_LOGA("WLAN triggered wakeup: %s (%d), vdev: %d (%s)",
2737 			 wma_wow_wake_reason_str(wake_info->wake_reason),
2738 			 wake_info->wake_reason,
2739 			 wake_info->vdev_id,
2740 			 wma_vdev_type_str(vdev->type));
2741 	} else if (!wmi_get_runtime_pm_inprogress(wma->wmi_handle)) {
2742 		WMA_LOGA("Non-WLAN triggered wakeup: %s (%d)",
2743 			 wma_wow_wake_reason_str(wake_info->wake_reason),
2744 			 wake_info->wake_reason);
2745 	}
2746 
2747 	qdf_wow_wakeup_host_event(wake_info->wake_reason);
2748 	qdf_wma_wow_wakeup_stats_event(wma);
2749 }
2750 
2751 /**
2752  * wma_wow_wakeup_host_event() - wakeup host event handler
2753  * @handle: wma handle
2754  * @event: event data
2755  * @len: buffer length
2756  *
2757  * Handler to catch wow wakeup host event. This event will have
2758  * reason why the firmware has woken the host.
2759  *
2760  * Return: Errno
2761  */
2762 int wma_wow_wakeup_host_event(void *handle, uint8_t *event, uint32_t len)
2763 {
2764 	int errno;
2765 	t_wma_handle *wma = handle;
2766 	WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param;
2767 	WOW_EVENT_INFO_fixed_param *wake_info;
2768 
2769 	event_param = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *)event;
2770 	if (!event_param) {
2771 		WMA_LOGE("Wake event data is null");
2772 		return -EINVAL;
2773 	}
2774 
2775 	wake_info = event_param->fixed_param;
2776 
2777 	if (wake_info->vdev_id >= wma->max_bssid) {
2778 		WMA_LOGE("%s: received invalid vdev_id %d",
2779 			 __func__, wake_info->vdev_id);
2780 		return -EINVAL;
2781 	}
2782 
2783 	wma_wake_event_log_reason(wma, wake_info);
2784 
2785 	pmo_ucfg_psoc_wakeup_host_event_received(wma->psoc);
2786 
2787 	wma_print_wow_stats(wma, wake_info);
2788 
2789 	/* split based on payload type */
2790 	if (is_piggybacked_event(wake_info->wake_reason))
2791 		errno = wma_wake_event_piggybacked(wma, event_param, len);
2792 	else if (event_param->wow_packet_buffer)
2793 		errno = wma_wake_event_packet(wma, event_param, len);
2794 	else
2795 		errno = wma_wake_event_no_payload(wma, event_param, len);
2796 
2797 	wma_inc_wow_stats(wma, wake_info);
2798 	wma_print_wow_stats(wma, wake_info);
2799 
2800 	wma_acquire_wow_wakelock(wma, wake_info->wake_reason);
2801 
2802 	return errno;
2803 }
2804 
2805 #ifdef FEATURE_WLAN_D0WOW
2806 /**
2807  * wma_d0_wow_disable_ack_event() - wakeup host event handler
2808  * @handle: wma handle
2809  * @event: event data
2810  * @len: buffer length
2811  *
2812  * Handler to catch D0-WOW disable ACK event.  This event will have
2813  * reason why the firmware has woken the host.
2814  * This is for backward compatible with cld2.0.
2815  *
2816  * Return: 0 for success or error
2817  */
2818 int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len)
2819 {
2820 	tp_wma_handle wma = (tp_wma_handle)handle;
2821 	WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *param_buf;
2822 	wmi_d0_wow_disable_ack_event_fixed_param *resp_data;
2823 
2824 	param_buf = (WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *)event;
2825 	if (!param_buf) {
2826 		WMA_LOGE("Invalid D0-WOW disable ACK event buffer!");
2827 		return -EINVAL;
2828 	}
2829 
2830 	resp_data = param_buf->fixed_param;
2831 
2832 	pmo_ucfg_psoc_wakeup_host_event_received(wma->psoc);
2833 
2834 	WMA_LOGD("Received D0-WOW disable ACK");
2835 
2836 	return 0;
2837 }
2838 #else
2839 int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len)
2840 {
2841 	return 0;
2842 }
2843 #endif
2844 
2845 /**
2846  * wma_pdev_resume_event_handler() - PDEV resume event handler
2847  * @handle: wma handle
2848  * @event: event data
2849  * @len: buffer length
2850  *
2851  * Return: 0 for success or error
2852  */
2853 int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len)
2854 {
2855 	tp_wma_handle wma = (tp_wma_handle) handle;
2856 
2857 	WMA_LOGA("Received PDEV resume event");
2858 
2859 	pmo_ucfg_psoc_wakeup_host_event_received(wma->psoc);
2860 
2861 	return 0;
2862 }
2863 
2864 /**
2865  * wma_wow_enter() - store enable/disable status for pattern
2866  * @wma: wma handle
2867  * @info: wow parameters
2868  *
2869  * Records pattern enable/disable status locally. This choice will
2870  * take effect when the driver enter into suspend state.
2871  *
2872  * Return: QDF status
2873  */
2874 QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info)
2875 {
2876 	return QDF_STATUS_SUCCESS;
2877 }
2878 
2879 /**
2880  * wma_wow_exit() - clear all wma states
2881  * @wma: wma handle
2882  * @info: wow params
2883  *
2884  * Return: QDF status
2885  */
2886 QDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
2887 {
2888 	return QDF_STATUS_SUCCESS;
2889 }
2890 
2891 /**
2892  * wma_del_ts_req() - send DELTS request to fw
2893  * @wma: wma handle
2894  * @msg: delts params
2895  *
2896  * Return: none
2897  */
2898 void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg)
2899 {
2900 	if (wmi_unified_del_ts_cmd(wma->wmi_handle,
2901 				 msg->sessionId,
2902 				 TID_TO_WME_AC(msg->userPrio))) {
2903 		WMA_LOGP("%s: Failed to send vdev DELTS command", __func__);
2904 	}
2905 
2906 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2907 	if (msg->setRICparams == true)
2908 		wma_set_ric_req(wma, msg, false);
2909 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2910 	qdf_mem_free(msg);
2911 }
2912 
2913 /**
2914  * wma_aggr_qos_req() - send aggr qos request to fw
2915  * @wma: handle to wma
2916  * @pAggrQosRspMsg - combined struct for all ADD_TS requests.
2917  *
2918  * A function to handle WMA_AGGR_QOS_REQ. This will send out
2919  * ADD_TS requestes to firmware in loop for all the ACs with
2920  * active flow.
2921  *
2922  * Return: none
2923  */
2924 void wma_aggr_qos_req(tp_wma_handle wma,
2925 		      tAggrAddTsParams *pAggrQosRspMsg)
2926 {
2927 	wmi_unified_aggr_qos_cmd(wma->wmi_handle,
2928 			   (struct aggr_add_ts_param *)pAggrQosRspMsg);
2929 	/* send reponse to upper layers from here only. */
2930 	wma_send_msg_high_priority(wma, WMA_AGGR_QOS_RSP, pAggrQosRspMsg, 0);
2931 }
2932 
2933 #ifdef FEATURE_WLAN_ESE
2934 /**
2935  * wma_set_tsm_interval() - Set TSM interval
2936  * @req: pointer to ADDTS request
2937  *
2938  * Return: QDF_STATUS_E_FAILURE or QDF_STATUS_SUCCESS
2939  */
2940 static QDF_STATUS wma_set_tsm_interval(tAddTsParams *req)
2941 {
2942 	/*
2943 	 * msmt_interval is in unit called TU (1 TU = 1024 us)
2944 	 * max value of msmt_interval cannot make resulting
2945 	 * interval_milliseconds overflow 32 bit
2946 	 *
2947 	 */
2948 	uint32_t interval_milliseconds;
2949 	struct cdp_pdev *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
2950 
2951 	if (NULL == pdev) {
2952 		WMA_LOGE("%s: Failed to get pdev", __func__);
2953 		return QDF_STATUS_E_FAILURE;
2954 	}
2955 
2956 	interval_milliseconds = (req->tsm_interval * 1024) / 1000;
2957 
2958 	cdp_tx_set_compute_interval(cds_get_context(QDF_MODULE_ID_SOC),
2959 			pdev,
2960 			interval_milliseconds);
2961 	return QDF_STATUS_SUCCESS;
2962 }
2963 #else
2964 static inline QDF_STATUS wma_set_tsm_interval(tAddTsParams *req)
2965 {
2966 	return QDF_STATUS_SUCCESS;
2967 }
2968 #endif /* FEATURE_WLAN_ESE */
2969 
2970 /**
2971  * wma_add_ts_req() - send ADDTS request to fw
2972  * @wma: wma handle
2973  * @msg: ADDTS params
2974  *
2975  * Return: none
2976  */
2977 void wma_add_ts_req(tp_wma_handle wma, tAddTsParams *msg)
2978 {
2979 	struct add_ts_param cmd = {0};
2980 
2981 	msg->status = QDF_STATUS_SUCCESS;
2982 	if (wma_set_tsm_interval(msg) == QDF_STATUS_SUCCESS) {
2983 
2984 		cmd.sme_session_id = msg->sme_session_id;
2985 		cmd.tspec.tsinfo.traffic.userPrio =
2986 			TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio);
2987 		cmd.tspec.mediumTime = msg->tspec.mediumTime;
2988 		if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd))
2989 			msg->status = QDF_STATUS_E_FAILURE;
2990 
2991 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2992 		if (msg->setRICparams == true)
2993 			wma_set_ric_req(wma, msg, true);
2994 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
2995 
2996 	}
2997 	wma_send_msg_high_priority(wma, WMA_ADD_TS_RSP, msg, 0);
2998 }
2999 
3000 #ifdef FEATURE_WLAN_ESE
3001 
3002 #define TSM_DELAY_HISTROGRAM_BINS 4
3003 /**
3004  * wma_process_tsm_stats_req() - process tsm stats request
3005  * @wma_handler - handle to wma
3006  * @pTsmStatsMsg - TSM stats struct that needs to be populated and
3007  *         passed in message.
3008  *
3009  * A parallel function to WMA_ProcessTsmStatsReq for pronto. This
3010  * function fetches stats from data path APIs and post
3011  * WMA_TSM_STATS_RSP msg back to LIM.
3012  *
3013  * Return: QDF status
3014  */
3015 QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler,
3016 				     void *pTsmStatsMsg)
3017 {
3018 	uint8_t counter;
3019 	uint32_t queue_delay_microsec = 0;
3020 	uint32_t tx_delay_microsec = 0;
3021 	uint16_t packet_count = 0;
3022 	uint16_t packet_loss_count = 0;
3023 	tpAniTrafStrmMetrics pTsmMetric = NULL;
3024 	tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg;
3025 	tpAniGetTsmStatsRsp pTsmRspParams = NULL;
3026 	int tid = pStats->tid;
3027 	/*
3028 	 * The number of histrogram bin report by data path api are different
3029 	 * than required by TSM, hence different (6) size array used
3030 	 */
3031 	uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, };
3032 	struct cdp_pdev *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
3033 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3034 
3035 	if (NULL == pdev) {
3036 		WMA_LOGE("%s: Failed to get pdev", __func__);
3037 		qdf_mem_free(pTsmStatsMsg);
3038 		return QDF_STATUS_E_INVAL;
3039 	}
3040 
3041 	/* get required values from data path APIs */
3042 	cdp_tx_delay(soc,
3043 		pdev,
3044 		&queue_delay_microsec,
3045 		&tx_delay_microsec, tid);
3046 	cdp_tx_delay_hist(soc,
3047 		pdev,
3048 		bin_values, tid);
3049 	cdp_tx_packet_count(soc,
3050 		pdev,
3051 		&packet_count,
3052 		&packet_loss_count, tid);
3053 
3054 	pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams));
3055 	if (NULL == pTsmRspParams) {
3056 		QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
3057 			  "%s: QDF MEM Alloc Failure", __func__);
3058 		QDF_ASSERT(0);
3059 		qdf_mem_free(pTsmStatsMsg);
3060 		return QDF_STATUS_E_NOMEM;
3061 	}
3062 	pTsmRspParams->staId = pStats->staId;
3063 	pTsmRspParams->rc = eSIR_FAILURE;
3064 	pTsmRspParams->tsmStatsReq = pStats;
3065 	pTsmMetric = &pTsmRspParams->tsmMetrics;
3066 	/* populate pTsmMetric */
3067 	pTsmMetric->UplinkPktQueueDly = queue_delay_microsec;
3068 	/* store only required number of bin values */
3069 	for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) {
3070 		pTsmMetric->UplinkPktQueueDlyHist[counter] =
3071 			bin_values[counter];
3072 	}
3073 	pTsmMetric->UplinkPktTxDly = tx_delay_microsec;
3074 	pTsmMetric->UplinkPktLoss = packet_loss_count;
3075 	pTsmMetric->UplinkPktCount = packet_count;
3076 
3077 	/*
3078 	 * No need to populate roaming delay and roaming count as they are
3079 	 * being populated just before sending IAPP frame out
3080 	 */
3081 	/* post this message to LIM/PE */
3082 	wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0);
3083 	return QDF_STATUS_SUCCESS;
3084 }
3085 
3086 #endif /* FEATURE_WLAN_ESE */
3087 
3088 /**
3089  * wma_process_mcbc_set_filter_req() - process mcbc set filter request
3090  * @wma_handle: wma handle
3091  * @mcbc_param: mcbc params
3092  *
3093  * Return: QDF status
3094  */
3095 QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
3096 					   tSirRcvFltMcAddrList *mcbc_param)
3097 {
3098 	return QDF_STATUS_SUCCESS;
3099 }
3100 
3101 /**
3102  * wma_process_cesium_enable_ind() - enables cesium functionality in target
3103  * @wma: wma handle
3104  *
3105  * Return: QDF status
3106  */
3107 QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
3108 {
3109 	QDF_STATUS ret;
3110 	int32_t vdev_id;
3111 
3112 	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
3113 	if (vdev_id < 0) {
3114 		WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
3115 			 __func__);
3116 		return QDF_STATUS_E_FAILURE;
3117 	}
3118 
3119 	/* Send enable cesium command to target */
3120 	WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
3121 	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
3122 				 WMI_VDEV_PARAM_ENABLE_RMC, 1);
3123 	if (ret) {
3124 		WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
3125 		return QDF_STATUS_E_FAILURE;
3126 	}
3127 	return QDF_STATUS_SUCCESS;
3128 }
3129 
3130 /**
3131  * wma_process_get_peer_info_req() - sends get peer info cmd to target
3132  * @wma: wma handle
3133  * @preq: get peer info request
3134  *
3135  * Return: QDF status
3136  */
3137 QDF_STATUS wma_process_get_peer_info_req
3138 	(tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
3139 {
3140 	int32_t ret;
3141 	uint8_t *p;
3142 	uint16_t len;
3143 	wmi_buf_t buf;
3144 	int32_t vdev_id;
3145 	struct cdp_pdev *pdev;
3146 	void *peer;
3147 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3148 	uint8_t peer_mac[IEEE80211_ADDR_LEN];
3149 	uint8_t *peer_mac_raw;
3150 	wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
3151 	uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
3152 						  0xff, 0xff, 0xff };
3153 
3154 	if (NULL == soc) {
3155 		WMA_LOGE("%s: SOC context is NULL", __func__);
3156 		return QDF_STATUS_E_FAILURE;
3157 	}
3158 
3159 	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
3160 	if (vdev_id < 0) {
3161 		WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
3162 			 __func__);
3163 		return QDF_STATUS_E_FAILURE;
3164 	}
3165 
3166 	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
3167 	if (NULL == pdev) {
3168 		WMA_LOGE("%s: Failed to get pdev context", __func__);
3169 		return QDF_STATUS_E_FAILURE;
3170 	}
3171 
3172 	if (0xFF == pReq->staIdx) {
3173 		/*get info for all peers */
3174 		qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
3175 	} else {
3176 		/*get info for a single peer */
3177 		peer = cdp_peer_find_by_local_id(soc,
3178 				pdev, pReq->staIdx);
3179 		if (!peer) {
3180 			WMA_LOGE("%s: Failed to get peer handle using peer id %d",
3181 				__func__, pReq->staIdx);
3182 			return QDF_STATUS_E_FAILURE;
3183 		}
3184 		peer_mac_raw = cdp_peer_get_peer_mac_addr(soc, peer);
3185 		if (peer_mac_raw == NULL) {
3186 			WMA_LOGE("peer_mac_raw is NULL");
3187 			return QDF_STATUS_E_FAILURE;
3188 		}
3189 
3190 		WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
3191 			__func__, pReq->staIdx, peer_mac_raw[0],
3192 			peer_mac_raw[1], peer_mac_raw[2],
3193 			peer_mac_raw[3], peer_mac_raw[4],
3194 			peer_mac_raw[5]);
3195 		qdf_mem_copy(peer_mac, peer_mac_raw, IEEE80211_ADDR_LEN);
3196 	}
3197 
3198 	len = sizeof(wmi_peer_info_req_cmd_fixed_param);
3199 	buf = wmi_buf_alloc(wma->wmi_handle, len);
3200 	if (!buf) {
3201 		WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
3202 		return QDF_STATUS_E_FAILURE;
3203 	}
3204 
3205 	p = (uint8_t *) wmi_buf_data(buf);
3206 	qdf_mem_zero(p, len);
3207 	p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
3208 
3209 	WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
3210 		       WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
3211 		       WMITLV_GET_STRUCT_TLVLEN
3212 			       (wmi_peer_info_req_cmd_fixed_param));
3213 
3214 	p_get_peer_info_cmd->vdev_id = vdev_id;
3215 	WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
3216 				   &p_get_peer_info_cmd->peer_mac_address);
3217 
3218 	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3219 				   WMI_PEER_INFO_REQ_CMDID);
3220 	if (ret != QDF_STATUS_SUCCESS)
3221 		wmi_buf_free(buf);
3222 
3223 	WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d command id: %d, status: %d",
3224 		len, vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
3225 
3226 	return QDF_STATUS_SUCCESS;
3227 }
3228 
3229 /**
3230  * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
3231  * @wma: wma handle
3232  * @pReq: tx fail monitor command params
3233  *
3234  * Return: QDF status
3235  */
3236 QDF_STATUS wma_process_tx_fail_monitor_ind(tp_wma_handle wma,
3237 					tAniTXFailMonitorInd *pReq)
3238 {
3239 	QDF_STATUS ret;
3240 	int32_t vdev_id;
3241 
3242 	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
3243 	if (vdev_id < 0) {
3244 		WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail monitor indication message to target",
3245 			__func__);
3246 		return QDF_STATUS_E_FAILURE;
3247 	}
3248 
3249 	/* Send enable cesium command to target */
3250 	WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
3251 		vdev_id, pReq->tx_fail_count);
3252 
3253 	if (pReq->tx_fail_count == 0)
3254 		wma->hddTxFailCb = NULL;
3255 	else
3256 		wma->hddTxFailCb = pReq->txFailIndCallback;
3257 	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
3258 				 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
3259 				 pReq->tx_fail_count);
3260 	if (ret) {
3261 		WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
3262 		return QDF_STATUS_E_FAILURE;
3263 	}
3264 
3265 	return QDF_STATUS_SUCCESS;
3266 }
3267 
3268 /**
3269  * wma_process_rmc_enable_ind() - enables RMC functionality in target
3270  * @wma: wma handle
3271  *
3272  * Return: QDF status
3273  */
3274 QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
3275 {
3276 	int ret;
3277 	uint8_t *p;
3278 	uint16_t len;
3279 	wmi_buf_t buf;
3280 	int32_t vdev_id;
3281 	wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
3282 
3283 	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
3284 	if (vdev_id < 0) {
3285 		WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
3286 			 __func__);
3287 		return QDF_STATUS_E_FAILURE;
3288 	}
3289 
3290 	len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
3291 	buf = wmi_buf_alloc(wma->wmi_handle, len);
3292 	if (!buf) {
3293 		WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
3294 		return QDF_STATUS_E_FAILURE;
3295 	}
3296 
3297 	p = (uint8_t *) wmi_buf_data(buf);
3298 	qdf_mem_zero(p, len);
3299 	p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
3300 
3301 	WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
3302 		       WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
3303 		       WMITLV_GET_STRUCT_TLVLEN
3304 			       (wmi_rmc_set_mode_cmd_fixed_param));
3305 
3306 	p_rmc_enable_cmd->vdev_id = vdev_id;
3307 	p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
3308 
3309 	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3310 				   WMI_RMC_SET_MODE_CMDID);
3311 	if (ret != QDF_STATUS_SUCCESS)
3312 		wmi_buf_free(buf);
3313 
3314 	WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d command id: %d, status: %d",
3315 		 len, vdev_id, WMI_RMC_SET_MODE_CMDID, ret);
3316 
3317 	return QDF_STATUS_SUCCESS;
3318 }
3319 
3320 /**
3321  * wma_process_rmc_disable_ind() - disables rmc functionality in target
3322  * @wma: wma handle
3323  *
3324  * Return: QDF status
3325  */
3326 QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
3327 {
3328 	int ret;
3329 	uint8_t *p;
3330 	uint16_t len;
3331 	wmi_buf_t buf;
3332 	int32_t vdev_id;
3333 	wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
3334 
3335 	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
3336 	if (vdev_id < 0) {
3337 		WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
3338 			 __func__);
3339 		return QDF_STATUS_E_FAILURE;
3340 	}
3341 
3342 	len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
3343 	buf = wmi_buf_alloc(wma->wmi_handle, len);
3344 	if (!buf) {
3345 		WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
3346 		return QDF_STATUS_E_FAILURE;
3347 	}
3348 
3349 	p = (uint8_t *) wmi_buf_data(buf);
3350 	qdf_mem_zero(p, len);
3351 	p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
3352 
3353 	WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
3354 		       WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
3355 		       WMITLV_GET_STRUCT_TLVLEN
3356 			       (wmi_rmc_set_mode_cmd_fixed_param));
3357 
3358 	p_rmc_disable_cmd->vdev_id = vdev_id;
3359 	p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
3360 
3361 	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3362 				   WMI_RMC_SET_MODE_CMDID);
3363 	if (ret != QDF_STATUS_SUCCESS)
3364 		wmi_buf_free(buf);
3365 
3366 	WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d command id: %d, status: %d",
3367 		 len, vdev_id, WMI_RMC_SET_MODE_CMDID, ret);
3368 
3369 	return QDF_STATUS_SUCCESS;
3370 }
3371 
3372 /**
3373  * wma_process_rmc_action_period_ind() - sends RMC action period to target
3374  * @wma: wma handle
3375  *
3376  * Return: QDF status
3377  */
3378 QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
3379 {
3380 	int ret;
3381 	uint8_t *p;
3382 	uint16_t len;
3383 	uint32_t periodicity_msec;
3384 	wmi_buf_t buf;
3385 	int32_t vdev_id;
3386 	wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
3387 	struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
3388 
3389 	if (NULL == mac) {
3390 		WMA_LOGE("%s: MAC mac does not exist", __func__);
3391 		return QDF_STATUS_E_FAILURE;
3392 	}
3393 
3394 	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
3395 	if (vdev_id < 0) {
3396 		WMA_LOGE("%s: IBSS vdev does not exist could not send RMC action period to target",
3397 			 __func__);
3398 		return QDF_STATUS_E_FAILURE;
3399 	}
3400 
3401 	len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
3402 	buf = wmi_buf_alloc(wma->wmi_handle, len);
3403 	if (!buf) {
3404 		WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
3405 		return QDF_STATUS_E_FAILURE;
3406 	}
3407 
3408 	p = (uint8_t *) wmi_buf_data(buf);
3409 	qdf_mem_zero(p, len);
3410 	p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
3411 
3412 	WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
3413 		       WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
3414 		       WMITLV_GET_STRUCT_TLVLEN
3415 			       (wmi_rmc_set_action_period_cmd_fixed_param));
3416 
3417 	if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
3418 			     &periodicity_msec) != eSIR_SUCCESS) {
3419 		WMA_LOGE("Failed to get value for RMC action period using default");
3420 		periodicity_msec = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
3421 	}
3422 
3423 	p_rmc_cmd->vdev_id = vdev_id;
3424 	p_rmc_cmd->periodicity_msec = periodicity_msec;
3425 
3426 	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3427 				   WMI_RMC_SET_ACTION_PERIOD_CMDID);
3428 	if (ret != QDF_STATUS_SUCCESS)
3429 		wmi_buf_free(buf);
3430 
3431 	WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d command id: %d, status: %d",
3432 		periodicity_msec, len, vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID,
3433 		ret);
3434 
3435 	return QDF_STATUS_SUCCESS;
3436 }
3437 
3438 /**
3439  * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
3440  * @handle: wma handle
3441  * @pAddPeriodicTxPtrnParams: tx ptrn params
3442  *
3443  * Retrun: QDF status
3444  */
3445 QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
3446 						tSirAddPeriodicTxPtrn *
3447 						pAddPeriodicTxPtrnParams)
3448 {
3449 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
3450 	struct periodic_tx_pattern *params_ptr;
3451 	uint8_t vdev_id;
3452 	QDF_STATUS status;
3453 
3454 	if (!wma_handle || !wma_handle->wmi_handle) {
3455 		WMA_LOGE("%s: WMA is closed, can not issue fw add pattern cmd",
3456 			 __func__);
3457 		return QDF_STATUS_E_INVAL;
3458 	}
3459 
3460 	params_ptr = qdf_mem_malloc(sizeof(*params_ptr));
3461 
3462 	if (!params_ptr) {
3463 		WMA_LOGE(
3464 			"%s: unable to allocate memory for periodic_tx_pattern",
3465 			 __func__);
3466 		return QDF_STATUS_E_NOMEM;
3467 	}
3468 
3469 	if (!wma_find_vdev_by_addr(wma_handle,
3470 				   pAddPeriodicTxPtrnParams->mac_address.bytes,
3471 				   &vdev_id)) {
3472 		WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
3473 			 pAddPeriodicTxPtrnParams->mac_address.bytes);
3474 		return QDF_STATUS_E_INVAL;
3475 	}
3476 
3477 	params_ptr->ucPtrnId = pAddPeriodicTxPtrnParams->ucPtrnId;
3478 	params_ptr->ucPtrnSize = pAddPeriodicTxPtrnParams->ucPtrnSize;
3479 	params_ptr->usPtrnIntervalMs =
3480 				pAddPeriodicTxPtrnParams->usPtrnIntervalMs;
3481 	qdf_mem_copy(&params_ptr->mac_address,
3482 			&pAddPeriodicTxPtrnParams->mac_address,
3483 			sizeof(struct qdf_mac_addr));
3484 	qdf_mem_copy(params_ptr->ucPattern,
3485 			pAddPeriodicTxPtrnParams->ucPattern,
3486 			params_ptr->ucPtrnSize);
3487 
3488 	status =  wmi_unified_process_add_periodic_tx_ptrn_cmd(
3489 			wma_handle->wmi_handle,	params_ptr, vdev_id);
3490 
3491 	qdf_mem_free(params_ptr);
3492 	return status;
3493 }
3494 
3495 /**
3496  * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn
3497  * @handle: wma handle
3498  * @pDelPeriodicTxPtrnParams: tx ptrn params
3499  *
3500  * Retrun: QDF status
3501  */
3502 QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,
3503 						tSirDelPeriodicTxPtrn *
3504 						pDelPeriodicTxPtrnParams)
3505 {
3506 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
3507 	uint8_t vdev_id;
3508 
3509 	if (!wma_handle || !wma_handle->wmi_handle) {
3510 		WMA_LOGE("%s: WMA is closed, can not issue Del Pattern cmd",
3511 			 __func__);
3512 		return QDF_STATUS_E_INVAL;
3513 	}
3514 
3515 	if (!wma_find_vdev_by_addr(wma_handle,
3516 				   pDelPeriodicTxPtrnParams->mac_address.bytes,
3517 				   &vdev_id)) {
3518 		WMA_LOGE("%s: Failed to find vdev id for %pM", __func__,
3519 			 pDelPeriodicTxPtrnParams->mac_address.bytes);
3520 		return QDF_STATUS_E_INVAL;
3521 	}
3522 
3523 	return wmi_unified_process_del_periodic_tx_ptrn_cmd(
3524 				wma_handle->wmi_handle, vdev_id,
3525 				pDelPeriodicTxPtrnParams->ucPtrnId);
3526 }
3527 
3528 #ifdef WLAN_FEATURE_STATS_EXT
3529 /**
3530  * wma_stats_ext_req() - request ext stats from fw
3531  * @wma_ptr: wma handle
3532  * @preq: stats ext params
3533  *
3534  * Return: QDF status
3535  */
3536 QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq)
3537 {
3538 	tp_wma_handle wma = (tp_wma_handle) wma_ptr;
3539 	struct stats_ext_params *params;
3540 	size_t params_len;
3541 	QDF_STATUS status;
3542 
3543 	if (!wma) {
3544 		WMA_LOGE("%s: wma handle is NULL", __func__);
3545 		return QDF_STATUS_E_FAILURE;
3546 	}
3547 
3548 	params_len = sizeof(*params) + preq->request_data_len;
3549 	params = qdf_mem_malloc(params_len);
3550 
3551 	if (params == NULL) {
3552 		WMA_LOGE(FL("memory allocation failed"));
3553 		return QDF_STATUS_E_NOMEM;
3554 	}
3555 
3556 	params->vdev_id = preq->vdev_id;
3557 	params->request_data_len = preq->request_data_len;
3558 	if (preq->request_data_len > 0)
3559 		qdf_mem_copy(params->request_data, preq->request_data,
3560 			     params->request_data_len);
3561 
3562 	status = wmi_unified_stats_ext_req_cmd(wma->wmi_handle, params);
3563 	qdf_mem_free(params);
3564 
3565 	return status;
3566 }
3567 
3568 #endif /* WLAN_FEATURE_STATS_EXT */
3569 
3570 #ifdef WLAN_FEATURE_EXTWOW_SUPPORT
3571 /**
3572  * wma_send_status_of_ext_wow() - send ext wow status to SME
3573  * @wma: wma handle
3574  * @status: status
3575  *
3576  * Return: none
3577  */
3578 static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status)
3579 {
3580 	tSirReadyToExtWoWInd *ready_to_extwow;
3581 	QDF_STATUS vstatus;
3582 	struct scheduler_msg message = {0};
3583 	uint8_t len;
3584 
3585 	WMA_LOGD("Posting ready to suspend indication to umac");
3586 
3587 	len = sizeof(tSirReadyToExtWoWInd);
3588 	ready_to_extwow = (tSirReadyToExtWoWInd *) qdf_mem_malloc(len);
3589 
3590 	if (NULL == ready_to_extwow) {
3591 		WMA_LOGE("%s: Memory allocation failure", __func__);
3592 		return;
3593 	}
3594 
3595 	ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND;
3596 	ready_to_extwow->mesgLen = len;
3597 	ready_to_extwow->status = status;
3598 
3599 	message.type = eWNI_SME_READY_TO_EXTWOW_IND;
3600 	message.bodyptr = (void *)ready_to_extwow;
3601 	message.bodyval = 0;
3602 
3603 	vstatus = scheduler_post_msg(QDF_MODULE_ID_SME, &message);
3604 	if (vstatus != QDF_STATUS_SUCCESS) {
3605 		WMA_LOGE("Failed to post ready to suspend");
3606 		qdf_mem_free(ready_to_extwow);
3607 	}
3608 }
3609 
3610 /**
3611  * wma_enable_ext_wow() - enable ext wow in fw
3612  * @wma: wma handle
3613  * @params: ext wow params
3614  *
3615  * Return:0 for success or error code
3616  */
3617 QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params)
3618 {
3619 	struct ext_wow_params wow_params = {0};
3620 	QDF_STATUS status;
3621 
3622 	if (!wma) {
3623 		WMA_LOGE("%s: wma handle is NULL", __func__);
3624 		return QDF_STATUS_E_FAILURE;
3625 	}
3626 
3627 	wow_params.vdev_id = params->vdev_id;
3628 	wow_params.type = (enum wmi_ext_wow_type) params->type;
3629 	wow_params.wakeup_pin_num = params->wakeup_pin_num;
3630 
3631 	status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle,
3632 				&wow_params);
3633 	if (QDF_IS_STATUS_ERROR(status))
3634 		return status;
3635 
3636 	wma_send_status_of_ext_wow(wma, true);
3637 	return status;
3638 
3639 }
3640 
3641 /**
3642  * wma_set_app_type1_params_in_fw() - set app type1 params in fw
3643  * @wma: wma handle
3644  * @appType1Params: app type1 params
3645  *
3646  * Return: QDF status
3647  */
3648 int wma_set_app_type1_params_in_fw(tp_wma_handle wma,
3649 				   tpSirAppType1Params appType1Params)
3650 {
3651 	int ret;
3652 
3653 	ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle,
3654 				   (struct app_type1_params *)appType1Params);
3655 	if (ret) {
3656 		WMA_LOGE("%s: Failed to set APP TYPE1 PARAMS", __func__);
3657 		return QDF_STATUS_E_FAILURE;
3658 	}
3659 
3660 	return QDF_STATUS_SUCCESS;
3661 }
3662 
3663 /**
3664  * wma_set_app_type2_params_in_fw() - set app type2 params in fw
3665  * @wma: wma handle
3666  * @appType2Params: app type2 params
3667  *
3668  * Return: QDF status
3669  */
3670 QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma,
3671 					  tpSirAppType2Params appType2Params)
3672 {
3673 	struct app_type2_params params = {0};
3674 
3675 	if (!wma) {
3676 		WMA_LOGE("%s: wma handle is NULL", __func__);
3677 		return QDF_STATUS_E_FAILURE;
3678 	}
3679 
3680 	params.vdev_id = appType2Params->vdev_id;
3681 	params.rc4_key_len = appType2Params->rc4_key_len;
3682 	qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16);
3683 	params.ip_id = appType2Params->ip_id;
3684 	params.ip_device_ip = appType2Params->ip_device_ip;
3685 	params.ip_server_ip = appType2Params->ip_server_ip;
3686 	params.tcp_src_port = appType2Params->tcp_src_port;
3687 	params.tcp_dst_port = appType2Params->tcp_dst_port;
3688 	params.tcp_seq = appType2Params->tcp_seq;
3689 	params.tcp_ack_seq = appType2Params->tcp_ack_seq;
3690 	params.keepalive_init = appType2Params->keepalive_init;
3691 	params.keepalive_min = appType2Params->keepalive_min;
3692 	params.keepalive_max = appType2Params->keepalive_max;
3693 	params.keepalive_inc = appType2Params->keepalive_inc;
3694 	params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
3695 	params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
3696 	qdf_mem_copy(&params.gateway_mac, &appType2Params->gateway_mac,
3697 			sizeof(struct qdf_mac_addr));
3698 
3699 	return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle,
3700 							&params);
3701 }
3702 #endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
3703 
3704 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
3705 /**
3706  * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger
3707  * @handle: wma handle
3708  * @event: event buffer
3709  * @len: buffer length
3710  *
3711  * Return: 0 for success or error code
3712  */
3713 int wma_auto_shutdown_event_handler(void *handle, uint8_t *event,
3714 				    uint32_t len)
3715 {
3716 	wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt;
3717 	WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf =
3718 		(WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *)
3719 		event;
3720 
3721 	if (!param_buf || !param_buf->fixed_param) {
3722 		WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
3723 			 __LINE__);
3724 		return -EINVAL;
3725 	}
3726 
3727 	wmi_auto_sh_evt = param_buf->fixed_param;
3728 
3729 	if (wmi_auto_sh_evt->shutdown_reason
3730 	    != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) {
3731 		WMA_LOGE("%s:%d: Invalid Auto shutdown timer evt", __func__,
3732 			 __LINE__);
3733 		return -EINVAL;
3734 	}
3735 
3736 	WMA_LOGD("%s:%d: Auto Shutdown Evt: %d", __func__, __LINE__,
3737 		 wmi_auto_sh_evt->shutdown_reason);
3738 	return wma_post_auto_shutdown_msg();
3739 }
3740 
3741 /**
3742  * wma_set_auto_shutdown_timer_req() - sets auto shutdown timer in firmware
3743  * @wma: wma handle
3744  * @auto_sh_cmd: auto shutdown timer value
3745  *
3746  * Return: QDF status
3747  */
3748 QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,
3749 						  tSirAutoShutdownCmdParams *
3750 						  auto_sh_cmd)
3751 {
3752 	if (auto_sh_cmd == NULL) {
3753 		WMA_LOGE("%s : Invalid Autoshutdown cfg cmd", __func__);
3754 		return QDF_STATUS_E_FAILURE;
3755 	}
3756 
3757 	return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle,
3758 					auto_sh_cmd->timer_val);
3759 }
3760 #endif /* FEATURE_WLAN_AUTO_SHUTDOWN */
3761 
3762 #ifdef WLAN_FEATURE_NAN
3763 /**
3764  * wma_nan_req() - to send nan request to target
3765  * @wma: wma_handle
3766  * @nan_req: request data which will be non-null
3767  *
3768  * Return: QDF status
3769  */
3770 QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req)
3771 {
3772 	tp_wma_handle wma_handle = (tp_wma_handle) wma_ptr;
3773 	struct nan_req_params *params;
3774 	size_t params_len;
3775 	QDF_STATUS status;
3776 
3777 	if (!wma_handle) {
3778 		WMA_LOGE("%s: wma handle is NULL", __func__);
3779 		return QDF_STATUS_E_FAILURE;
3780 	}
3781 
3782 	params_len = sizeof(*params) + nan_req->request_data_len;
3783 	params = qdf_mem_malloc(params_len);
3784 
3785 	if (params == NULL) {
3786 		WMA_LOGE(FL("memory allocation failed"));
3787 		return QDF_STATUS_E_NOMEM;
3788 	}
3789 
3790 	params->request_data_len = nan_req->request_data_len;
3791 	if (params->request_data_len > 0)
3792 		qdf_mem_copy(params->request_data, nan_req->request_data,
3793 			     params->request_data_len);
3794 
3795 	status = wmi_unified_nan_req_cmd(wma_handle->wmi_handle, params);
3796 	qdf_mem_free(params);
3797 
3798 	return status;
3799 }
3800 #endif /* WLAN_FEATURE_NAN */
3801 
3802 #ifdef DHCP_SERVER_OFFLOAD
3803 /**
3804  * wma_process_dhcpserver_offload() - enable DHCP server offload
3805  * @wma_handle: wma handle
3806  * @pDhcpSrvOffloadInfo: DHCP server offload info
3807  *
3808  * Return: 0 for success or error code
3809  */
3810 QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,
3811 					  tSirDhcpSrvOffloadInfo *
3812 					  pDhcpSrvOffloadInfo)
3813 {
3814 	struct dhcp_offload_info_params params = {0};
3815 	QDF_STATUS status;
3816 
3817 	if (!wma_handle) {
3818 		WMA_LOGE("%s: wma handle is NULL", __func__);
3819 		return -EIO;
3820 	}
3821 
3822 	params.vdev_id = pDhcpSrvOffloadInfo->vdev_id;
3823 	params.dhcp_offload_enabled =
3824 				pDhcpSrvOffloadInfo->dhcpSrvOffloadEnabled;
3825 	params.dhcp_client_num = pDhcpSrvOffloadInfo->dhcpClientNum;
3826 	params.dhcp_srv_addr = pDhcpSrvOffloadInfo->dhcpSrvIP;
3827 
3828 	status = wmi_unified_process_dhcpserver_offload_cmd(
3829 				wma_handle->wmi_handle, &params);
3830 	if (QDF_IS_STATUS_ERROR(status))
3831 		return status;
3832 
3833 	WMA_LOGD("Set dhcp server offload to vdevId %d",
3834 		 pDhcpSrvOffloadInfo->vdev_id);
3835 	return status;
3836 }
3837 #endif /* DHCP_SERVER_OFFLOAD */
3838 
3839 #ifdef WLAN_FEATURE_GPIO_LED_FLASHING
3840 /**
3841  * wma_set_led_flashing() - set led flashing in fw
3842  * @wma_handle: wma handle
3843  * @flashing: flashing request
3844  *
3845  * Return: QDF status
3846  */
3847 QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle,
3848 				struct flashing_req_params *flashing)
3849 {
3850 	QDF_STATUS status;
3851 
3852 	if (!wma_handle || !wma_handle->wmi_handle) {
3853 		WMA_LOGE(FL("WMA is closed, can not issue cmd"));
3854 		return QDF_STATUS_E_INVAL;
3855 	}
3856 	if (!flashing) {
3857 		WMA_LOGE(FL("invalid parameter: flashing"));
3858 		return QDF_STATUS_E_INVAL;
3859 	}
3860 	status = wmi_unified_set_led_flashing_cmd(wma_handle->wmi_handle,
3861 						  flashing);
3862 	return status;
3863 }
3864 #endif /* WLAN_FEATURE_GPIO_LED_FLASHING */
3865 
3866 #ifdef FEATURE_WLAN_CH_AVOID
3867 /**
3868  * wma_process_ch_avoid_update_req() - handles channel avoid update request
3869  * @wma_handle: wma handle
3870  * @ch_avoid_update_req: channel avoid update params
3871  *
3872  * Return: QDF status
3873  */
3874 QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,
3875 					   tSirChAvoidUpdateReq *
3876 					   ch_avoid_update_req)
3877 {
3878 	QDF_STATUS status;
3879 
3880 	if (!wma_handle) {
3881 		WMA_LOGE("%s: wma handle is NULL", __func__);
3882 		return QDF_STATUS_E_FAILURE;
3883 	}
3884 	if (ch_avoid_update_req == NULL) {
3885 		WMA_LOGE("%s : ch_avoid_update_req is NULL", __func__);
3886 		return QDF_STATUS_E_FAILURE;
3887 	}
3888 
3889 	WMA_LOGD("%s: WMA --> WMI_CHAN_AVOID_UPDATE", __func__);
3890 
3891 	status = wmi_unified_process_ch_avoid_update_cmd(
3892 					wma_handle->wmi_handle);
3893 	if (QDF_IS_STATUS_ERROR(status))
3894 		return status;
3895 
3896 	WMA_LOGD("%s: WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI",
3897 		 __func__);
3898 	return status;
3899 }
3900 #endif
3901 
3902 /**
3903  * wma_send_regdomain_info_to_fw() - send regdomain info to fw
3904  * @reg_dmn: reg domain
3905  * @regdmn2G: 2G reg domain
3906  * @regdmn5G: 5G reg domain
3907  * @ctl2G: 2G test limit
3908  * @ctl5G: 5G test limit
3909  *
3910  * Return: none
3911  */
3912 void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
3913 				   uint16_t regdmn5G, uint8_t ctl2G,
3914 				   uint8_t ctl5G)
3915 {
3916 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3917 	int32_t cck_mask_val = 0;
3918 	struct pdev_params pdev_param = {0};
3919 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
3920 	QDF_STATUS status = QDF_STATUS_SUCCESS;
3921 
3922 	if (NULL == wma) {
3923 		WMA_LOGE("%s: wma context is NULL", __func__);
3924 		return;
3925 	}
3926 
3927 	status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle,
3928 			reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G);
3929 	if (status == QDF_STATUS_E_NOMEM)
3930 		return;
3931 
3932 	if ((((reg_dmn & ~CTRY_FLAG) == CTRY_JAPAN15) ||
3933 	     ((reg_dmn & ~CTRY_FLAG) == CTRY_KOREA_ROC)) &&
3934 	    (true == wma->tx_chain_mask_cck))
3935 		cck_mask_val = 1;
3936 
3937 	cck_mask_val |= (wma->self_gen_frm_pwr << 16);
3938 	pdev_param.param_id = WMI_PDEV_PARAM_TX_CHAIN_MASK_CCK;
3939 	pdev_param.param_value = cck_mask_val;
3940 	ret = wmi_unified_pdev_param_send(wma->wmi_handle,
3941 					 &pdev_param,
3942 					 WMA_WILDCARD_PDEV_ID);
3943 
3944 	if (QDF_IS_STATUS_ERROR(ret))
3945 		WMA_LOGE("failed to set PDEV tx_chain_mask_cck %d",
3946 			 ret);
3947 }
3948 
3949 #ifdef FEATURE_WLAN_TDLS
3950 /**
3951  * wma_tdls_event_handler() - handle TDLS event
3952  * @handle: wma handle
3953  * @event: event buffer
3954  * @len: buffer length
3955  *
3956  * Return: 0 for success or error code
3957  */
3958 int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len)
3959 {
3960 	/* TODO update with target rx ops */
3961 	return 0;
3962 }
3963 
3964 /**
3965  * wma_set_tdls_offchan_mode() - set tdls off channel mode
3966  * @handle: wma handle
3967  * @chan_switch_params: Pointer to tdls channel switch parameter structure
3968  *
3969  * This function sets tdls off channel mode
3970  *
3971  * Return: 0 on success; Negative errno otherwise
3972  */
3973 QDF_STATUS wma_set_tdls_offchan_mode(WMA_HANDLE handle,
3974 			      tdls_chan_switch_params *chan_switch_params)
3975 {
3976 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
3977 	struct tdls_channel_switch_params params = {0};
3978 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
3979 
3980 	if (!wma_handle || !wma_handle->wmi_handle) {
3981 		WMA_LOGE(FL(
3982 			    "WMA is closed, can not issue tdls off channel cmd"
3983 			 ));
3984 		ret = -EINVAL;
3985 		goto end;
3986 	}
3987 
3988 	if (wma_is_roam_synch_in_progress(wma_handle,
3989 					  chan_switch_params->vdev_id)) {
3990 		WMA_LOGE("%s: roaming in progress, reject offchan mode cmd!",
3991 			 __func__);
3992 		ret = -EPERM;
3993 		goto end;
3994 	}
3995 
3996 	params.vdev_id = chan_switch_params->vdev_id;
3997 	params.tdls_off_ch_bw_offset =
3998 			chan_switch_params->tdls_off_ch_bw_offset;
3999 	params.tdls_off_ch = chan_switch_params->tdls_off_ch;
4000 	params.tdls_sw_mode = chan_switch_params->tdls_sw_mode;
4001 	params.oper_class = chan_switch_params->oper_class;
4002 	params.is_responder = chan_switch_params->is_responder;
4003 	qdf_mem_copy(params.peer_mac_addr, chan_switch_params->peer_mac_addr,
4004 		     IEEE80211_ADDR_LEN);
4005 
4006 	ret = wmi_unified_set_tdls_offchan_mode_cmd(wma_handle->wmi_handle,
4007 							&params);
4008 
4009 end:
4010 	if (chan_switch_params)
4011 		qdf_mem_free(chan_switch_params);
4012 	return ret;
4013 }
4014 
4015 /**
4016  * wma_update_tdls_peer_state() - update TDLS peer state
4017  * @handle: wma handle
4018  * @peerStateParams: TDLS peer state params
4019  *
4020  * Return: 0 for success or error code
4021  */
4022 int wma_update_tdls_peer_state(WMA_HANDLE handle,
4023 			       tTdlsPeerStateParams *peerStateParams)
4024 {
4025 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
4026 	uint32_t i;
4027 	struct cdp_pdev *pdev;
4028 	uint8_t peer_id;
4029 	void *peer;
4030 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4031 	uint8_t *peer_mac_addr;
4032 	int ret = 0;
4033 	uint32_t *ch_mhz = NULL;
4034 	bool restore_last_peer = false;
4035 
4036 	if (!wma_handle || !wma_handle->wmi_handle) {
4037 		WMA_LOGE("%s: WMA is closed, can not issue cmd", __func__);
4038 		ret = -EINVAL;
4039 		goto end_tdls_peer_state;
4040 	}
4041 
4042 	if (!soc) {
4043 		WMA_LOGE("%s: SOC context is NULL", __func__);
4044 		ret = -EINVAL;
4045 		goto end_tdls_peer_state;
4046 	}
4047 
4048 	if (wma_is_roam_synch_in_progress(wma_handle,
4049 					  peerStateParams->vdevId)) {
4050 		WMA_LOGE("%s: roaming in progress, reject peer update cmd!",
4051 			 __func__);
4052 		ret = -EPERM;
4053 		goto end_tdls_peer_state;
4054 	}
4055 
4056 	/* peer capability info is valid only when peer state is connected */
4057 	if (WMA_TDLS_PEER_STATE_CONNECTED != peerStateParams->peerState) {
4058 		qdf_mem_zero(&peerStateParams->peerCap,
4059 			     sizeof(tTdlsPeerCapParams));
4060 	}
4061 
4062 	if (peerStateParams->peerCap.peerChanLen) {
4063 		ch_mhz = qdf_mem_malloc(sizeof(uint32_t) *
4064 				peerStateParams->peerCap.peerChanLen);
4065 		if (ch_mhz == NULL) {
4066 			WMA_LOGE("%s: memory allocation failed", __func__);
4067 			ret = -ENOMEM;
4068 			goto end_tdls_peer_state;
4069 		}
4070 	}
4071 
4072 	for (i = 0; i < peerStateParams->peerCap.peerChanLen; ++i) {
4073 		ch_mhz[i] =
4074 			cds_chan_to_freq(peerStateParams->peerCap.peerChan[i].
4075 					 chanId);
4076 	}
4077 
4078 	/* Make sure that peer exists before sending peer state cmd*/
4079 	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
4080 	if (!pdev) {
4081 		WMA_LOGE("%s: Failed to find pdev", __func__);
4082 		ret = -EIO;
4083 		goto end_tdls_peer_state;
4084 	}
4085 
4086 	peer = cdp_peer_find_by_addr(soc,
4087 			pdev,
4088 			peerStateParams->peerMacAddr,
4089 			&peer_id);
4090 	if (!peer) {
4091 		WMA_LOGE("%s: Failed to get peer handle using peer mac %pM",
4092 				__func__, peerStateParams->peerMacAddr);
4093 		ret = -EIO;
4094 		goto end_tdls_peer_state;
4095 	}
4096 
4097 	if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle,
4098 			 (struct tdls_peer_state_params *)peerStateParams,
4099 			 ch_mhz)) {
4100 		WMA_LOGE("%s: failed to send tdls peer update state command",
4101 			 __func__);
4102 		ret = -EIO;
4103 		goto end_tdls_peer_state;
4104 	}
4105 
4106 	/* in case of teardown, remove peer from fw */
4107 	if (WMA_TDLS_PEER_STATE_TEARDOWN == peerStateParams->peerState) {
4108 		peer_mac_addr = cdp_peer_get_peer_mac_addr(soc, peer);
4109 		if (peer_mac_addr == NULL) {
4110 			WMA_LOGE("peer_mac_addr is NULL");
4111 			ret = -EIO;
4112 			goto end_tdls_peer_state;
4113 		}
4114 
4115 		restore_last_peer = cdp_peer_is_vdev_restore_last_peer(
4116 						soc, peer);
4117 
4118 		WMA_LOGD("%s: calling wma_remove_peer for peer " MAC_ADDRESS_STR
4119 			 " vdevId: %d", __func__,
4120 			 MAC_ADDR_ARRAY(peer_mac_addr),
4121 			 peerStateParams->vdevId);
4122 		wma_remove_peer(wma_handle, peer_mac_addr,
4123 				peerStateParams->vdevId, peer, false);
4124 		cdp_peer_update_last_real_peer(soc,
4125 				pdev, peer, &peer_id,
4126 				restore_last_peer);
4127 	}
4128 
4129 end_tdls_peer_state:
4130 	if (ch_mhz)
4131 		qdf_mem_free(ch_mhz);
4132 	if (peerStateParams)
4133 		qdf_mem_free(peerStateParams);
4134 	return ret;
4135 }
4136 #endif /* FEATURE_WLAN_TDLS */
4137 
4138 
4139 /*
4140  * wma_process_set_ie_info() - Function to send IE info to firmware
4141  * @wma:                Pointer to WMA handle
4142  * @ie_data:       Pointer for ie data
4143  *
4144  * This function sends IE information to firmware
4145  *
4146  * Return: QDF_STATUS_SUCCESS for success otherwise failure
4147  *
4148  */
4149 QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
4150 				   struct vdev_ie_info *ie_info)
4151 {
4152 	struct wma_txrx_node *interface;
4153 	struct vdev_ie_info_param cmd = {0};
4154 	int ret;
4155 
4156 	if (!ie_info || !wma) {
4157 		WMA_LOGE(FL("input pointer is NULL"));
4158 		return QDF_STATUS_E_FAILURE;
4159 	}
4160 
4161 	/* Validate the input */
4162 	if (ie_info->length  <= 0) {
4163 		WMA_LOGE(FL("Invalid IE length"));
4164 		return QDF_STATUS_E_INVAL;
4165 	}
4166 
4167 	if (ie_info->vdev_id >= wma->max_bssid) {
4168 		WMA_LOGE(FL("Invalid vdev_id: %d"), ie_info->vdev_id);
4169 		return QDF_STATUS_E_INVAL;
4170 	}
4171 
4172 	interface = &wma->interfaces[ie_info->vdev_id];
4173 	if (!interface->is_vdev_valid) {
4174 		WMA_LOGE(FL("vdev_id: %d is not active"), ie_info->vdev_id);
4175 		return QDF_STATUS_E_INVAL;
4176 	}
4177 
4178 	cmd.vdev_id = ie_info->vdev_id;
4179 	cmd.ie_id = ie_info->ie_id;
4180 	cmd.length = ie_info->length;
4181 	cmd.band = ie_info->band;
4182 	cmd.data = ie_info->data;
4183 	cmd.ie_source = WMA_SET_VDEV_IE_SOURCE_HOST;
4184 
4185 	WMA_LOGD(FL("vdev id: %d, ie_id: %d, band: %d, len: %d"),
4186 		 ie_info->vdev_id, ie_info->ie_id, ie_info->band,
4187 		 ie_info->length);
4188 
4189 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
4190 		ie_info->data, ie_info->length);
4191 
4192 	ret = wmi_unified_process_set_ie_info_cmd(wma->wmi_handle,
4193 				   &cmd);
4194 	return ret;
4195 }
4196 
4197 /**
4198  *  wma_get_bpf_caps_event_handler() - Event handler for get bpf capability
4199  *  @handle: WMA global handle
4200  *  @cmd_param_info: command event data
4201  *  @len: Length of @cmd_param_info
4202  *
4203  *  Return: 0 on Success or Errno on failure
4204  */
4205 int wma_get_bpf_caps_event_handler(void *handle,
4206 			u_int8_t *cmd_param_info,
4207 			u_int32_t len)
4208 {
4209 	WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs  *param_buf;
4210 	wmi_bpf_capability_info_evt_fixed_param *event;
4211 	struct sir_bpf_get_offload *bpf_get_offload;
4212 	tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context(
4213 				QDF_MODULE_ID_PE);
4214 
4215 	if (!pmac) {
4216 		WMA_LOGE("%s: Invalid pmac", __func__);
4217 		return -EINVAL;
4218 	}
4219 	if (!pmac->sme.bpf_get_offload_cb) {
4220 		WMA_LOGE("%s: Callback not registered", __func__);
4221 		return -EINVAL;
4222 	}
4223 
4224 	param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info;
4225 	event = param_buf->fixed_param;
4226 	bpf_get_offload = qdf_mem_malloc(sizeof(*bpf_get_offload));
4227 
4228 	if (!bpf_get_offload) {
4229 		WMA_LOGP("%s: Memory allocation failed.", __func__);
4230 		return -ENOMEM;
4231 	}
4232 
4233 	bpf_get_offload->bpf_version = event->bpf_version;
4234 	bpf_get_offload->max_bpf_filters = event->max_bpf_filters;
4235 	bpf_get_offload->max_bytes_for_bpf_inst =
4236 			event->max_bytes_for_bpf_inst;
4237 	WMA_LOGD("%s: BPF capabilities version: %d max bpf filter size: %d",
4238 			__func__, bpf_get_offload->bpf_version,
4239 	bpf_get_offload->max_bytes_for_bpf_inst);
4240 
4241 	WMA_LOGD("%s: sending bpf capabilities event to hdd", __func__);
4242 	pmac->sme.bpf_get_offload_cb(pmac->sme.bpf_get_offload_context,
4243 				     bpf_get_offload);
4244 	qdf_mem_free(bpf_get_offload);
4245 	return 0;
4246 }
4247 
4248 /**
4249  * wma_get_bpf_capabilities - Send get bpf capability to firmware
4250  * @wma_handle: wma handle
4251  *
4252  * Return: QDF_STATUS enumeration.
4253  */
4254 QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma)
4255 {
4256 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4257 	wmi_bpf_get_capability_cmd_fixed_param *cmd;
4258 	wmi_buf_t wmi_buf;
4259 	uint32_t   len;
4260 	u_int8_t *buf_ptr;
4261 
4262 	if (!wma || !wma->wmi_handle) {
4263 		WMA_LOGE(FL("WMA is closed, can not issue get BPF capab"));
4264 		return QDF_STATUS_E_INVAL;
4265 	}
4266 
4267 	if (!wmi_service_enabled(wma->wmi_handle,
4268 		wmi_service_bpf_offload)) {
4269 		WMA_LOGE(FL("BPF cababilities feature bit not enabled"));
4270 		return QDF_STATUS_E_FAILURE;
4271 	}
4272 
4273 	len = sizeof(*cmd);
4274 	wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
4275 	if (!wmi_buf) {
4276 		WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
4277 		return QDF_STATUS_E_NOMEM;
4278 	}
4279 
4280 	buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
4281 	cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr;
4282 	WMITLV_SET_HDR(&cmd->tlv_header,
4283 	WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param,
4284 		WMITLV_GET_STRUCT_TLVLEN(
4285 		wmi_bpf_get_capability_cmd_fixed_param));
4286 
4287 	if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
4288 		WMI_BPF_GET_CAPABILITY_CMDID)) {
4289 		WMA_LOGE(FL("Failed to send BPF capability command"));
4290 		wmi_buf_free(wmi_buf);
4291 		return QDF_STATUS_E_FAILURE;
4292 	}
4293 	return status;
4294 }
4295 
4296 /**
4297  *  wma_set_bpf_instructions - Set bpf instructions to firmware
4298  *  @wma: wma handle
4299  *  @bpf_set_offload: Bpf offload information to set to firmware
4300  *
4301  *  Return: QDF_STATUS enumeration
4302  */
4303 QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma,
4304 				struct sir_bpf_set_offload *bpf_set_offload)
4305 {
4306 	wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd;
4307 	wmi_buf_t wmi_buf;
4308 	uint32_t   len = 0, len_aligned = 0;
4309 	u_int8_t *buf_ptr;
4310 
4311 	if (!wma || !wma->wmi_handle) {
4312 		WMA_LOGE("%s: WMA is closed, can not issue set BPF capability",
4313 			__func__);
4314 		return QDF_STATUS_E_INVAL;
4315 	}
4316 
4317 	if (!wmi_service_enabled(wma->wmi_handle,
4318 		wmi_service_bpf_offload)) {
4319 		WMA_LOGE(FL("BPF offload feature Disabled"));
4320 		return QDF_STATUS_E_NOSUPPORT;
4321 	}
4322 
4323 	if (!bpf_set_offload) {
4324 		WMA_LOGE("%s: Invalid BPF instruction request", __func__);
4325 		return QDF_STATUS_E_INVAL;
4326 	}
4327 
4328 	if (bpf_set_offload->session_id >= wma->max_bssid) {
4329 		WMA_LOGE(FL("Invalid vdev_id: %d"),
4330 			bpf_set_offload->session_id);
4331 		return QDF_STATUS_E_INVAL;
4332 	}
4333 
4334 	if (!wma_is_vdev_up(bpf_set_offload->session_id)) {
4335 		WMA_LOGE("vdev %d is not up skipping BPF offload",
4336 			bpf_set_offload->session_id);
4337 		return QDF_STATUS_E_INVAL;
4338 	}
4339 
4340 	if (bpf_set_offload->total_length) {
4341 		len_aligned = roundup(bpf_set_offload->current_length,
4342 					sizeof(A_UINT32));
4343 		len = len_aligned + WMI_TLV_HDR_SIZE;
4344 	}
4345 
4346 	len += sizeof(*cmd);
4347 	wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
4348 	if (!wmi_buf) {
4349 		WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
4350 		return QDF_STATUS_E_NOMEM;
4351 	}
4352 
4353 	buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf);
4354 	cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr;
4355 
4356 	WMITLV_SET_HDR(&cmd->tlv_header,
4357 		WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param,
4358 		WMITLV_GET_STRUCT_TLVLEN(
4359 			wmi_bpf_set_vdev_instructions_cmd_fixed_param));
4360 	cmd->vdev_id = bpf_set_offload->session_id;
4361 	cmd->filter_id = bpf_set_offload->filter_id;
4362 	cmd->total_length = bpf_set_offload->total_length;
4363 	cmd->current_offset = bpf_set_offload->current_offset;
4364 	cmd->current_length = bpf_set_offload->current_length;
4365 
4366 	if (bpf_set_offload->total_length) {
4367 		buf_ptr +=
4368 			sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param);
4369 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned);
4370 		buf_ptr += WMI_TLV_HDR_SIZE;
4371 		qdf_mem_copy(buf_ptr, bpf_set_offload->program,
4372 					bpf_set_offload->current_length);
4373 	}
4374 
4375 	if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
4376 		WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) {
4377 		WMA_LOGE(FL("Failed to send config bpf instructions command"));
4378 		wmi_buf_free(wmi_buf);
4379 		return QDF_STATUS_E_FAILURE;
4380 	}
4381 	WMA_LOGD(FL("BPF offload enabled in fw"));
4382 
4383 	return QDF_STATUS_SUCCESS;
4384 }
4385 
4386 /**
4387  * wma_set_tx_rx_aggregation_size() - sets tx rx aggregation sizes
4388  * @tx_rx_aggregation_size: aggregation size parameters
4389  *
4390  * This function sets tx rx aggregation sizes
4391  *
4392  * Return: VOS_STATUS_SUCCESS on success, error number otherwise
4393  */
4394 QDF_STATUS wma_set_tx_rx_aggregation_size(
4395 	struct sir_set_tx_rx_aggregation_size *tx_rx_aggregation_size)
4396 {
4397 	tp_wma_handle wma_handle;
4398 	wmi_vdev_set_custom_aggr_size_cmd_fixed_param *cmd;
4399 	int32_t len;
4400 	wmi_buf_t buf;
4401 	u_int8_t *buf_ptr;
4402 	int ret;
4403 
4404 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
4405 
4406 	if (!tx_rx_aggregation_size) {
4407 		WMA_LOGE("%s: invalid pointer", __func__);
4408 		return QDF_STATUS_E_INVAL;
4409 	}
4410 
4411 	if (!wma_handle) {
4412 		WMA_LOGE("%s: WMA context is invald!", __func__);
4413 		return QDF_STATUS_E_INVAL;
4414 	}
4415 
4416 	len = sizeof(*cmd);
4417 	buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
4418 
4419 	if (!buf) {
4420 		WMA_LOGE("%s: Failed allocate wmi buffer", __func__);
4421 		return QDF_STATUS_E_NOMEM;
4422 	}
4423 
4424 	buf_ptr = (u_int8_t *) wmi_buf_data(buf);
4425 	cmd = (wmi_vdev_set_custom_aggr_size_cmd_fixed_param *) buf_ptr;
4426 
4427 	WMITLV_SET_HDR(&cmd->tlv_header,
4428 		WMITLV_TAG_STRUC_wmi_vdev_set_custom_aggr_size_cmd_fixed_param,
4429 		WMITLV_GET_STRUCT_TLVLEN(
4430 			wmi_vdev_set_custom_aggr_size_cmd_fixed_param));
4431 
4432 	cmd->vdev_id = tx_rx_aggregation_size->vdev_id;
4433 	cmd->tx_aggr_size = tx_rx_aggregation_size->tx_aggregation_size;
4434 	cmd->rx_aggr_size = tx_rx_aggregation_size->rx_aggregation_size;
4435 
4436 	WMA_LOGD("tx aggr: %d rx aggr: %d vdev: %d",
4437 		cmd->tx_aggr_size, cmd->rx_aggr_size, cmd->vdev_id);
4438 
4439 	ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
4440 				WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID);
4441 	if (ret) {
4442 		WMA_LOGE("%s: Failed to send aggregation size command",
4443 				__func__);
4444 		wmi_buf_free(buf);
4445 		return QDF_STATUS_E_FAILURE;
4446 	}
4447 
4448 	return QDF_STATUS_SUCCESS;
4449 }
4450 
4451 /**
4452  *  wma_p2p_lo_start() - P2P listen offload start
4453  *  @params: p2p listen offload parameters
4454  *
4455  *  This function sends WMI command to start P2P listen offload.
4456  *
4457  *  Return: QDF_STATUS enumeration
4458  */
4459 QDF_STATUS wma_p2p_lo_start(struct sir_p2p_lo_start *params)
4460 {
4461 	wmi_buf_t buf;
4462 	wmi_p2p_lo_start_cmd_fixed_param *cmd;
4463 	int32_t len = sizeof(*cmd);
4464 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4465 	uint8_t *buf_ptr;
4466 	int ret;
4467 	int device_types_len_aligned, probe_resp_len_aligned;
4468 
4469 	if (NULL == wma) {
4470 		WMA_LOGE("%s: wma context is NULL", __func__);
4471 		return QDF_STATUS_E_INVAL;
4472 	}
4473 
4474 	device_types_len_aligned = qdf_roundup(params->dev_types_len,
4475 						sizeof(A_UINT32));
4476 	probe_resp_len_aligned = qdf_roundup(params->probe_resp_len,
4477 						sizeof(A_UINT32));
4478 
4479 	len += 2 * WMI_TLV_HDR_SIZE + device_types_len_aligned +
4480 			probe_resp_len_aligned;
4481 
4482 	buf = wmi_buf_alloc(wma->wmi_handle, len);
4483 	if (!buf) {
4484 		WMA_LOGP("%s: failed to allocate memory for p2p lo start",
4485 			 __func__);
4486 		return QDF_STATUS_E_NOMEM;
4487 	}
4488 
4489 	cmd = (wmi_p2p_lo_start_cmd_fixed_param *)wmi_buf_data(buf);
4490 	buf_ptr = (uint8_t *) wmi_buf_data(buf);
4491 
4492 	WMITLV_SET_HDR(&cmd->tlv_header,
4493 		 WMITLV_TAG_STRUC_wmi_p2p_lo_start_cmd_fixed_param,
4494 		 WMITLV_GET_STRUCT_TLVLEN(
4495 			wmi_p2p_lo_start_cmd_fixed_param));
4496 
4497 	cmd->vdev_id = params->vdev_id;
4498 	cmd->ctl_flags = params->ctl_flags;
4499 	cmd->channel = params->freq;
4500 	cmd->period = params->period;
4501 	cmd->interval = params->interval;
4502 	cmd->count = params->count;
4503 	cmd->device_types_len = params->dev_types_len;
4504 	cmd->prob_resp_len = params->probe_resp_len;
4505 
4506 	buf_ptr += sizeof(wmi_p2p_lo_start_cmd_fixed_param);
4507 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
4508 				device_types_len_aligned);
4509 	buf_ptr += WMI_TLV_HDR_SIZE;
4510 	qdf_mem_copy(buf_ptr, params->device_types, params->dev_types_len);
4511 
4512 	buf_ptr += device_types_len_aligned;
4513 	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, probe_resp_len_aligned);
4514 	buf_ptr += WMI_TLV_HDR_SIZE;
4515 	qdf_mem_copy(buf_ptr, params->probe_resp_tmplt, params->probe_resp_len);
4516 
4517 	WMA_LOGI("%s: Sending WMI_P2P_LO_START command, channel=%d, period=%d, interval=%d, count=%d",
4518 			__func__, cmd->channel, cmd->period,
4519 			cmd->interval, cmd->count);
4520 
4521 	ret = wmi_unified_cmd_send(wma->wmi_handle,
4522 				   buf, len,
4523 				   WMI_P2P_LISTEN_OFFLOAD_START_CMDID);
4524 	if (ret) {
4525 		WMA_LOGE("Failed to send p2p lo start: %d", ret);
4526 		wmi_buf_free(buf);
4527 	}
4528 
4529 	WMA_LOGI("%s: Successfully sent WMI_P2P_LO_START", __func__);
4530 	wma->interfaces[params->vdev_id].p2p_lo_in_progress = true;
4531 
4532 	return ret;
4533 }
4534 
4535 /**
4536  *  wma_p2p_lo_stop() - P2P listen offload stop
4537  *  @vdev_id: vdev identifier
4538  *
4539  *  This function sends WMI command to stop P2P listen offload.
4540  *
4541  *  Return: QDF_STATUS enumeration
4542  */
4543 QDF_STATUS wma_p2p_lo_stop(u_int32_t vdev_id)
4544 {
4545 	wmi_buf_t buf;
4546 	wmi_p2p_lo_stop_cmd_fixed_param *cmd;
4547 	int32_t len;
4548 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4549 	int ret;
4550 
4551 	if (NULL == wma) {
4552 		WMA_LOGE("%s: wma context is NULL", __func__);
4553 		return QDF_STATUS_E_INVAL;
4554 	}
4555 
4556 	len = sizeof(*cmd);
4557 	buf = wmi_buf_alloc(wma->wmi_handle, len);
4558 	if (!buf) {
4559 		WMA_LOGP("%s: failed to allocate memory for p2p lo stop",
4560 			 __func__);
4561 		return QDF_STATUS_E_NOMEM;
4562 	}
4563 	cmd = (wmi_p2p_lo_stop_cmd_fixed_param *)wmi_buf_data(buf);
4564 
4565 	WMITLV_SET_HDR(&cmd->tlv_header,
4566 		WMITLV_TAG_STRUC_wmi_p2p_lo_stop_cmd_fixed_param,
4567 		WMITLV_GET_STRUCT_TLVLEN(
4568 			wmi_p2p_lo_stop_cmd_fixed_param));
4569 
4570 	cmd->vdev_id = vdev_id;
4571 
4572 	WMA_LOGI("%s: Sending WMI_P2P_LO_STOP command", __func__);
4573 
4574 	ret = wmi_unified_cmd_send(wma->wmi_handle,
4575 				   buf, len,
4576 				   WMI_P2P_LISTEN_OFFLOAD_STOP_CMDID);
4577 	if (ret) {
4578 		WMA_LOGE("Failed to send p2p lo stop: %d", ret);
4579 		wmi_buf_free(buf);
4580 	}
4581 
4582 	WMA_LOGI("%s: Successfully sent WMI_P2P_LO_STOP", __func__);
4583 	wma->interfaces[vdev_id].p2p_lo_in_progress = false;
4584 
4585 	return ret;
4586 }
4587 
4588 /**
4589  * wma_p2p_lo_event_handler() - p2p lo event
4590  * @handle: the WMA handle
4591  * @event_buf: buffer with the event parameters
4592  * @len: length of the buffer
4593  *
4594  * This function receives P2P listen offload stop event from FW and
4595  * pass the event information to upper layer.
4596  *
4597  * Return: 0 on success
4598  */
4599 int wma_p2p_lo_event_handler(void *handle, uint8_t *event_buf,
4600 				uint32_t len)
4601 {
4602 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4603 	struct sir_p2p_lo_event *event;
4604 	WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *param_tlvs;
4605 	wmi_p2p_lo_stopped_event_fixed_param *fix_param;
4606 	tpAniSirGlobal p_mac = cds_get_context(QDF_MODULE_ID_PE);
4607 
4608 	if (!wma) {
4609 		WMA_LOGE("%s: Invalid WMA Context", __func__);
4610 		return -EINVAL;
4611 	}
4612 
4613 	if (!p_mac) {
4614 		WMA_LOGE("%s: Invalid p_mac", __func__);
4615 		return -EINVAL;
4616 	}
4617 
4618 	if (!p_mac->sme.p2p_lo_event_callback) {
4619 		WMA_LOGE("%s: Callback not registered", __func__);
4620 		return -EINVAL;
4621 	}
4622 
4623 	param_tlvs = (WMI_P2P_LISTEN_OFFLOAD_STOPPED_EVENTID_param_tlvs *)
4624 								event_buf;
4625 	fix_param = param_tlvs->fixed_param;
4626 	if (fix_param->vdev_id >= wma->max_bssid) {
4627 		WMA_LOGE("%s: received invalid vdev_id %d",
4628 			 __func__, fix_param->vdev_id);
4629 		return -EINVAL;
4630 	}
4631 	event = qdf_mem_malloc(sizeof(*event));
4632 	if (event == NULL) {
4633 		WMA_LOGE("Event allocation failed");
4634 		return -ENOMEM;
4635 	}
4636 	event->vdev_id = fix_param->vdev_id;
4637 	event->reason_code = fix_param->reason;
4638 
4639 	p_mac->sme.p2p_lo_event_callback(p_mac->hHdd, event);
4640 
4641 	wma->interfaces[event->vdev_id].p2p_lo_in_progress = false;
4642 
4643 	return 0;
4644 }
4645 
4646 /**
4647  * wma_get_wakelock_stats() - Populates wake lock stats
4648  * @stats: non-null wakelock structure to populate
4649  *
4650  * This function collects wake lock stats
4651  *
4652  * Return: QDF_STATUS_SUCCESS on success, error value otherwise
4653  */
4654 QDF_STATUS wma_get_wakelock_stats(struct sir_wake_lock_stats *stats)
4655 {
4656 	t_wma_handle *wma;
4657 	struct sir_vdev_wow_stats *vstats;
4658 	int i;
4659 
4660 	if (!stats) {
4661 		WMA_LOGE("%s: invalid stats pointer", __func__);
4662 		return QDF_STATUS_E_INVAL;
4663 	}
4664 
4665 	wma = cds_get_context(QDF_MODULE_ID_WMA);
4666 	if (!wma) {
4667 		WMA_LOGE("%s: invalid WMA context", __func__);
4668 		return QDF_STATUS_E_INVAL;
4669 	}
4670 
4671 	/* ensure counters are zeroed */
4672 	qdf_mem_zero(stats, sizeof(*stats));
4673 
4674 	/* populate global level stats */
4675 	stats->wow_unspecified_wake_up_count = wma->wow_unspecified_wake_count;
4676 
4677 	/* populate vdev level stats */
4678 	for (i = 0; i < wma->max_bssid; ++i) {
4679 		if (!wma->interfaces[i].handle)
4680 			continue;
4681 
4682 		vstats = &wma->interfaces[i].wow_stats;
4683 
4684 		stats->wow_ucast_wake_up_count += vstats->ucast;
4685 		stats->wow_bcast_wake_up_count += vstats->bcast;
4686 		stats->wow_ipv4_mcast_wake_up_count += vstats->ipv4_mcast;
4687 		stats->wow_ipv6_mcast_wake_up_count += vstats->ipv6_mcast;
4688 		stats->wow_ipv6_mcast_ra_stats += vstats->ipv6_mcast_ra;
4689 		stats->wow_ipv6_mcast_ns_stats += vstats->ipv6_mcast_ns;
4690 		stats->wow_ipv6_mcast_na_stats += vstats->ipv6_mcast_na;
4691 		stats->wow_icmpv4_count += vstats->icmpv4;
4692 		stats->wow_icmpv6_count += vstats->icmpv6;
4693 		stats->wow_rssi_breach_wake_up_count += vstats->rssi_breach;
4694 		stats->wow_low_rssi_wake_up_count += vstats->low_rssi;
4695 		stats->wow_gscan_wake_up_count += vstats->gscan;
4696 		stats->wow_pno_complete_wake_up_count += vstats->pno_complete;
4697 		stats->wow_pno_match_wake_up_count += vstats->pno_match;
4698 		stats->wow_oem_response_wake_up_count += vstats->oem_response;
4699 	}
4700 
4701 	return QDF_STATUS_SUCCESS;
4702 }
4703 
4704 /**
4705  * wma_process_fw_test_cmd() - send unit test command to fw.
4706  * @handle: wma handle
4707  * @wma_fwtest: fw test command
4708  *
4709  * This function send fw test command to fw.
4710  *
4711  * Return: none
4712  */
4713 void wma_process_fw_test_cmd(WMA_HANDLE handle,
4714 			     struct set_fwtest_params *wma_fwtest)
4715 {
4716 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
4717 
4718 	if (!wma_handle || !wma_handle->wmi_handle) {
4719 		WMA_LOGE("%s: WMA is closed, can not issue fw test cmd",
4720 			 __func__);
4721 		return;
4722 	}
4723 
4724 	if (wmi_unified_fw_test_cmd(wma_handle->wmi_handle,
4725 				    (struct set_fwtest_params *)wma_fwtest)) {
4726 		WMA_LOGE("%s: Failed to issue fw test cmd",
4727 			 __func__);
4728 		return;
4729 	}
4730 }
4731 
4732 /**
4733  * wma_enable_disable_caevent_ind() - Issue WMI command to enable or
4734  * disable ca event indication
4735  * @wma: wma handler
4736  * @val: boolean value true or false
4737  *
4738  * Return: QDF_STATUS
4739  */
4740 QDF_STATUS wma_enable_disable_caevent_ind(tp_wma_handle wma, uint8_t val)
4741 {
4742 	WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *cmd;
4743 	wmi_buf_t wmi_buf;
4744 	uint8_t *buf_ptr;
4745 	uint32_t len;
4746 
4747 	if (!wma || !wma->wmi_handle) {
4748 		WMA_LOGE(FL("WMA is closed, can not issue set/clear CA"));
4749 		return QDF_STATUS_E_INVAL;
4750 	}
4751 
4752 	len = sizeof(*cmd);
4753 	wmi_buf = wmi_buf_alloc(wma->wmi_handle, len);
4754 	if (!wmi_buf) {
4755 		WMA_LOGE(FL("wmi_buf_alloc failed"));
4756 		return QDF_STATUS_E_NOMEM;
4757 	}
4758 	buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
4759 	cmd = (WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *) buf_ptr;
4760 	WMITLV_SET_HDR(&cmd->tlv_header,
4761 		WMITLV_TAG_STRUC_WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param,
4762 		WMITLV_GET_STRUCT_TLVLEN(
4763 				WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param));
4764 	cmd->rpt_allow = val;
4765 	if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len,
4766 				WMI_CHAN_AVOID_RPT_ALLOW_CMDID)) {
4767 		WMA_LOGE(FL("Failed to send enable/disable CA event command"));
4768 		wmi_buf_free(wmi_buf);
4769 		return QDF_STATUS_E_FAILURE;
4770 	}
4771 
4772 	return QDF_STATUS_SUCCESS;
4773 }
4774 
4775 static wma_sar_cb sar_callback;
4776 static void *sar_context;
4777 
4778 static int wma_sar_event_handler(void *handle, uint8_t *evt_buf, uint32_t len)
4779 {
4780 	tp_wma_handle wma_handle;
4781 	wmi_unified_t wmi_handle;
4782 	struct sar_limit_event *event;
4783 	wma_sar_cb callback;
4784 	QDF_STATUS status;
4785 
4786 	WMA_LOGI(FL("handle:%pK event:%pK len:%u"), handle, evt_buf, len);
4787 
4788 	wma_handle = handle;
4789 	if (!wma_handle) {
4790 		WMA_LOGE(FL("NULL wma_handle"));
4791 		return QDF_STATUS_E_INVAL;
4792 	}
4793 
4794 	wmi_handle = wma_handle->wmi_handle;
4795 	if (!wmi_handle) {
4796 		WMA_LOGE(FL("NULL wmi_handle"));
4797 		return QDF_STATUS_E_INVAL;
4798 	}
4799 
4800 	event = qdf_mem_malloc(sizeof(*event));
4801 	if (!event) {
4802 		WMA_LOGE(FL("failed to malloc sar_limit_event"));
4803 		return QDF_STATUS_E_NOMEM;
4804 	}
4805 
4806 	status = wmi_unified_extract_sar_limit_event(wmi_handle,
4807 						     evt_buf, event);
4808 	if (QDF_IS_STATUS_ERROR(status)) {
4809 		WMA_LOGE(FL("Event extract failure: %d"), status);
4810 		qdf_mem_free(event);
4811 		return QDF_STATUS_E_INVAL;
4812 	}
4813 
4814 	callback = sar_callback;
4815 	sar_callback = NULL;
4816 	if (callback)
4817 		callback(sar_context, event);
4818 
4819 	qdf_mem_free(event);
4820 
4821 	return 0;
4822 }
4823 
4824 QDF_STATUS wma_sar_register_event_handlers(WMA_HANDLE handle)
4825 {
4826 	tp_wma_handle wma_handle = handle;
4827 	wmi_unified_t wmi_handle;
4828 
4829 	if (!wma_handle) {
4830 		WMA_LOGE(FL("NULL wma_handle"));
4831 		return QDF_STATUS_E_INVAL;
4832 	}
4833 
4834 	wmi_handle = wma_handle->wmi_handle;
4835 	if (!wmi_handle) {
4836 		WMA_LOGE(FL("NULL wmi_handle"));
4837 		return QDF_STATUS_E_INVAL;
4838 	}
4839 
4840 	return wmi_unified_register_event_handler(wmi_handle,
4841 						  wmi_sar_get_limits_event_id,
4842 						  wma_sar_event_handler,
4843 						  WMA_RX_WORK_CTX);
4844 }
4845 
4846 QDF_STATUS wma_get_sar_limit(WMA_HANDLE handle,
4847 			     wma_sar_cb callback, void *context)
4848 {
4849 	tp_wma_handle wma_handle = handle;
4850 	wmi_unified_t wmi_handle;
4851 	QDF_STATUS status;
4852 
4853 	if (!wma_handle) {
4854 		WMA_LOGE(FL("NULL wma_handle"));
4855 		return QDF_STATUS_E_INVAL;
4856 	}
4857 
4858 	wmi_handle = wma_handle->wmi_handle;
4859 	if (!wmi_handle) {
4860 		WMA_LOGE(FL("NULL wmi_handle"));
4861 		return QDF_STATUS_E_INVAL;
4862 	}
4863 
4864 	sar_callback = callback;
4865 	sar_context = context;
4866 	status = wmi_unified_get_sar_limit_cmd(wmi_handle);
4867 	if (QDF_IS_STATUS_ERROR(status)) {
4868 		WMA_LOGE(FL("wmi_unified_get_sar_limit_cmd() error: %u"),
4869 			 status);
4870 		sar_callback = NULL;
4871 	}
4872 
4873 	return status;
4874 }
4875 
4876 QDF_STATUS wma_set_sar_limit(WMA_HANDLE handle,
4877 		struct sar_limit_cmd_params *sar_limit_params)
4878 {
4879 	int ret;
4880 	tp_wma_handle wma = (tp_wma_handle) handle;
4881 
4882 	if (!wma || !wma->wmi_handle) {
4883 		WMA_LOGE("%s: WMA is closed, can not issue set sar limit msg",
4884 			__func__);
4885 		return QDF_STATUS_E_INVAL;
4886 	}
4887 
4888 	if (sar_limit_params == NULL) {
4889 		WMA_LOGE("%s: set sar limit ptr NULL",
4890 			__func__);
4891 		return QDF_STATUS_E_INVAL;
4892 	}
4893 
4894 	ret = wmi_unified_send_sar_limit_cmd(wma->wmi_handle,
4895 				sar_limit_params);
4896 
4897 	return ret;
4898 }
4899 
4900 /**
4901  * wma_get_arp_stats_handler() - handle arp stats data
4902  * indicated by FW
4903  * @handle: wma context
4904  * @data: event buffer
4905  * @data len: length of event buffer
4906  *
4907  * Return: 0 on success
4908  */
4909 int wma_get_arp_stats_handler(void *handle, uint8_t *data,
4910 			uint32_t data_len)
4911 {
4912 	WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *param_buf;
4913 	wmi_vdev_get_arp_stats_event_fixed_param *data_event;
4914 	struct rsp_stats rsp;
4915 	tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
4916 
4917 	if (!mac) {
4918 		WMA_LOGE("%s: Invalid mac context", __func__);
4919 		return -EINVAL;
4920 	}
4921 
4922 	if (!mac->sme.get_arp_stats_cb) {
4923 		WMA_LOGE("%s: Callback not registered", __func__);
4924 		return -EINVAL;
4925 	}
4926 
4927 	if (data == NULL) {
4928 		WMA_LOGE("%s: invalid pointer", __func__);
4929 		return -EINVAL;
4930 	}
4931 	param_buf = (WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *)data;
4932 	if (!param_buf) {
4933 		WMA_LOGE("%s: Invalid get arp stats event", __func__);
4934 		return -EINVAL;
4935 	}
4936 	data_event = param_buf->fixed_param;
4937 	if (!data_event) {
4938 		WMA_LOGE("%s: Invalid get arp stats data event", __func__);
4939 		return -EINVAL;
4940 	}
4941 	rsp.arp_req_enqueue = data_event->arp_req_enqueue;
4942 	rsp.vdev_id = data_event->vdev_id;
4943 	rsp.arp_req_tx_success = data_event->arp_req_tx_success;
4944 	rsp.arp_req_tx_failure = data_event->arp_req_tx_failure;
4945 	rsp.arp_rsp_recvd = data_event->arp_rsp_recvd;
4946 	rsp.out_of_order_arp_rsp_drop_cnt =
4947 		data_event->out_of_order_arp_rsp_drop_cnt;
4948 	rsp.dad_detected = data_event->dad_detected;
4949 	rsp.connect_status = data_event->connect_status;
4950 	rsp.ba_session_establishment_status =
4951 		data_event->ba_session_establishment_status;
4952 
4953 	mac->sme.get_arp_stats_cb(mac->hHdd, &rsp);
4954 
4955 	return 0;
4956 }
4957 
4958 /**
4959  * wma_unified_power_debug_stats_event_handler() - WMA handler function to
4960  * handle Power stats event from firmware
4961  * @handle: Pointer to wma handle
4962  * @cmd_param_info: Pointer to Power stats event TLV
4963  * @len: Length of the cmd_param_info
4964  *
4965  * Return: 0 on success, error number otherwise
4966  */
4967 #ifdef WLAN_POWER_DEBUGFS
4968 int wma_unified_power_debug_stats_event_handler(void *handle,
4969 			uint8_t *cmd_param_info, uint32_t len)
4970 {
4971 	WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *param_tlvs;
4972 	struct power_stats_response *power_stats_results;
4973 	wmi_pdev_chip_power_stats_event_fixed_param *param_buf;
4974 	uint32_t power_stats_len, stats_registers_len, *debug_registers;
4975 
4976 	tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
4977 
4978 	param_tlvs =
4979 		(WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *) cmd_param_info;
4980 
4981 	param_buf = (wmi_pdev_chip_power_stats_event_fixed_param *)
4982 		param_tlvs->fixed_param;
4983 	if (!mac || !mac->sme.power_stats_resp_callback) {
4984 		WMA_LOGD("%s: NULL mac ptr or HDD callback is null", __func__);
4985 		return -EINVAL;
4986 	}
4987 
4988 	if (!param_buf) {
4989 		WMA_LOGD("%s: NULL power stats event fixed param", __func__);
4990 		return -EINVAL;
4991 	}
4992 
4993 	if (param_buf->num_debug_register > ((WMI_SVC_MSG_MAX_SIZE -
4994 		sizeof(wmi_pdev_chip_power_stats_event_fixed_param)) /
4995 		sizeof(uint32_t)) ||
4996 	    param_buf->num_debug_register > param_tlvs->num_debug_registers) {
4997 		WMA_LOGE("excess payload: LEN num_debug_register:%u",
4998 				param_buf->num_debug_register);
4999 		return -EINVAL;
5000 	}
5001 	debug_registers = param_tlvs->debug_registers;
5002 	stats_registers_len =
5003 		(sizeof(uint32_t) * param_buf->num_debug_register);
5004 	power_stats_len = stats_registers_len + sizeof(*power_stats_results);
5005 	power_stats_results = qdf_mem_malloc(power_stats_len);
5006 	if (!power_stats_results) {
5007 		WMA_LOGD("%s: could not allocate mem for power stats results",
5008 				__func__);
5009 		return -ENOMEM;
5010 	}
5011 	WMA_LOGD("Cumulative sleep time %d cumulative total on time %d deep sleep enter counter %d last deep sleep enter tstamp ts %d debug registers fmt %d num debug register %d",
5012 			param_buf->cumulative_sleep_time_ms,
5013 			param_buf->cumulative_total_on_time_ms,
5014 			param_buf->deep_sleep_enter_counter,
5015 			param_buf->last_deep_sleep_enter_tstamp_ms,
5016 			param_buf->debug_register_fmt,
5017 			param_buf->num_debug_register);
5018 
5019 	power_stats_results->cumulative_sleep_time_ms
5020 		= param_buf->cumulative_sleep_time_ms;
5021 	power_stats_results->cumulative_total_on_time_ms
5022 		= param_buf->cumulative_total_on_time_ms;
5023 	power_stats_results->deep_sleep_enter_counter
5024 		= param_buf->deep_sleep_enter_counter;
5025 	power_stats_results->last_deep_sleep_enter_tstamp_ms
5026 		= param_buf->last_deep_sleep_enter_tstamp_ms;
5027 	power_stats_results->debug_register_fmt
5028 		= param_buf->debug_register_fmt;
5029 	power_stats_results->num_debug_register
5030 		= param_buf->num_debug_register;
5031 
5032 	power_stats_results->debug_registers
5033 		= (uint32_t *)(power_stats_results + 1);
5034 
5035 	qdf_mem_copy(power_stats_results->debug_registers,
5036 			debug_registers, stats_registers_len);
5037 
5038 	mac->sme.power_stats_resp_callback(power_stats_results,
5039 			mac->sme.power_debug_stats_context);
5040 	qdf_mem_free(power_stats_results);
5041 	return 0;
5042 }
5043 #else
5044 int wma_unified_power_debug_stats_event_handler(void *handle,
5045 		uint8_t *cmd_param_info, uint32_t len)
5046 {
5047 	return 0;
5048 }
5049 #endif
5050 
5051 int wma_chan_info_event_handler(void *handle, uint8_t *event_buf,
5052 				uint32_t len)
5053 {
5054 	tp_wma_handle wma = (tp_wma_handle)handle;
5055 	WMI_CHAN_INFO_EVENTID_param_tlvs *param_buf;
5056 	wmi_chan_info_event_fixed_param *event;
5057 	struct scan_chan_info buf;
5058 	tpAniSirGlobal mac = NULL;
5059 	struct lim_channel_status *channel_status;
5060 
5061 	WMA_LOGD("%s: Enter", __func__);
5062 
5063 	if (wma != NULL && wma->cds_context != NULL)
5064 		mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
5065 
5066 	if (!mac) {
5067 		WMA_LOGE("%s: Invalid mac context", __func__);
5068 		return -EINVAL;
5069 	}
5070 
5071 	WMA_LOGD("%s: monitor:%d", __func__, mac->snr_monitor_enabled);
5072 	if (mac->snr_monitor_enabled && mac->chan_info_cb) {
5073 		param_buf =
5074 			(WMI_CHAN_INFO_EVENTID_param_tlvs *)event_buf;
5075 		if (!param_buf) {
5076 			WMA_LOGA("%s: Invalid chan info event", __func__);
5077 			return -EINVAL;
5078 		}
5079 
5080 		event = param_buf->fixed_param;
5081 		if (!event) {
5082 			WMA_LOGA("%s: Invalid fixed param", __func__);
5083 			return -EINVAL;
5084 		}
5085 		buf.tx_frame_count = event->tx_frame_cnt;
5086 		buf.clock_freq = event->mac_clk_mhz;
5087 		buf.cmd_flag = event->cmd_flags;
5088 		buf.freq = event->freq;
5089 		buf.noise_floor = event->noise_floor;
5090 		buf.cycle_count = event->cycle_count;
5091 		buf.rx_clear_count = event->rx_clear_count;
5092 		mac->chan_info_cb(&buf);
5093 	}
5094 
5095 	if (mac->sap.acs_with_more_param &&
5096 	    mac->sme.currDeviceMode == QDF_SAP_MODE) {
5097 		param_buf = (WMI_CHAN_INFO_EVENTID_param_tlvs *) event_buf;
5098 		if (!param_buf)  {
5099 			WMA_LOGE("Invalid chan info event buffer");
5100 			return -EINVAL;
5101 		}
5102 		event = param_buf->fixed_param;
5103 		channel_status =
5104 			qdf_mem_malloc(sizeof(*channel_status));
5105 		if (!channel_status) {
5106 			WMA_LOGE(FL("Mem alloc fail"));
5107 			return -ENOMEM;
5108 		}
5109 		WMA_LOGD(FL("freq=%d nf=%d rxcnt=%u cyccnt=%u tx_r=%d tx_t=%d"),
5110 			 event->freq,
5111 			 event->noise_floor,
5112 			 event->rx_clear_count,
5113 			 event->cycle_count,
5114 			 event->chan_tx_pwr_range,
5115 			 event->chan_tx_pwr_tp);
5116 
5117 		channel_status->channelfreq = event->freq;
5118 		channel_status->noise_floor = event->noise_floor;
5119 		channel_status->rx_clear_count =
5120 			 event->rx_clear_count;
5121 		channel_status->cycle_count = event->cycle_count;
5122 		channel_status->chan_tx_pwr_range =
5123 			 event->chan_tx_pwr_range;
5124 		channel_status->chan_tx_pwr_throughput =
5125 			 event->chan_tx_pwr_tp;
5126 		channel_status->rx_frame_count =
5127 			 event->rx_frame_count;
5128 		channel_status->bss_rx_cycle_count =
5129 			event->my_bss_rx_cycle_count;
5130 		channel_status->rx_11b_mode_data_duration =
5131 			event->rx_11b_mode_data_duration;
5132 		channel_status->tx_frame_count = event->tx_frame_cnt;
5133 		channel_status->mac_clk_mhz = event->mac_clk_mhz;
5134 		channel_status->channel_id =
5135 			cds_freq_to_chan(event->freq);
5136 		channel_status->cmd_flags =
5137 			event->cmd_flags;
5138 
5139 		wma_send_msg(handle, WMA_RX_CHN_STATUS_EVENT,
5140 			     (void *)channel_status, 0);
5141 	}
5142 
5143 	return 0;
5144 }
5145 
5146 int wma_rx_aggr_failure_event_handler(void *handle, u_int8_t *event_buf,
5147 							u_int32_t len)
5148 {
5149 	WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *param_buf;
5150 	struct sir_sme_rx_aggr_hole_ind *rx_aggr_hole_event;
5151 	wmi_rx_aggr_failure_event_fixed_param *rx_aggr_failure_info;
5152 	wmi_rx_aggr_failure_info *hole_info;
5153 	uint32_t i, alloc_len;
5154 	tpAniSirGlobal mac;
5155 
5156 	mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
5157 	if (!mac || !mac->sme.stats_ext2_cb) {
5158 		WMA_LOGD("%s: NULL mac ptr or HDD callback is null", __func__);
5159 		return -EINVAL;
5160 	}
5161 
5162 	param_buf = (WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *)event_buf;
5163 	if (!param_buf) {
5164 		WMA_LOGE("%s: Invalid stats ext event buf", __func__);
5165 		return -EINVAL;
5166 	}
5167 
5168 	rx_aggr_failure_info = param_buf->fixed_param;
5169 	hole_info = param_buf->failure_info;
5170 
5171 	if (rx_aggr_failure_info->num_failure_info > ((WMI_SVC_MSG_MAX_SIZE -
5172 	    sizeof(*rx_aggr_hole_event)) /
5173 	    sizeof(rx_aggr_hole_event->hole_info_array[0]))) {
5174 		WMA_LOGE("%s: Excess data from WMI num_failure_info %d",
5175 			 __func__, rx_aggr_failure_info->num_failure_info);
5176 		return -EINVAL;
5177 	}
5178 
5179 	alloc_len = sizeof(*rx_aggr_hole_event) +
5180 		(rx_aggr_failure_info->num_failure_info)*
5181 		sizeof(rx_aggr_hole_event->hole_info_array[0]);
5182 	rx_aggr_hole_event = qdf_mem_malloc(alloc_len);
5183 	if (NULL == rx_aggr_hole_event) {
5184 		WMA_LOGE("%s: Memory allocation failure", __func__);
5185 		return -ENOMEM;
5186 	}
5187 
5188 	rx_aggr_hole_event->hole_cnt = rx_aggr_failure_info->num_failure_info;
5189 	if (rx_aggr_hole_event->hole_cnt > param_buf->num_failure_info) {
5190 		WMA_LOGE("Invalid no of hole count: %d",
5191 				rx_aggr_hole_event->hole_cnt);
5192 		qdf_mem_free(rx_aggr_hole_event);
5193 		return -EINVAL;
5194 	}
5195 	WMA_LOGD("aggr holes_sum: %d\n",
5196 		rx_aggr_failure_info->num_failure_info);
5197 	for (i = 0; i < rx_aggr_hole_event->hole_cnt; i++) {
5198 		rx_aggr_hole_event->hole_info_array[i] =
5199 			hole_info->end_seq - hole_info->start_seq + 1;
5200 		WMA_LOGD("aggr_index: %d\tstart_seq: %d\tend_seq: %d\t"
5201 			"hole_info: %d mpdu lost",
5202 			i, hole_info->start_seq, hole_info->end_seq,
5203 			rx_aggr_hole_event->hole_info_array[i]);
5204 		hole_info++;
5205 	}
5206 
5207 	mac->sme.stats_ext2_cb(mac->hHdd, rx_aggr_hole_event);
5208 	qdf_mem_free(rx_aggr_hole_event);
5209 
5210 	return 0;
5211 }
5212 
5213 int wma_wlan_bt_activity_evt_handler(void *handle, uint8_t *event, uint32_t len)
5214 {
5215 	wmi_coex_bt_activity_event_fixed_param *fixed_param;
5216 	WMI_WLAN_COEX_BT_ACTIVITY_EVENTID_param_tlvs *param_buf =
5217 		(WMI_WLAN_COEX_BT_ACTIVITY_EVENTID_param_tlvs *)event;
5218 	struct scheduler_msg sme_msg = {0};
5219 	QDF_STATUS qdf_status;
5220 
5221 	if (!param_buf) {
5222 		WMA_LOGE(FL("Invalid BT activity event buffer"));
5223 		return -EINVAL;
5224 	}
5225 
5226 	fixed_param = param_buf->fixed_param;
5227 	if (!fixed_param) {
5228 		WMA_LOGE(FL("Invalid BT activity event fixed param buffer"));
5229 		return -EINVAL;
5230 	}
5231 
5232 	WMA_LOGI(FL("Received BT activity event %u"),
5233 		    fixed_param->coex_profile_evt);
5234 
5235 	sme_msg.type = eWNI_SME_BT_ACTIVITY_INFO_IND;
5236 	sme_msg.bodyptr = NULL;
5237 	sme_msg.bodyval = fixed_param->coex_profile_evt;
5238 
5239 	qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
5240 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
5241 		WMA_LOGE(FL("Failed to post msg to SME"));
5242 		return -EINVAL;
5243 	}
5244 
5245 	return 0;
5246 }
5247 
5248 int wma_peer_ant_info_evt_handler(void *handle, u_int8_t *event,
5249 	u_int32_t len)
5250 {
5251 	wmi_peer_antdiv_info *peer_ant_info;
5252 	WMI_PEER_ANTDIV_INFO_EVENTID_param_tlvs *param_buf;
5253 	wmi_peer_antdiv_info_event_fixed_param *fix_param;
5254 	struct chain_rssi_result *chain_rssi_result;
5255 	u_int32_t chain_index;
5256 
5257 	tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context(
5258 					QDF_MODULE_ID_PE);
5259 	if (!pmac) {
5260 		WMA_LOGE("%s: Invalid pmac", __func__);
5261 		return -EINVAL;
5262 	}
5263 
5264 	param_buf = (WMI_PEER_ANTDIV_INFO_EVENTID_param_tlvs *) event;
5265 	if (!param_buf) {
5266 		WMA_LOGE("Invalid peer_ant_info event buffer");
5267 		return -EINVAL;
5268 	}
5269 	fix_param = param_buf->fixed_param;
5270 	peer_ant_info = param_buf->peer_info;
5271 
5272 	WMA_LOGD("num_peers=%d\tvdev_id=%d",
5273 		fix_param->num_peers, fix_param->vdev_id);
5274 	WMA_LOGD("peer_ant_info: %pK", peer_ant_info);
5275 
5276 	if (!peer_ant_info) {
5277 		WMA_LOGE("Invalid peer_ant_info ptr");
5278 		return -EINVAL;
5279 	}
5280 
5281 	chain_rssi_result = qdf_mem_malloc(sizeof(*chain_rssi_result));
5282 	if (!chain_rssi_result) {
5283 		WMA_LOGE("%s: Failed to malloc", __func__);
5284 		return -ENOMEM;
5285 	}
5286 
5287 	for (chain_index = 0; chain_index < CHAIN_RSSI_NUM; chain_index++)
5288 		WMA_LOGD("chain%d rssi: %x", chain_index,
5289 				peer_ant_info->chain_rssi[chain_index]);
5290 
5291 	qdf_mem_copy(chain_rssi_result->chain_rssi,
5292 				peer_ant_info->chain_rssi,
5293 				sizeof(peer_ant_info->chain_rssi));
5294 
5295 	pmac->sme.get_chain_rssi_cb(pmac->sme.get_chain_rssi_context,
5296 				chain_rssi_result);
5297 
5298 	qdf_mem_free(chain_rssi_result);
5299 
5300 	return 0;
5301 }
5302 
5303 int wma_vdev_obss_detection_info_handler(void *handle, uint8_t *event,
5304 					 uint32_t len)
5305 {
5306 	tp_wma_handle wma = (tp_wma_handle) handle;
5307 	struct wmi_obss_detect_info *obss_detection;
5308 	QDF_STATUS status;
5309 
5310 	if (!event) {
5311 		WMA_LOGE("Invalid obss_detection_info event buffer");
5312 		return -EINVAL;
5313 	}
5314 
5315 	obss_detection = qdf_mem_malloc(sizeof(*obss_detection));
5316 	if (!obss_detection) {
5317 		WMA_LOGE("%s: Failed to malloc", __func__);
5318 		return -ENOMEM;
5319 	}
5320 
5321 	status = wmi_unified_extract_obss_detection_info(wma->wmi_handle,
5322 							 event, obss_detection);
5323 
5324 	if (QDF_IS_STATUS_ERROR(status)) {
5325 		WMA_LOGE("%s: Failed to extract obss info", __func__);
5326 		qdf_mem_free(obss_detection);
5327 		return -EINVAL;
5328 	}
5329 
5330 	if (!wma_is_vdev_valid(obss_detection->vdev_id)) {
5331 		WMA_LOGE("%s: Invalid vdev id %d", __func__,
5332 			 obss_detection->vdev_id);
5333 		qdf_mem_free(obss_detection);
5334 		return -EINVAL;
5335 	}
5336 
5337 	wma_send_msg(wma, WMA_OBSS_DETECTION_INFO, obss_detection, 0);
5338 
5339 	return 0;
5340 }
5341 
5342 int wma_vdev_bss_color_collision_info_handler(void *handle,
5343 					      uint8_t *event,
5344 					      uint32_t len)
5345 {
5346 	tp_wma_handle wma = (tp_wma_handle) handle;
5347 	struct wmi_obss_color_collision_info *obss_color_info;
5348 	QDF_STATUS status;
5349 
5350 	if (!event) {
5351 		WMA_LOGE("Invalid obss_color_collision event buffer");
5352 		return -EINVAL;
5353 	}
5354 
5355 	obss_color_info = qdf_mem_malloc(sizeof(*obss_color_info));
5356 	if (!obss_color_info) {
5357 		WMA_LOGE("%s: Failed to malloc", __func__);
5358 		return -ENOMEM;
5359 	}
5360 
5361 	status = wmi_unified_extract_obss_color_collision_info(wma->wmi_handle,
5362 							       event,
5363 							       obss_color_info);
5364 
5365 	if (QDF_IS_STATUS_ERROR(status)) {
5366 		WMA_LOGE("%s: Failed to extract obss color info", __func__);
5367 		qdf_mem_free(obss_color_info);
5368 		return -EINVAL;
5369 	}
5370 
5371 	if (!wma_is_vdev_valid(obss_color_info->vdev_id)) {
5372 		WMA_LOGE("%s: Invalid vdev id %d", __func__,
5373 			 obss_color_info->vdev_id);
5374 		qdf_mem_free(obss_color_info);
5375 		return -EINVAL;
5376 	}
5377 
5378 	wma_send_msg(wma, WMA_OBSS_COLOR_COLLISION_INFO, obss_color_info, 0);
5379 
5380 	return 0;
5381 }
5382